mirror of
				https://github.com/rofafor/vdr-plugin-femon.git
				synced 2023-10-10 11:36:53 +00:00 
			
		
		
		
	Added PES assembler.
This commit is contained in:
		
							
								
								
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							@@ -368,3 +368,4 @@ VDR Plugin 'femon' Revision History
 | 
			
		||||
2009-07-xx: Version 1.7.3
 | 
			
		||||
 | 
			
		||||
- Removed OSD offset and height options.
 | 
			
		||||
- Added PES assembler.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								README
									
									
									
									
									
								
							@@ -27,9 +27,8 @@ transponder and stream information are also available in advanced display modes.
 | 
			
		||||
The plugin is based on a neat console frontend status monitor application
 | 
			
		||||
called 'femon' by Johannes Stezenbach (see DVB-apps/szap/femon.c for further
 | 
			
		||||
information). The bitrate calculation trick originates from the 'dvbstream'
 | 
			
		||||
application by Dave Chapman and the stream information routines are taken from
 | 
			
		||||
the 'libdvb' library by Metzler Brothers. The H.264 parsing routines are taken
 | 
			
		||||
from vdr-xineliboutput plugin by Petri Hintukainen.
 | 
			
		||||
application by Dave Chapman and the H.264 parsing routines are taken from
 | 
			
		||||
vdr-xineliboutput plugin by Petri Hintukainen.
 | 
			
		||||
 | 
			
		||||
Terminology:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								femonaac.c
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								femonaac.c
									
									
									
									
									
								
							@@ -10,15 +10,25 @@
 | 
			
		||||
 | 
			
		||||
#define IS_HEAAC_AUDIO(buf) (((buf)[0] == 0xFF) && (((buf)[1] & 0xF6) == 0xF0))
 | 
			
		||||
 | 
			
		||||
static unsigned int samplerates[16] =
 | 
			
		||||
unsigned int cFemonAAC::s_Samplerates[16] =
 | 
			
		||||
{
 | 
			
		||||
  96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, -1, -1, -1, -1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool getAACAudioInfo(uint8_t *buf, int len, audio_info_t *info)
 | 
			
		||||
cFemonAAC::cFemonAAC(cFemonAudioIf *audiohandler)
 | 
			
		||||
: m_AudioHandler(audiohandler)
 | 
			
		||||
{
 | 
			
		||||
  // HE-AAC audio detection, search for syncword with layer set to 0
 | 
			
		||||
  if ((len < 4) || !IS_HEAAC_AUDIO(buf))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cFemonAAC::~cFemonAAC()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cFemonAAC::processAudio(const uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  cBitStream bs(buf, len * 8);
 | 
			
		||||
 | 
			
		||||
  if (!m_AudioHandler)
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  /* ADTS Fixed Header:
 | 
			
		||||
@@ -35,41 +45,59 @@ bool getAACAudioInfo(uint8_t *buf, int len, audio_info_t *info)
 | 
			
		||||
   * emphasis                  2b only if ID == 0 (ie MPEG-4)
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  int sampling_frequency_index = (buf[2] & 0x03C) >> 2;
 | 
			
		||||
  int channel_configuration = ((buf[2] & 0x01) << 2) | ((buf[3] & 0xC0) >> 6);
 | 
			
		||||
  // skip PES header
 | 
			
		||||
  if (!PesLongEnough(len))
 | 
			
		||||
      return false;
 | 
			
		||||
  bs.skipBits(8 * PesPayloadOffset(buf));
 | 
			
		||||
 | 
			
		||||
  info->codec = AUDIO_CODEC_HEAAC;
 | 
			
		||||
  info->bitrate = AUDIO_BITRATE_RESERVED;
 | 
			
		||||
  // HE-AAC audio detection
 | 
			
		||||
  if (bs.getBits(12) != 0xFFF)                  // syncword
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  bs.skipBit();                                 // id
 | 
			
		||||
 | 
			
		||||
  // layer must be 0
 | 
			
		||||
  if (bs.getBits(2))                            // layer
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
  bs.skipBit();                                 // protection_absent
 | 
			
		||||
  bs.skipBits(2);                               // profile
 | 
			
		||||
  int sampling_frequency_index = bs.getBits(4); // sampling_frequency_index
 | 
			
		||||
  bs.skipBit();                                 // private pid
 | 
			
		||||
  int channel_configuration = bs.getBits(3);    // channel_configuration
 | 
			
		||||
 | 
			
		||||
  m_AudioHandler->SetAudioCodec(AUDIO_CODEC_HEAAC);
 | 
			
		||||
  m_AudioHandler->SetAudioBitrate(AUDIO_BITRATE_RESERVED);
 | 
			
		||||
 | 
			
		||||
  switch (channel_configuration) {
 | 
			
		||||
    case 0:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_STEREO;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_STEREO);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 1:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_JOINT_STEREO;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_JOINT_STEREO);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 2:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_DUAL;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_DUAL);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 3:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_SINGLE;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_SINGLE);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_INVALID;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_INVALID);
 | 
			
		||||
         break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (sampling_frequency_index) {
 | 
			
		||||
    case 0xC ... 0xF:
 | 
			
		||||
         info->samplingFrequency = AUDIO_SAMPLING_FREQUENCY_RESERVED;
 | 
			
		||||
         m_AudioHandler->SetAudioSamplingFrequency(AUDIO_SAMPLING_FREQUENCY_RESERVED);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
         info->samplingFrequency = samplerates[sampling_frequency_index];
 | 
			
		||||
         m_AudioHandler->SetAudioSamplingFrequency(s_Samplerates[sampling_frequency_index]);
 | 
			
		||||
         break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								femonaac.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								femonaac.h
									
									
									
									
									
								
							@@ -10,6 +10,17 @@
 | 
			
		||||
 | 
			
		||||
#include "femonaudio.h"
 | 
			
		||||
 | 
			
		||||
bool getAACAudioInfo(uint8_t *buf, int len, audio_info_t *info);
 | 
			
		||||
class cFemonAAC {
 | 
			
		||||
private:
 | 
			
		||||
  cFemonAudioIf *m_AudioHandler;
 | 
			
		||||
 | 
			
		||||
  static unsigned int s_Samplerates[16];
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cFemonAAC(cFemonAudioIf *audiohandler);
 | 
			
		||||
  virtual ~cFemonAAC();
 | 
			
		||||
 | 
			
		||||
  bool processAudio(const uint8_t *buf, int len);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__FEMONAAC_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										149
									
								
								femonac3.c
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								femonac3.c
									
									
									
									
									
								
							@@ -9,107 +9,74 @@
 | 
			
		||||
#include "femontools.h"
 | 
			
		||||
#include "femonac3.h"
 | 
			
		||||
 | 
			
		||||
#define IS_AC3_DATA(buf) (((buf)[0] == 0x0b) && ((buf)[1] == 0x77))
 | 
			
		||||
 | 
			
		||||
static unsigned int ac3_bitrates[32] =
 | 
			
		||||
unsigned int cFemonAC3::s_Bitrates[32] =
 | 
			
		||||
{
 | 
			
		||||
  32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static unsigned int ac3_freq[4] =
 | 
			
		||||
unsigned int cFemonAC3::s_Frequencies[4] =
 | 
			
		||||
{
 | 
			
		||||
  480, 441, 320, 0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//static unsigned int ac3_frames[3][32] =
 | 
			
		||||
//{
 | 
			
		||||
//  {64, 80,  96,  112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,  896,  1024, 1152, 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 | 
			
		||||
//  {69, 87,  104, 121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835,  975,  1114, 1253, 1393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 | 
			
		||||
//  {96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960, 1152, 1344, 1536, 1728, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 | 
			
		||||
//};
 | 
			
		||||
 | 
			
		||||
bool getAC3AudioInfo(uint8_t *buf, int len, ac3_info_t *info)
 | 
			
		||||
unsigned int cFemonAC3::s_Frames[3][32] =
 | 
			
		||||
{
 | 
			
		||||
  if (!IS_AC3_DATA(buf) || (len < 8))
 | 
			
		||||
  {64, 80,  96,  112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,  896,  1024, 1152, 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 | 
			
		||||
  {69, 87,  104, 121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835,  975,  1114, 1253, 1393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 | 
			
		||||
  {96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960, 1152, 1344, 1536, 1728, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
cFemonAC3::cFemonAC3(cFemonAC3If *audiohandler)
 | 
			
		||||
: m_AudioHandler(audiohandler)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cFemonAC3::~cFemonAC3()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cFemonAC3::processAudio(const uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  cBitStream bs(buf, len * 8);
 | 
			
		||||
 | 
			
		||||
  if (!m_AudioHandler)
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  uint8_t *data = buf + 2;
 | 
			
		||||
  uint8_t frame = (uint8_t)(data[2] & 0x3f);
 | 
			
		||||
  info->bitrate = 1000 * ac3_bitrates[frame >> 1];
 | 
			
		||||
  uint8_t fr = (data[2] & 0xc0 ) >> 6;
 | 
			
		||||
  //uint8_t sz = ac3_frames[fr][frame >> 1];
 | 
			
		||||
  //if ((frame & 1) && (fr == 1))
 | 
			
		||||
  //   sz++;
 | 
			
		||||
  //sz <<= 1;
 | 
			
		||||
  info->samplingFrequency = 100 * ac3_freq[fr];
 | 
			
		||||
  info->bitstreamMode = (data[3] & 7);
 | 
			
		||||
  int acm = (data[4] & 0xE0) >> 5;
 | 
			
		||||
  info->audioCodingMode = acm;
 | 
			
		||||
  if ((acm & 0x01) && (acm != 0x01)) {
 | 
			
		||||
     // 3 front channels
 | 
			
		||||
     info->centerMixLevel = (data[4] & 0x18) >> 3;
 | 
			
		||||
     if (acm & 0x04) {
 | 
			
		||||
        // a surround channel exists
 | 
			
		||||
        info->surroundMixLevel = (data[4] & 0x06) >> 1;
 | 
			
		||||
        if (acm == 0x02) {
 | 
			
		||||
           // if in 2/0 mode
 | 
			
		||||
           info->dolbySurroundMode = ((data[4] & 0x01) << 1) | ((data[5] & 0x80) >> 7);
 | 
			
		||||
           info->lfe = (data[5] & 0x40) >> 6;
 | 
			
		||||
           info->dialogLevel = (data[5] & 0x3e) >> 1;
 | 
			
		||||
           }
 | 
			
		||||
        else {
 | 
			
		||||
           info->dolbySurroundMode = AUDIO_DOLBY_SURROUND_MODE_INVALID;
 | 
			
		||||
           info->lfe = (data[4] & 0x01);
 | 
			
		||||
           info->dialogLevel = (data[5] & 0xF8) >> 3;
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     else {
 | 
			
		||||
        info->surroundMixLevel = AUDIO_SURROUND_MIX_LEVEL_INVALID;
 | 
			
		||||
        if (acm == 0x02) {
 | 
			
		||||
           // if in 2/0 mode
 | 
			
		||||
            info->dolbySurroundMode = (data[4] & 0x06) >> 1;
 | 
			
		||||
            info->lfe = (data[4] & 0x01);
 | 
			
		||||
            info->dialogLevel = (data[5] & 0xF8) >> 3;
 | 
			
		||||
           }
 | 
			
		||||
        else {
 | 
			
		||||
           info->dolbySurroundMode = AUDIO_DOLBY_SURROUND_MODE_INVALID;
 | 
			
		||||
           info->lfe = (data[4] & 0x04) >> 2;
 | 
			
		||||
           info->dialogLevel = (data[4] & 0x03) << 3 | ((data[5] & 0xE0) >> 5);
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
  else {
 | 
			
		||||
     info->centerMixLevel = AUDIO_CENTER_MIX_LEVEL_INVALID;
 | 
			
		||||
     if (acm & 0x04) {
 | 
			
		||||
        // a surround channel exists
 | 
			
		||||
        info->surroundMixLevel = (data[4] & 0x18) >> 3;
 | 
			
		||||
        if (acm == 0x02) {
 | 
			
		||||
           // if in 2/0 mode
 | 
			
		||||
           info->dolbySurroundMode = (data[4] & 0x06) >> 1;
 | 
			
		||||
           info->lfe = (data[4] & 0x01);
 | 
			
		||||
           info->dialogLevel = (data[5] & 0xF8) >> 3;
 | 
			
		||||
           }
 | 
			
		||||
        else {
 | 
			
		||||
           info->dolbySurroundMode = AUDIO_DOLBY_SURROUND_MODE_INVALID;
 | 
			
		||||
           info->lfe = (data[4] & 0x04) >> 2;
 | 
			
		||||
           info->dialogLevel = (data[4] & 0x03) << 3 | ((data[5] & 0xE0) >> 5);
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     else {
 | 
			
		||||
        info->surroundMixLevel = AUDIO_SURROUND_MIX_LEVEL_INVALID;
 | 
			
		||||
        if (acm == 0x02) {
 | 
			
		||||
           // if in 2/0 mode
 | 
			
		||||
           info->dolbySurroundMode = (data[4] & 0x18) >> 3;
 | 
			
		||||
           info->lfe = (data[4] & 0x04) >> 2;
 | 
			
		||||
           info->dialogLevel = (data[4] & 0x03) << 3 | ((data[5] & 0xE0) >> 5);
 | 
			
		||||
           }
 | 
			
		||||
        else {
 | 
			
		||||
           info->dolbySurroundMode = AUDIO_DOLBY_SURROUND_MODE_INVALID;
 | 
			
		||||
           info->lfe = (data[4] & 0x10) >> 4;
 | 
			
		||||
           info->dialogLevel = ((data[4] & 0x0F) << 1) | ((data[5] & 0x80) >> 7);
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
     
 | 
			
		||||
  // skip PES header
 | 
			
		||||
  if (!PesLongEnough(len))
 | 
			
		||||
      return false;
 | 
			
		||||
  bs.skipBits(8 * PesPayloadOffset(buf));
 | 
			
		||||
 | 
			
		||||
  // http://rmworkshop.com/dvd_info/related_info/ac3hdr.htm
 | 
			
		||||
 | 
			
		||||
  // AC3 audio detection
 | 
			
		||||
  if (bs.getU16() != 0x0B77)        // syncword
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  bs.skipBits(16);                  // CRC1
 | 
			
		||||
 | 
			
		||||
  uint8_t fscod = bs.getBits(2);    // sampling rate values
 | 
			
		||||
  uint8_t frmsizcod = bs.getBits(6);// frame size code
 | 
			
		||||
 | 
			
		||||
  m_AudioHandler->SetAC3Bitrate(1000 * s_Bitrates[frmsizcod >> 1]);
 | 
			
		||||
  m_AudioHandler->SetAC3SamplingFrequency(100 * s_Frequencies[fscod]);
 | 
			
		||||
 | 
			
		||||
  bs.skipBits(5);                   // bitstream id
 | 
			
		||||
  int bsmod = bs.getBits(3);        // bitstream mode
 | 
			
		||||
  int acmod = bs.getBits(3);        // audio coding mode
 | 
			
		||||
 | 
			
		||||
  m_AudioHandler->SetAC3Bitstream(bsmod);
 | 
			
		||||
  m_AudioHandler->SetAC3AudioCoding(acmod);
 | 
			
		||||
 | 
			
		||||
  // 3 front channels
 | 
			
		||||
  m_AudioHandler->SetAC3CenterMix(((acmod & 0x01) && (acmod != 0x01)) ? bs.getBits(2) : AUDIO_CENTER_MIX_LEVEL_INVALID);
 | 
			
		||||
  // if a surround channel exists
 | 
			
		||||
  m_AudioHandler->SetAC3SurroundMix((acmod & 0x04) ? bs.getBits(2) : AUDIO_SURROUND_MIX_LEVEL_INVALID);
 | 
			
		||||
  // if in 2/0 mode
 | 
			
		||||
  m_AudioHandler->SetAC3DolbySurround((acmod == 0x02) ? bs.getBits(2) : AUDIO_DOLBY_SURROUND_MODE_INVALID);
 | 
			
		||||
 | 
			
		||||
  m_AudioHandler->SetAC3LFE(bs.getBit());       // low frequency effects on
 | 
			
		||||
  m_AudioHandler->SetAC3Dialog(bs.getBits(5));  // dialog normalization
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								femonac3.h
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								femonac3.h
									
									
									
									
									
								
							@@ -10,6 +10,19 @@
 | 
			
		||||
 | 
			
		||||
#include "femonaudio.h"
 | 
			
		||||
 | 
			
		||||
bool getAC3AudioInfo(uint8_t *buf, int len, ac3_info_t *info);
 | 
			
		||||
class cFemonAC3 {
 | 
			
		||||
private:
 | 
			
		||||
  cFemonAC3If *m_AudioHandler;
 | 
			
		||||
 | 
			
		||||
  static unsigned int s_Bitrates[32];
 | 
			
		||||
  static unsigned int s_Frequencies[4];
 | 
			
		||||
  static unsigned int s_Frames[3][32];
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cFemonAC3(cFemonAC3If *audiohandler);
 | 
			
		||||
  virtual ~cFemonAC3();
 | 
			
		||||
 | 
			
		||||
  bool processAudio(const uint8_t *buf, int len);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__FEMONAC3_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								femonaudio.h
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								femonaudio.h
									
									
									
									
									
								
							@@ -106,4 +106,44 @@ typedef struct ac3_info {
 | 
			
		||||
  bool        lfe;               // boolean
 | 
			
		||||
} ac3_info_t;
 | 
			
		||||
 | 
			
		||||
class cFemonAudioIf {
 | 
			
		||||
public:
 | 
			
		||||
  cFemonAudioIf() {}
 | 
			
		||||
  virtual ~cFemonAudioIf() {}
 | 
			
		||||
 | 
			
		||||
  // enum
 | 
			
		||||
  virtual void SetAudioCodec(eAudioCodec codec) = 0;
 | 
			
		||||
  // kbit/s or eAudioBitrate
 | 
			
		||||
  virtual void SetAudioBitrate(double bitrate) = 0;
 | 
			
		||||
  // Hz or eAudioSamplingFrequency
 | 
			
		||||
  virtual void SetAudioSamplingFrequency(int sampling) = 0;
 | 
			
		||||
  // eAudioChannelMode
 | 
			
		||||
  virtual void SetAudioChannel(eAudioChannelMode mode) = 0;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cFemonAC3If {
 | 
			
		||||
public:
 | 
			
		||||
  cFemonAC3If() {}
 | 
			
		||||
  virtual ~cFemonAC3If() {}
 | 
			
		||||
 | 
			
		||||
  // bit/s or eAudioBitrate
 | 
			
		||||
  virtual void SetAC3Bitrate(int bitrate) = 0;
 | 
			
		||||
  // Hz or eAudioSamplingFrequency
 | 
			
		||||
  virtual void SetAC3SamplingFrequency(int sampling) = 0;
 | 
			
		||||
  // 0..7 or eAudioBitstreamMode
 | 
			
		||||
  virtual void SetAC3Bitstream(int mode) = 0;
 | 
			
		||||
  // 0..7 or eAudioCodingMode
 | 
			
		||||
  virtual void SetAC3AudioCoding(int mode) = 0;
 | 
			
		||||
  // eAudioDolbySurroundMode
 | 
			
		||||
  virtual void SetAC3DolbySurround(int mode) = 0;
 | 
			
		||||
  // eAudioCenterMixLevel
 | 
			
		||||
  virtual void SetAC3CenterMix(int level) = 0;
 | 
			
		||||
  // eAudioSurroundMixLevel
 | 
			
		||||
  virtual void SetAC3SurroundMix(int level) = 0;
 | 
			
		||||
  // -dB
 | 
			
		||||
  virtual void SetAC3Dialog(int level) = 0;
 | 
			
		||||
  // boolean
 | 
			
		||||
  virtual void SetAC3LFE(bool onoff) = 0;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__FEMONAUDIO_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										247
									
								
								femonh264.c
									
									
									
									
									
								
							
							
						
						
									
										247
									
								
								femonh264.c
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * The original NAL SPS parsing and bitstream functions are taken from
 | 
			
		||||
 * vdr-xineliboutput plugin by Petri Hintukainen. 
 | 
			
		||||
 * vdr-xineliboutput plugin by Petri Hintukainen.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "femontools.h"
 | 
			
		||||
@@ -71,105 +71,32 @@ typedef struct {
 | 
			
		||||
   eVideoScan scan;
 | 
			
		||||
} h264_sei_data_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  const uint8_t *data;
 | 
			
		||||
  int            count; // bits
 | 
			
		||||
  int            index; // bits
 | 
			
		||||
} br_state;
 | 
			
		||||
 | 
			
		||||
#define BR_INIT(data, bytes)  { (data), 8 * (bytes), 0 }
 | 
			
		||||
#define BR_EOF(br)            ((br)->index >= (br)->count)
 | 
			
		||||
#define br_skip_bit(br)       br_skip_bits(br,1)
 | 
			
		||||
#define br_get_u8(br)         br_get_bits(br, 8)
 | 
			
		||||
#define br_get_u16(br)        ((br_get_bits(br, 8) << 8) | br_get_bits(br, 8))
 | 
			
		||||
#define br_skip_ue_golomb(br) br_skip_golomb(br)
 | 
			
		||||
#define br_skip_se_golomb(br) br_skip_golomb(br)
 | 
			
		||||
 | 
			
		||||
static inline void br_init(br_state *br, const uint8_t *data, int bytes)
 | 
			
		||||
{
 | 
			
		||||
  br->data  = data;
 | 
			
		||||
  br->count = 8 * bytes;
 | 
			
		||||
  br->index = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int br_get_bit(br_state *br)
 | 
			
		||||
{
 | 
			
		||||
  if (br->index >= br->count)
 | 
			
		||||
    return 1; // -> no infinite colomb's ...
 | 
			
		||||
 | 
			
		||||
  int r = (br->data[br->index >> 3] >> (7 - (br->index & 7))) & 1;
 | 
			
		||||
  br->index++;
 | 
			
		||||
  return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint32_t br_get_bits(br_state *br, uint32_t n)
 | 
			
		||||
{
 | 
			
		||||
  uint32_t r = 0;
 | 
			
		||||
  while (n--)
 | 
			
		||||
    r = r | (br_get_bit(br) << n);
 | 
			
		||||
  return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void br_skip_bits(br_state *br, int n)
 | 
			
		||||
{
 | 
			
		||||
  br->index += n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint32_t br_get_ue_golomb(br_state *br)
 | 
			
		||||
{
 | 
			
		||||
  int n = 0;
 | 
			
		||||
  while (!br_get_bit(br) && (n < 32))
 | 
			
		||||
    n++;
 | 
			
		||||
  return n ? ((1 << n) - 1) + br_get_bits(br, n) : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int32_t br_get_se_golomb(br_state *br)
 | 
			
		||||
{
 | 
			
		||||
  uint32_t r = br_get_ue_golomb(br) + 1;
 | 
			
		||||
  return (r & 1) ? -(r >> 1) : (r >> 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void br_skip_golomb(br_state *br)
 | 
			
		||||
{
 | 
			
		||||
  int n = 0;
 | 
			
		||||
  while (!br_get_bit(br) && (n < 32))
 | 
			
		||||
    n++;
 | 
			
		||||
  br_skip_bits(br, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void br_byte_align(br_state *br)
 | 
			
		||||
{
 | 
			
		||||
  int n = br->index % 8;
 | 
			
		||||
  if (n > 0)
 | 
			
		||||
     br_skip_bits(br, 8 - n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps)
 | 
			
		||||
{
 | 
			
		||||
  br_state br = BR_INIT(buf, len);
 | 
			
		||||
  int profile_idc, pic_order_cnt_type;
 | 
			
		||||
  int frame_mbs_only;
 | 
			
		||||
  int i, j;
 | 
			
		||||
  cBitStream bs(buf, len);
 | 
			
		||||
 | 
			
		||||
  profile_idc = bs.getU8();
 | 
			
		||||
 | 
			
		||||
  profile_idc = br_get_u8(&br);
 | 
			
		||||
  
 | 
			
		||||
  //Dprintf("H.264 SPS: profile_idc %d", profile_idc);
 | 
			
		||||
  
 | 
			
		||||
  br_skip_bits(&br, 16);
 | 
			
		||||
  br_skip_ue_golomb(&br);            // seq_parameter_set_id
 | 
			
		||||
 | 
			
		||||
  bs.skipBits(16);
 | 
			
		||||
  bs.skipUeGolomb();                        // seq_parameter_set_id
 | 
			
		||||
  if (profile_idc >= 100) {
 | 
			
		||||
     if (br_get_ue_golomb(&br) == 3) // chroma_format_idc
 | 
			
		||||
        br_skip_bit(&br);            // residual_colour_transform_flag
 | 
			
		||||
     br_skip_ue_golomb(&br);         // bit_depth_luma - 8
 | 
			
		||||
     br_skip_ue_golomb(&br);         // bit_depth_chroma - 8
 | 
			
		||||
     br_skip_bit(&br);               // transform_bypass
 | 
			
		||||
     if (br_get_bit(&br)) {          // seq_scaling_matrix_present
 | 
			
		||||
        for (i = 0; i < 8; i++) {  
 | 
			
		||||
            if (br_get_bit(&br)) {   // seq_scaling_list_present
 | 
			
		||||
     if (bs.getUeGolomb() == 3)             // chroma_format_idc
 | 
			
		||||
        bs.skipBit();                       // residual_colour_transform_flag
 | 
			
		||||
     bs.skipUeGolomb();                     // bit_depth_luma - 8
 | 
			
		||||
     bs.skipUeGolomb();                     // bit_depth_chroma - 8
 | 
			
		||||
     bs.skipBit();                          // transform_bypass
 | 
			
		||||
     if (bs.getBit()) {                     // seq_scaling_matrix_present
 | 
			
		||||
        for (i = 0; i < 8; i++) {
 | 
			
		||||
            if (bs.getBit()) {              // seq_scaling_list_present
 | 
			
		||||
               int last = 8, next = 8, size = (i < 6) ? 16 : 64;
 | 
			
		||||
               for (j = 0; j < size; j++) {
 | 
			
		||||
                   if (next)
 | 
			
		||||
                      next = (last + br_get_se_golomb(&br)) & 0xff;
 | 
			
		||||
                      next = (last + bs.getSeGolomb()) & 0xff;
 | 
			
		||||
                   last = next ?: last;
 | 
			
		||||
                   }
 | 
			
		||||
               }
 | 
			
		||||
@@ -177,23 +104,23 @@ static bool h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps)
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
  br_skip_ue_golomb(&br);            // log2_max_frame_num - 4
 | 
			
		||||
  pic_order_cnt_type = br_get_ue_golomb(&br);
 | 
			
		||||
  bs.skipUeGolomb();                        // log2_max_frame_num - 4
 | 
			
		||||
  pic_order_cnt_type = bs.getUeGolomb();
 | 
			
		||||
  if (pic_order_cnt_type == 0)
 | 
			
		||||
     br_skip_ue_golomb(&br);         // log2_max_poc_lsb - 4
 | 
			
		||||
     bs.skipUeGolomb();                     // log2_max_poc_lsb - 4
 | 
			
		||||
  else if (pic_order_cnt_type == 1) {
 | 
			
		||||
     br_skip_bit(&br);               // delta_pic_order_always_zero
 | 
			
		||||
     br_skip_se_golomb(&br);         // offset_for_non_ref_pic
 | 
			
		||||
     br_skip_se_golomb(&br);         // offset_for_top_to_bottom_field
 | 
			
		||||
     j = br_get_ue_golomb(&br);      // num_ref_frames_in_pic_order_cnt_cycle
 | 
			
		||||
     bs.skipBit();                          // delta_pic_order_always_zero
 | 
			
		||||
     bs.skipSeGolomb();                     // offset_for_non_ref_pic
 | 
			
		||||
     bs.skipSeGolomb();                     // offset_for_top_to_bottom_field
 | 
			
		||||
     j = bs.getUeGolomb();                  // num_ref_frames_in_pic_order_cnt_cycle
 | 
			
		||||
     for (i = 0; i < j; i++)
 | 
			
		||||
         br_skip_se_golomb(&br);     // offset_for_ref_frame[i]
 | 
			
		||||
         bs.skipSeGolomb();                 // offset_for_ref_frame[i]
 | 
			
		||||
     }
 | 
			
		||||
  br_skip_ue_golomb(&br);            // ref_frames
 | 
			
		||||
  br_skip_bit(&br);                  // gaps_in_frame_num_allowed
 | 
			
		||||
  sps->width      = br_get_ue_golomb(&br) + 1; // mbs
 | 
			
		||||
  sps->height     = br_get_ue_golomb(&br) + 1; // mbs
 | 
			
		||||
  frame_mbs_only  = br_get_bit(&br);
 | 
			
		||||
  bs.skipUeGolomb();                        // ref_frames
 | 
			
		||||
  bs.skipBit();                             // gaps_in_frame_num_allowed
 | 
			
		||||
  sps->width      = bs.getUeGolomb() + 1;   // mbs
 | 
			
		||||
  sps->height     = bs.getUeGolomb() + 1;   // mbs
 | 
			
		||||
  frame_mbs_only  = bs.getBit();
 | 
			
		||||
 | 
			
		||||
  //Dprintf("H.264 SPS: pic_width:  %u mbs", (unsigned int)sps->width);
 | 
			
		||||
  //Dprintf("H.264 SPS: pic_height: %u mbs", (unsigned int)sps->height);
 | 
			
		||||
@@ -203,22 +130,22 @@ static bool h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps)
 | 
			
		||||
  sps->height *= 16 * (2 - frame_mbs_only);
 | 
			
		||||
 | 
			
		||||
  if (!frame_mbs_only) {
 | 
			
		||||
    if (br_get_bit(&br)) {           // mb_adaptive_frame_field_flag
 | 
			
		||||
    if (bs.getBit()) {                      // mb_adaptive_frame_field_flag
 | 
			
		||||
       //Dprintf("H.264 SPS: MBAFF");
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  br_skip_bit(&br);                  // direct_8x8_inference_flag
 | 
			
		||||
  if (br_get_bit(&br)) {             // frame_cropping_flag
 | 
			
		||||
    uint32_t crop_left   = br_get_ue_golomb(&br);
 | 
			
		||||
    uint32_t crop_right  = br_get_ue_golomb(&br);
 | 
			
		||||
    uint32_t crop_top    = br_get_ue_golomb(&br);
 | 
			
		||||
    uint32_t crop_bottom = br_get_ue_golomb(&br);
 | 
			
		||||
  bs.skipBit();                             // direct_8x8_inference_flag
 | 
			
		||||
  if (bs.getBit()) {                        // frame_cropping_flag
 | 
			
		||||
    uint32_t crop_left   = bs.getUeGolomb();
 | 
			
		||||
    uint32_t crop_right  = bs.getUeGolomb();
 | 
			
		||||
    uint32_t crop_top    = bs.getUeGolomb();
 | 
			
		||||
    uint32_t crop_bottom = bs.getUeGolomb();
 | 
			
		||||
    //Dprintf("H.264 SPS: cropping %d %d %d %d", crop_left, crop_top, crop_right, crop_bottom);
 | 
			
		||||
 | 
			
		||||
    sps->width -= 2 * (crop_left + crop_right);
 | 
			
		||||
    if (frame_mbs_only)
 | 
			
		||||
       sps->height -= 2 * (crop_top + crop_bottom); 
 | 
			
		||||
       sps->height -= 2 * (crop_top + crop_bottom);
 | 
			
		||||
    else
 | 
			
		||||
       sps->height -= 4 * (crop_top + crop_bottom);
 | 
			
		||||
    }
 | 
			
		||||
@@ -226,13 +153,13 @@ static bool h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps)
 | 
			
		||||
  // VUI parameters
 | 
			
		||||
  sps->aspect_ratio = VIDEO_ASPECT_RATIO_INVALID;
 | 
			
		||||
  sps->format = VIDEO_FORMAT_INVALID;
 | 
			
		||||
  if (br_get_bit(&br)) {             // vui_parameters_present_flag
 | 
			
		||||
     if (br_get_bit(&br)) {          // aspect_ratio_info_present
 | 
			
		||||
        uint32_t aspect_ratio_idc = br_get_u8(&br);
 | 
			
		||||
  if (bs.getBit()) {                        // vui_parameters_present_flag
 | 
			
		||||
     if (bs.getBit()) {                     // aspect_ratio_info_present
 | 
			
		||||
        uint32_t aspect_ratio_idc = bs.getU8();
 | 
			
		||||
        //Dprintf("H.264 SPS: aspect_ratio_idc %d", aspect_ratio_idc);
 | 
			
		||||
        if (aspect_ratio_idc == 255) { // extended sar
 | 
			
		||||
           br_skip_bit(&br);           // sar_width
 | 
			
		||||
           br_skip_bit(&br);           // sar_height
 | 
			
		||||
        if (aspect_ratio_idc == 255) {      // extended sar
 | 
			
		||||
           bs.skipBit();                    // sar_width
 | 
			
		||||
           bs.skipBit();                    // sar_height
 | 
			
		||||
           sps->aspect_ratio = VIDEO_ASPECT_RATIO_EXTENDED;
 | 
			
		||||
           //Dprintf("H.264 SPS: aspect ratio extended");
 | 
			
		||||
           }
 | 
			
		||||
@@ -241,10 +168,10 @@ static bool h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps)
 | 
			
		||||
           //Dprintf("H.264 SPS: -> aspect ratio %d", sps->aspect_ratio);
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     if (br_get_bit(&br))            // overscan_info_present_flag
 | 
			
		||||
        br_skip_bit(&br);            // overscan_approriate_flag
 | 
			
		||||
     if (br_get_bit(&br)) {          // video_signal_type_present_flag
 | 
			
		||||
        uint32_t video_format = br_get_bits(&br, 3);
 | 
			
		||||
     if (bs.getBit())                       // overscan_info_present_flag
 | 
			
		||||
        bs.skipBit();                       // overscan_approriate_flag
 | 
			
		||||
     if (bs.getBit()) {                     // video_signal_type_present_flag
 | 
			
		||||
        uint32_t video_format = bs.getBits(3);
 | 
			
		||||
        if (video_format < sizeof(video_formats) / sizeof(video_formats[0])) {
 | 
			
		||||
           sps->format = video_formats[video_format];
 | 
			
		||||
           //Dprintf("H.264 SPS: -> video format %d", sps->format);
 | 
			
		||||
@@ -254,38 +181,38 @@ static bool h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps)
 | 
			
		||||
 | 
			
		||||
  //Dprintf("H.264 SPS: -> video size %dx%d, aspect %d", sps->width, sps->height, sps->aspect_ratio);
 | 
			
		||||
 | 
			
		||||
  if (BR_EOF(&br)) {
 | 
			
		||||
  if (bs.isEOF()) {
 | 
			
		||||
     //Dprintf("H.264 SPS: not enough data ?");
 | 
			
		||||
     return false;
 | 
			
		||||
     }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool h264_parse_sei(const uint8_t *buf, int len, h264_sei_data_t *sei)
 | 
			
		||||
{
 | 
			
		||||
  int num_referenced_subseqs, i;
 | 
			
		||||
  br_state br = BR_INIT(buf, len);
 | 
			
		||||
  cBitStream bs(buf, len);
 | 
			
		||||
 | 
			
		||||
  while (!BR_EOF(&br)) { // sei_message
 | 
			
		||||
  while (!bs.isEOF()) { // sei_message
 | 
			
		||||
    int lastByte, payloadSize = 0, payloadType = 0;
 | 
			
		||||
 | 
			
		||||
    // last_payload_type_byte
 | 
			
		||||
    do {
 | 
			
		||||
       lastByte = br_get_u8(&br) & 0xFF;
 | 
			
		||||
       lastByte = bs.getU8() & 0xFF;
 | 
			
		||||
       payloadType += lastByte;
 | 
			
		||||
    } while (lastByte == 0xFF);
 | 
			
		||||
 | 
			
		||||
    // last_payload_size_byte
 | 
			
		||||
    do {
 | 
			
		||||
       lastByte = br_get_u8(&br) & 0xFF;
 | 
			
		||||
       lastByte = bs.getU8() & 0xFF;
 | 
			
		||||
       payloadSize += lastByte;
 | 
			
		||||
    } while (lastByte == 0xFF);
 | 
			
		||||
 | 
			
		||||
    switch (payloadType) {                             // sei_payload
 | 
			
		||||
      //case 1:                                        // pic_timing
 | 
			
		||||
      //     ...
 | 
			
		||||
      //     switch (br_get_bits(&br, 2)) {            // ct_type
 | 
			
		||||
      //     switch (bs.getBits(2)) {                    // ct_type
 | 
			
		||||
      //       case 0:
 | 
			
		||||
      //            sei->scan = VIDEO_SCAN_PROGRESSIVE;
 | 
			
		||||
      //            break;
 | 
			
		||||
@@ -301,32 +228,32 @@ static bool h264_parse_sei(const uint8_t *buf, int len, h264_sei_data_t *sei)
 | 
			
		||||
      //       }
 | 
			
		||||
      //     break;
 | 
			
		||||
 | 
			
		||||
      case 12:                                         // sub_seq_characteristics
 | 
			
		||||
           br_skip_ue_golomb(&br);                     // sub_seq_layer_num
 | 
			
		||||
           br_skip_ue_golomb(&br);                     // sub_seq_id
 | 
			
		||||
           if (br_get_bit(&br))                        // duration_flag
 | 
			
		||||
              br_skip_bits(&br, 32);                   // sub_seq_duration
 | 
			
		||||
           if (br_get_bit(&br)) {                      // average_rate_flag
 | 
			
		||||
              br_skip_bit(&br);                        // accurate_statistics_flag
 | 
			
		||||
              sei->bitrate = br_get_u16(&br);          // average_bit_rate
 | 
			
		||||
              sei->frame_rate = br_get_u16(&br);       // average_frame_rate
 | 
			
		||||
      case 12:                                          // sub_seq_characteristics
 | 
			
		||||
           bs.skipUeGolomb();                           // sub_seq_layer_num
 | 
			
		||||
           bs.skipUeGolomb();                           // sub_seq_id
 | 
			
		||||
           if (bs.getBit())                             // duration_flag
 | 
			
		||||
              bs.skipBits(32);                          // sub_seq_duration
 | 
			
		||||
           if (bs.getBit()) {                           // average_rate_flag
 | 
			
		||||
              bs.skipBit();                             // accurate_statistics_flag
 | 
			
		||||
              sei->bitrate = bs.getU16();               // average_bit_rate
 | 
			
		||||
              sei->frame_rate = bs.getU16();            // average_frame_rate
 | 
			
		||||
              //Dprintf("H.264 SEI: -> stream bitrate %.1f, frame rate %.1f", sei->bitrate, sei->frame_rate);
 | 
			
		||||
              }
 | 
			
		||||
           num_referenced_subseqs = br_get_ue_golomb(&br); // num_referenced_subseqs
 | 
			
		||||
           num_referenced_subseqs = bs.getUeGolomb();   // num_referenced_subseqs
 | 
			
		||||
           for (i = 0; i < num_referenced_subseqs; ++i) {
 | 
			
		||||
               br_skip_ue_golomb(&br);                 // ref_sub_seq_layer_num
 | 
			
		||||
               br_skip_ue_golomb(&br);                 // ref_sub_seq_id
 | 
			
		||||
               br_get_bit(&br);                        // ref_sub_seq_direction
 | 
			
		||||
               bs.skipUeGolomb();                       // ref_sub_seq_layer_num
 | 
			
		||||
               bs.skipUeGolomb();                       // ref_sub_seq_id
 | 
			
		||||
               bs.getBit();                             // ref_sub_seq_direction
 | 
			
		||||
               }
 | 
			
		||||
           break;
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
           br_skip_bits(&br, payloadSize);
 | 
			
		||||
           bs.skipBits(payloadSize);
 | 
			
		||||
           break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    // force byte align
 | 
			
		||||
    br_byte_align(&br);
 | 
			
		||||
    bs.byteAlign();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
@@ -350,7 +277,7 @@ static int h264_nal_unescape(uint8_t *dst, const uint8_t *src, int len)
 | 
			
		||||
       }
 | 
			
		||||
    dst[d++] = src[s++];
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
  return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -370,10 +297,27 @@ static int h264_get_picture_type(const uint8_t *buf, int len)
 | 
			
		||||
  return NO_PICTURE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool getH264VideoInfo(uint8_t *buf, int len, video_info_t *info)
 | 
			
		||||
cFemonH264::cFemonH264(cFemonVideoIf *videohandler)
 | 
			
		||||
: m_VideoHandler(videohandler)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cFemonH264::~cFemonH264()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cFemonH264::processVideo(const uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  bool sps_found = false, sei_found = true; // sei currently disabled
 | 
			
		||||
 | 
			
		||||
  if (!m_VideoHandler)
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  // skip PES header
 | 
			
		||||
  if (!PesLongEnough(len))
 | 
			
		||||
      return false;
 | 
			
		||||
  buf += PesPayloadOffset(buf);
 | 
			
		||||
 | 
			
		||||
  // H.264 detection, search for NAL AUD
 | 
			
		||||
  if (!IS_NAL_AUD(buf))
 | 
			
		||||
     return false;
 | 
			
		||||
@@ -382,7 +326,7 @@ bool getH264VideoInfo(uint8_t *buf, int len, video_info_t *info)
 | 
			
		||||
  if (h264_get_picture_type(buf, len) != I_FRAME)
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  info->codec = VIDEO_CODEC_H264;
 | 
			
		||||
  m_VideoHandler->SetVideoCodec(VIDEO_CODEC_H264);
 | 
			
		||||
 | 
			
		||||
  // Scan video packet ...
 | 
			
		||||
  for (int i = 5; i < len - 4; i++) {
 | 
			
		||||
@@ -394,10 +338,9 @@ bool getH264VideoInfo(uint8_t *buf, int len, video_info_t *info)
 | 
			
		||||
         if (0 < (nal_len = h264_nal_unescape(nal_data, buf + i + 4, len - i - 4))) {
 | 
			
		||||
            h264_sps_data_t sps = { 0, 0, VIDEO_ASPECT_RATIO_INVALID, VIDEO_FORMAT_INVALID };
 | 
			
		||||
            if (h264_parse_sps(nal_data, nal_len, &sps)) {
 | 
			
		||||
               info->format = sps.format;
 | 
			
		||||
               info->width = sps.width;
 | 
			
		||||
               info->height = sps.height;
 | 
			
		||||
               info->aspectRatio = sps.aspect_ratio;
 | 
			
		||||
               m_VideoHandler->SetVideoFormat(sps.format);
 | 
			
		||||
               m_VideoHandler->SetVideoSize(sps.width, sps.height);
 | 
			
		||||
               m_VideoHandler->SetVideoAspectRatio(sps.aspect_ratio);
 | 
			
		||||
               sps_found = true;
 | 
			
		||||
               }
 | 
			
		||||
            }
 | 
			
		||||
@@ -410,9 +353,9 @@ bool getH264VideoInfo(uint8_t *buf, int len, video_info_t *info)
 | 
			
		||||
         if (0 < (nal_len = h264_nal_unescape(nal_data, buf + i + 4, len - i - 4))) {
 | 
			
		||||
            h264_sei_data_t sei = { 0, 0, VIDEO_SCAN_INVALID };
 | 
			
		||||
            if (h264_parse_sei(nal_data, nal_len, &sei)) {
 | 
			
		||||
               info->frameRate = sei.frame_rate;
 | 
			
		||||
               info->bitrate = sei.bitrate;
 | 
			
		||||
               info->scan = sei.scan;
 | 
			
		||||
               m_VideoHandler->SetVideoFramerate(sei.frame_rate);
 | 
			
		||||
               m_VideoHandler->SetVideoBitrate(sei.bitrate);
 | 
			
		||||
               m_VideoHandler->SetVideoScan(sei.scan);
 | 
			
		||||
               sei_found = true;
 | 
			
		||||
               }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								femonh264.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								femonh264.h
									
									
									
									
									
								
							@@ -10,6 +10,15 @@
 | 
			
		||||
 | 
			
		||||
#include "femonvideo.h"
 | 
			
		||||
 | 
			
		||||
bool getH264VideoInfo(uint8_t *buf, int len, video_info_t *info);
 | 
			
		||||
class cFemonH264 {
 | 
			
		||||
private:
 | 
			
		||||
  cFemonVideoIf *m_VideoHandler;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cFemonH264(cFemonVideoIf *videohandler);
 | 
			
		||||
  virtual ~cFemonH264();
 | 
			
		||||
 | 
			
		||||
  bool processVideo(const uint8_t *buf, int len);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__FEMONH264_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										278
									
								
								femonmpeg.c
									
									
									
									
									
								
							
							
						
						
									
										278
									
								
								femonmpeg.c
									
									
									
									
									
								
							@@ -8,10 +8,9 @@
 | 
			
		||||
#include "femontools.h"
 | 
			
		||||
#include "femonmpeg.h"
 | 
			
		||||
 | 
			
		||||
#define IS_MPEG_AUDIO(buf)      (((buf)[0] == 0xFF) && ((buf)[1] & 0xF0))
 | 
			
		||||
#define IS_SEQUENCE_HEADER(buf) (((buf)[0] == 0x00) && ((buf)[1] == 0x00) && ((buf)[2] == 0x01) && ((buf)[3] == 0xB3))
 | 
			
		||||
#define IS_EXTENSION_START(buf) (((buf)[0] == 0x00) && ((buf)[1] == 0x00) && ((buf)[2] == 0x01) && ((buf)[3] == 0xB5))
 | 
			
		||||
 | 
			
		||||
static unsigned int bitrates[2][3][16] =
 | 
			
		||||
unsigned int cFemonMPEG::s_Bitrates[2][3][16] =
 | 
			
		||||
{
 | 
			
		||||
  {
 | 
			
		||||
    {0,  32,  48,  56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, -1}, // MPEG-2 Layer I
 | 
			
		||||
@@ -25,160 +24,263 @@ static unsigned int bitrates[2][3][16] =
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static unsigned int samplerates[2][4] =
 | 
			
		||||
unsigned int cFemonMPEG::s_Samplerates[2][4] =
 | 
			
		||||
{
 | 
			
		||||
  {22050, 24000, 16000, -1}, // MPEG-2
 | 
			
		||||
  {44100, 48000, 32000, -1}  // MPEG-1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static eAudioCodec formats[2][4] =
 | 
			
		||||
eAudioCodec cFemonMPEG::s_Formats[2][4] =
 | 
			
		||||
{
 | 
			
		||||
  {AUDIO_CODEC_MPEG2_I, AUDIO_CODEC_MPEG2_II, AUDIO_CODEC_MPEG2_III, AUDIO_CODEC_UNKNOWN}, // MPEG-2
 | 
			
		||||
  {AUDIO_CODEC_MPEG1_I, AUDIO_CODEC_MPEG1_II, AUDIO_CODEC_MPEG1_III, AUDIO_CODEC_UNKNOWN}  // MPEG-1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool getMPEGAudioInfo(uint8_t *buf, int len, audio_info_t *info)
 | 
			
		||||
cFemonMPEG::cFemonMPEG(cFemonVideoIf *videohandler, cFemonAudioIf *audiohandler)
 | 
			
		||||
: m_VideoHandler(videohandler),
 | 
			
		||||
  m_AudioHandler(audiohandler)
 | 
			
		||||
{
 | 
			
		||||
  // MPEG audio detection, search for syncword
 | 
			
		||||
  if ((len < 4) || !IS_MPEG_AUDIO(buf))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cFemonMPEG::~cFemonMPEG()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cFemonMPEG::processAudio(const uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  cBitStream bs(buf, len * 8);
 | 
			
		||||
 | 
			
		||||
  if (!m_AudioHandler)
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  int mpegIndex = (buf[1] & 0x08) >> 3;        // MPEG-2=0, MPEG-1=1
 | 
			
		||||
  int layerIndex = 3 - ((buf[1] & 0x06) >> 1); // I=11, II=10, III=01 
 | 
			
		||||
  int bitrateIndex = (buf[2] & 0xF0) >> 4;
 | 
			
		||||
  int frequency = (buf[2] & 0x0C) >> 2;
 | 
			
		||||
  int channelMode = (buf[3] & 0xC0) >> 6;
 | 
			
		||||
  // skip PES header
 | 
			
		||||
  if (!PesLongEnough(len))
 | 
			
		||||
      return false;
 | 
			
		||||
  bs.skipBits(8 * PesPayloadOffset(buf));
 | 
			
		||||
 | 
			
		||||
  info->codec = formats[mpegIndex][layerIndex];
 | 
			
		||||
  // MPEG audio detection
 | 
			
		||||
  if (bs.getBits(12) != 0xFFF)              // syncword
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  switch (channelMode) {
 | 
			
		||||
  int id = bs.getBit();                     // id: MPEG-2=0, MPEG-1=1
 | 
			
		||||
  int layer = 3 - bs.getBits(2);            // layer: I=11, II=10, III=01
 | 
			
		||||
  bs.skipBit();                             // protection bit
 | 
			
		||||
  int bit_rate_index = bs.getBits(4);       // bitrate index
 | 
			
		||||
  int sampling_frequency = bs.getBits(2);   // sampling frequency
 | 
			
		||||
  bs.skipBit();                             // padding bit
 | 
			
		||||
  bs.skipBit();                             // private pid
 | 
			
		||||
  int mode = bs.getBits(2);                 // mode
 | 
			
		||||
 | 
			
		||||
  m_AudioHandler->SetAudioCodec(s_Formats[id][layer]);
 | 
			
		||||
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
    case 0:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_STEREO;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_STEREO);
 | 
			
		||||
         break;
 | 
			
		||||
         
 | 
			
		||||
 | 
			
		||||
    case 1:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_JOINT_STEREO;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_JOINT_STEREO);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 2:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_DUAL;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_DUAL);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 3:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_SINGLE;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_SINGLE);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
         info->channelMode = AUDIO_CHANNEL_MODE_INVALID;
 | 
			
		||||
         m_AudioHandler->SetAudioChannel(AUDIO_CHANNEL_MODE_INVALID);
 | 
			
		||||
         break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (bitrateIndex) {
 | 
			
		||||
  switch (bit_rate_index) {
 | 
			
		||||
    case 0:
 | 
			
		||||
         info->bitrate = AUDIO_BITRATE_FREE;
 | 
			
		||||
         m_AudioHandler->SetAudioBitrate(AUDIO_BITRATE_FREE);
 | 
			
		||||
         break;
 | 
			
		||||
         
 | 
			
		||||
 | 
			
		||||
    case 0xF:
 | 
			
		||||
         info->bitrate = AUDIO_BITRATE_RESERVED;
 | 
			
		||||
         m_AudioHandler->SetAudioBitrate(AUDIO_BITRATE_RESERVED);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
         info->bitrate = 1000 * bitrates[mpegIndex][layerIndex][bitrateIndex];
 | 
			
		||||
         m_AudioHandler->SetAudioBitrate(1000 * s_Bitrates[id][layer][bit_rate_index]);
 | 
			
		||||
         break;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  switch (frequency) {
 | 
			
		||||
 | 
			
		||||
  switch (sampling_frequency) {
 | 
			
		||||
    case 3:
 | 
			
		||||
         info->samplingFrequency = AUDIO_SAMPLING_FREQUENCY_RESERVED;
 | 
			
		||||
         m_AudioHandler->SetAudioSamplingFrequency(AUDIO_SAMPLING_FREQUENCY_RESERVED);
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
         info->samplingFrequency = samplerates[mpegIndex][frequency];
 | 
			
		||||
         m_AudioHandler->SetAudioSamplingFrequency(s_Samplerates[id][sampling_frequency]);
 | 
			
		||||
         break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool getMPEGVideoInfo(uint8_t *buf, int len, video_info_t *info)
 | 
			
		||||
bool cFemonMPEG::processVideo(const uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  // MPEG-2 video detection, search for sequence header
 | 
			
		||||
  if ((len < 7) || !IS_SEQUENCE_HEADER(buf))
 | 
			
		||||
  cBitStream bs(buf, len * 8);
 | 
			
		||||
 | 
			
		||||
  if (!m_VideoHandler)
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  // Parse header   
 | 
			
		||||
  uint8_t *data = buf + 4;
 | 
			
		||||
  info->codec = VIDEO_CODEC_MPEG2;
 | 
			
		||||
  info->width = ((data[1] & 0xF0) >> 4) | (data[0] << 4);
 | 
			
		||||
  info->height = ((data[1] & 0x0F) << 8) | (data[2]);
 | 
			
		||||
  switch ((data[3] & 0xF0) >> 4) {
 | 
			
		||||
  // skip PES header
 | 
			
		||||
  if (!PesLongEnough(len))
 | 
			
		||||
      return false;
 | 
			
		||||
  bs.skipBits(8 * PesPayloadOffset(buf));
 | 
			
		||||
 | 
			
		||||
  // MPEG-2 video detection, search for start code
 | 
			
		||||
  if (bs.getU32() != 0x000001B3)            // sequence header
 | 
			
		||||
     return false;
 | 
			
		||||
 | 
			
		||||
  int scan = VIDEO_SCAN_UNKNOWN;
 | 
			
		||||
  int format = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
  int aspect = VIDEO_ASPECT_RATIO_RESERVED;
 | 
			
		||||
 | 
			
		||||
  int horizontal_size = bs.getBits(12);     // horizontal size value
 | 
			
		||||
  int vertical_size = bs.getBits(12);       // vertical size value
 | 
			
		||||
 | 
			
		||||
  switch (bs.getBits(4)) {                  // aspect ratio information
 | 
			
		||||
    case 1:
 | 
			
		||||
      info->aspectRatio = VIDEO_ASPECT_RATIO_1_1;
 | 
			
		||||
      break;
 | 
			
		||||
         aspect = VIDEO_ASPECT_RATIO_1_1;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 2:
 | 
			
		||||
      info->aspectRatio = VIDEO_ASPECT_RATIO_4_3;
 | 
			
		||||
      break;
 | 
			
		||||
         aspect = VIDEO_ASPECT_RATIO_4_3;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 3:
 | 
			
		||||
      info->aspectRatio = VIDEO_ASPECT_RATIO_16_9;
 | 
			
		||||
      break;
 | 
			
		||||
         aspect = VIDEO_ASPECT_RATIO_16_9;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 4:
 | 
			
		||||
      info->aspectRatio = VIDEO_ASPECT_RATIO_2_21_1;
 | 
			
		||||
      break;
 | 
			
		||||
         aspect = VIDEO_ASPECT_RATIO_2_21_1;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 5 ... 15:
 | 
			
		||||
    default:
 | 
			
		||||
      info->aspectRatio = VIDEO_ASPECT_RATIO_RESERVED;
 | 
			
		||||
      break;
 | 
			
		||||
         aspect = VIDEO_ASPECT_RATIO_RESERVED;
 | 
			
		||||
         break;
 | 
			
		||||
    }
 | 
			
		||||
  // Video scan should be read from progressive_sequence field in sequence extension
 | 
			
		||||
  switch (data[3] & 0x0F) {
 | 
			
		||||
 | 
			
		||||
  double frame_rate = 0;
 | 
			
		||||
  switch (bs.getBits(4)) {                  // frame rate code
 | 
			
		||||
    case 1:
 | 
			
		||||
      info->frameRate   = 24000 / 1001.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_PROGRESSIVE;
 | 
			
		||||
      info->format      = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 24000 / 1001.0;
 | 
			
		||||
         format = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 2:
 | 
			
		||||
      info->frameRate   = 24.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_PROGRESSIVE;
 | 
			
		||||
      info->format      = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 24.0;
 | 
			
		||||
         format = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 3:
 | 
			
		||||
      info->frameRate   = 25.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_UNKNOWN;  // interlaced or progressive
 | 
			
		||||
      info->format      = VIDEO_FORMAT_PAL;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 25.0;
 | 
			
		||||
         format = VIDEO_FORMAT_PAL;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 4:
 | 
			
		||||
      info->frameRate   = 30000 / 1001.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_UNKNOWN; // interlaced or progressive
 | 
			
		||||
      info->format      = VIDEO_FORMAT_NTSC;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 30000 / 1001.0;
 | 
			
		||||
         format = VIDEO_FORMAT_NTSC;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 5:
 | 
			
		||||
      info->frameRate   = 30.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_UNKNOWN;  // interlaced or progressive
 | 
			
		||||
      info->format      = VIDEO_FORMAT_NTSC;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 30.0;
 | 
			
		||||
         format = VIDEO_FORMAT_NTSC;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 6:
 | 
			
		||||
      info->frameRate   = 50.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_PROGRESSIVE;
 | 
			
		||||
      info->format      = VIDEO_FORMAT_PAL;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 50.0;
 | 
			
		||||
         format = VIDEO_FORMAT_PAL;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 7:
 | 
			
		||||
      info->frameRate   = 60.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_PROGRESSIVE;
 | 
			
		||||
      info->format      = VIDEO_FORMAT_NTSC;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 60.0;
 | 
			
		||||
         format = VIDEO_FORMAT_NTSC;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 8:
 | 
			
		||||
      info->frameRate   = 60000 / 1001.0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_PROGRESSIVE;
 | 
			
		||||
      info->format      = VIDEO_FORMAT_NTSC;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 60000 / 1001.0;
 | 
			
		||||
         format = VIDEO_FORMAT_NTSC;
 | 
			
		||||
         break;
 | 
			
		||||
 | 
			
		||||
    case 9 ... 15:
 | 
			
		||||
    default:
 | 
			
		||||
      info->frameRate   = 0;
 | 
			
		||||
      info->scan        = VIDEO_SCAN_UNKNOWN;
 | 
			
		||||
      info->format      = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
      break;
 | 
			
		||||
         frame_rate = 0;
 | 
			
		||||
         format = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
         break;
 | 
			
		||||
    }
 | 
			
		||||
  info->bitrate = 400.0 * (double)(((data[4] << 10) & 0x0003FC00UL) | ((data[5] << 2) & 0x000003FCUL) | (((data[6] & 0xC0) >> 6) & 0x00000003UL));
 | 
			
		||||
 | 
			
		||||
  int bit_rate = bs.getBits(18);            // bit rate value
 | 
			
		||||
 | 
			
		||||
  bs.skipBit();             // marker bit
 | 
			
		||||
  bs.skipBits(10);          // vbv buffer size value
 | 
			
		||||
  bs.skipBit();             // constrained parameters value
 | 
			
		||||
  if (bs.getBit())          // load intra quantizer matrix
 | 
			
		||||
     bs.skipBits(8 * 64);   // intra quantizer matrix
 | 
			
		||||
  if (bs.getBit())          // load non-intra quantizer matrix
 | 
			
		||||
     bs.skipBits(8 * 64);   // non-intra quantizer matrix
 | 
			
		||||
 | 
			
		||||
  if (bs.getU32() != 0x000001B5) {                  // extension start
 | 
			
		||||
     bs.skipBits(4);                                // extension start code identifier
 | 
			
		||||
     bs.skipBits(8);                                // profile and level indicator
 | 
			
		||||
     scan = bs.getBit() ? VIDEO_SCAN_PROGRESSIVE :
 | 
			
		||||
                          VIDEO_SCAN_INTERLACED;    // progressive sequence
 | 
			
		||||
     bs.skipBits(2);                                // chroma format
 | 
			
		||||
     horizontal_size |= (bs.getBits(2) << 12);      // horizontal size extension
 | 
			
		||||
     vertical_size |= (bs.getBits(2) << 12);        // vertical size extension
 | 
			
		||||
     bit_rate |= (bs.getBits(12) << 18);            // bit rate extension
 | 
			
		||||
     bs.skipBit();                                  // marker bit
 | 
			
		||||
     bs.skipBits(8);                                // vpv buffer size extension
 | 
			
		||||
     bs.skipBit();                                  // low delay
 | 
			
		||||
     bs.skipBits(2);                                // frame rate extension n
 | 
			
		||||
     bs.skipBits(5);                                // frame rate extension d
 | 
			
		||||
 | 
			
		||||
     if ((bs.getU32() != 0x000001B5) &&             // extension start code
 | 
			
		||||
         (bs.getBits(4) == 0x0010)) {               // sequence display extension id
 | 
			
		||||
        switch (bs.getBits(3)) {                    // video format
 | 
			
		||||
          case 0x000:
 | 
			
		||||
               format = VIDEO_FORMAT_COMPONENT;
 | 
			
		||||
               break;
 | 
			
		||||
          case 0x001:
 | 
			
		||||
               format = VIDEO_FORMAT_PAL;
 | 
			
		||||
               break;
 | 
			
		||||
          case 0x010:
 | 
			
		||||
               format = VIDEO_FORMAT_NTSC;
 | 
			
		||||
               break;
 | 
			
		||||
          case 0x011:
 | 
			
		||||
               format = VIDEO_FORMAT_SECAM;
 | 
			
		||||
               break;
 | 
			
		||||
          case 0x100:
 | 
			
		||||
               format = VIDEO_FORMAT_MAC;
 | 
			
		||||
               break;
 | 
			
		||||
          case 0x101:
 | 
			
		||||
               format = VIDEO_FORMAT_UNKNOWN;
 | 
			
		||||
               break;
 | 
			
		||||
          case 0x110:
 | 
			
		||||
          case 0x111:
 | 
			
		||||
               format = VIDEO_FORMAT_RESERVED;
 | 
			
		||||
               break;
 | 
			
		||||
          default:
 | 
			
		||||
               format = VIDEO_FORMAT_INVALID;
 | 
			
		||||
               break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
  m_VideoHandler->SetVideoCodec(VIDEO_CODEC_MPEG2);
 | 
			
		||||
  m_VideoHandler->SetVideoSize(horizontal_size, vertical_size);
 | 
			
		||||
  m_VideoHandler->SetVideoBitrate(400.0 * (double)(bit_rate));
 | 
			
		||||
  m_VideoHandler->SetVideoFramerate(frame_rate);
 | 
			
		||||
  m_VideoHandler->SetVideoScan(eVideoScan(scan));
 | 
			
		||||
  m_VideoHandler->SetVideoAspectRatio(eVideoAspectRatio(aspect));
 | 
			
		||||
  m_VideoHandler->SetVideoFormat(eVideoFormat(format));
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								femonmpeg.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								femonmpeg.h
									
									
									
									
									
								
							@@ -8,10 +8,24 @@
 | 
			
		||||
#ifndef __FEMONMPEG_H
 | 
			
		||||
#define __FEMONMPEG_H
 | 
			
		||||
 | 
			
		||||
#include "femonaudio.h"
 | 
			
		||||
#include "femonvideo.h"
 | 
			
		||||
#include "femonaudio.h"
 | 
			
		||||
 | 
			
		||||
bool getMPEGAudioInfo(uint8_t *buf, int len, audio_info_t *info);
 | 
			
		||||
bool getMPEGVideoInfo(uint8_t *buf, int len, video_info_t *info);
 | 
			
		||||
class cFemonMPEG {
 | 
			
		||||
private:
 | 
			
		||||
  cFemonVideoIf *m_VideoHandler;
 | 
			
		||||
  cFemonAudioIf *m_AudioHandler;
 | 
			
		||||
 | 
			
		||||
  static unsigned int s_Bitrates[2][3][16];
 | 
			
		||||
  static unsigned int s_Samplerates[2][4];
 | 
			
		||||
  static eAudioCodec  s_Formats[2][4];
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cFemonMPEG(cFemonVideoIf *videohandler, cFemonAudioIf *audiohandler);
 | 
			
		||||
  virtual ~cFemonMPEG();
 | 
			
		||||
 | 
			
		||||
  bool processVideo(const uint8_t *buf, int len);
 | 
			
		||||
  bool processAudio(const uint8_t *buf, int len);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__FEMONMPEG_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										152
									
								
								femonreceiver.c
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								femonreceiver.c
									
									
									
									
									
								
							@@ -8,38 +8,29 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include "femontools.h"
 | 
			
		||||
#include "femoncfg.h"
 | 
			
		||||
#include "femonmpeg.h"
 | 
			
		||||
#include "femonaac.h"
 | 
			
		||||
#include "femonac3.h"
 | 
			
		||||
#include "femonh264.h"
 | 
			
		||||
#include "femonreceiver.h"
 | 
			
		||||
 | 
			
		||||
#define TS_SIZE       188
 | 
			
		||||
#define PAY_START     0x40
 | 
			
		||||
#define ADAPT_FIELD   0x20
 | 
			
		||||
#define PAYLOAD       0x10
 | 
			
		||||
#define PTS_DTS_FLAGS 0xC0
 | 
			
		||||
 | 
			
		||||
cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[], int Dpid[])
 | 
			
		||||
: cReceiver(ChannelID, -1, Vpid, Apid, Dpid, NULL),
 | 
			
		||||
  cThread("femon receiver"),
 | 
			
		||||
  m_Sleep(),
 | 
			
		||||
  m_Active(false),
 | 
			
		||||
  m_DetectH264(this),
 | 
			
		||||
  m_DetectMPEG(this, this),
 | 
			
		||||
  m_DetectAAC(this),
 | 
			
		||||
  m_DetectAC3(this),
 | 
			
		||||
  m_VideoPid(Vpid),
 | 
			
		||||
  m_VideoPacketCount(0),
 | 
			
		||||
  m_VideoBitrate(0.0),
 | 
			
		||||
  m_VideoValid(false),
 | 
			
		||||
  m_VideoInfoBufferIndex(0),
 | 
			
		||||
  m_AudioPid(Apid[0]),
 | 
			
		||||
  m_AudioPacketCount(0),
 | 
			
		||||
  m_AudioBitrate(0.0),
 | 
			
		||||
  m_AudioValid(false),
 | 
			
		||||
  m_AudioInfoBufferIndex(0),
 | 
			
		||||
  m_AC3Pid(Dpid[0]),
 | 
			
		||||
  m_AC3PacketCount(0), 
 | 
			
		||||
  m_AC3Bitrate(0),
 | 
			
		||||
  m_AC3Valid(false),
 | 
			
		||||
  m_AC3InfoBufferIndex(0)
 | 
			
		||||
  m_AC3Valid(false)
 | 
			
		||||
{
 | 
			
		||||
  Dprintf("%s()\n", __PRETTY_FUNCTION__);
 | 
			
		||||
 | 
			
		||||
@@ -51,16 +42,10 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[
 | 
			
		||||
  m_VideoInfo.height = 0;
 | 
			
		||||
  m_VideoInfo.frameRate = 0;
 | 
			
		||||
  m_VideoInfo.bitrate = AUDIO_BITRATE_INVALID;
 | 
			
		||||
  for (unsigned int i = 0; i < ELEMENTS(m_VideoInfoBuffer); ++i)
 | 
			
		||||
      memcpy(&m_VideoInfoBuffer[i], &m_VideoInfo, sizeof(video_info_t));
 | 
			
		||||
 | 
			
		||||
  m_AudioInfo.codec = AUDIO_CODEC_UNKNOWN;
 | 
			
		||||
  m_AudioInfo.bitrate = AUDIO_BITRATE_INVALID;
 | 
			
		||||
  m_AudioInfo.samplingFrequency = AUDIO_SAMPLING_FREQUENCY_INVALID;
 | 
			
		||||
  m_AudioInfo.channelMode = AUDIO_CHANNEL_MODE_INVALID;
 | 
			
		||||
  for (unsigned int i = 0; i < ELEMENTS(m_AudioInfoBuffer); ++i)
 | 
			
		||||
      memcpy(&m_AudioInfoBuffer[i], &m_AudioInfo, sizeof(audio_info_t));
 | 
			
		||||
 | 
			
		||||
  m_AC3Info.bitrate = AUDIO_BITRATE_INVALID;
 | 
			
		||||
  m_AC3Info.samplingFrequency = AUDIO_SAMPLING_FREQUENCY_INVALID;
 | 
			
		||||
  m_AC3Info.bitstreamMode = AUDIO_BITSTREAM_MODE_INVALID;
 | 
			
		||||
@@ -70,8 +55,6 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[
 | 
			
		||||
  m_AC3Info.surroundMixLevel = AUDIO_SURROUND_MIX_LEVEL_INVALID;
 | 
			
		||||
  m_AC3Info.dialogLevel = 0;
 | 
			
		||||
  m_AC3Info.lfe = false;
 | 
			
		||||
  for (unsigned int i = 0; i < ELEMENTS(m_AC3InfoBuffer); ++i)
 | 
			
		||||
      memcpy(&m_AC3InfoBuffer[i], &m_AC3Info, sizeof(ac3_info_t));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cFemonReceiver::~cFemonReceiver(void)
 | 
			
		||||
@@ -92,84 +75,6 @@ void cFemonReceiver::Deactivate(void)
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cFemonReceiver::GetVideoInfo(uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  int c = 0;
 | 
			
		||||
 | 
			
		||||
  while (c < len) {
 | 
			
		||||
    video_info_t tmp;
 | 
			
		||||
    uint8_t *b = buf + c;
 | 
			
		||||
    if (getMPEGVideoInfo(b, len - c, &tmp) || getH264VideoInfo(b, len - c, &tmp)) {
 | 
			
		||||
       bool coherent = true;
 | 
			
		||||
       memcpy(&m_VideoInfoBuffer[m_VideoInfoBufferIndex], &tmp, sizeof(video_info_t));
 | 
			
		||||
       m_VideoInfoBufferIndex = (m_VideoInfoBufferIndex + 1) % ELEMENTS(m_VideoInfoBuffer);
 | 
			
		||||
       for (unsigned int i = 1; i < ELEMENTS(m_VideoInfoBuffer); ++i) {
 | 
			
		||||
           if (memcmp(&m_VideoInfoBuffer[0], &m_VideoInfoBuffer[i], sizeof(video_info_t)))
 | 
			
		||||
              coherent = false;
 | 
			
		||||
              break;
 | 
			
		||||
           }
 | 
			
		||||
       if (!m_VideoValid || coherent) {
 | 
			
		||||
          m_VideoValid = true;
 | 
			
		||||
          memcpy(&m_VideoInfo, &m_VideoInfoBuffer[0], sizeof(video_info_t));
 | 
			
		||||
          }
 | 
			
		||||
       return;
 | 
			
		||||
       }
 | 
			
		||||
    c++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cFemonReceiver::GetAudioInfo(uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  int c = 0;
 | 
			
		||||
 | 
			
		||||
  while (c < len) {
 | 
			
		||||
    audio_info_t tmp;
 | 
			
		||||
    uint8_t *b = buf + c;
 | 
			
		||||
    if (getAACAudioInfo(b, len - c, &tmp) || getMPEGAudioInfo(b, len - c, &tmp)) {
 | 
			
		||||
       bool coherent = true;
 | 
			
		||||
       memcpy(&m_AudioInfoBuffer[m_AudioInfoBufferIndex], &tmp, sizeof(audio_info_t));
 | 
			
		||||
       m_AudioInfoBufferIndex = (m_AudioInfoBufferIndex + 1) % ELEMENTS(m_AudioInfoBuffer);
 | 
			
		||||
       for (unsigned int i = 1; i < ELEMENTS(m_AudioInfoBuffer); ++i) {
 | 
			
		||||
           if (memcmp(&m_AudioInfoBuffer[0], &m_AudioInfoBuffer[i], sizeof(audio_info_t)))
 | 
			
		||||
              coherent = false;
 | 
			
		||||
              break;
 | 
			
		||||
           }
 | 
			
		||||
       if (!m_AudioValid || coherent) {
 | 
			
		||||
          m_AudioValid = true;
 | 
			
		||||
          memcpy(&m_AudioInfo, &m_AudioInfoBuffer[0], sizeof(audio_info_t));
 | 
			
		||||
          }
 | 
			
		||||
       return;
 | 
			
		||||
       }
 | 
			
		||||
    c++;
 | 
			
		||||
    }	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cFemonReceiver::GetAC3Info(uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
  int c = 0;
 | 
			
		||||
 | 
			
		||||
  while (c < len) {
 | 
			
		||||
    ac3_info_t tmp;
 | 
			
		||||
    uint8_t *b = buf + c;
 | 
			
		||||
    if (getAC3AudioInfo(b, len - c, &tmp)) {
 | 
			
		||||
       bool coherent = true;
 | 
			
		||||
       memcpy(&m_AC3InfoBuffer[m_AC3InfoBufferIndex], &tmp, sizeof(ac3_info_t));
 | 
			
		||||
       m_AC3InfoBufferIndex = (m_AC3InfoBufferIndex + 1) % ELEMENTS(m_AC3InfoBuffer);
 | 
			
		||||
       for (unsigned int i = 1; i < ELEMENTS(m_AC3InfoBuffer); ++i) {
 | 
			
		||||
           if (memcmp(&m_AC3InfoBuffer[0], &m_AC3InfoBuffer[i], sizeof(ac3_info_t)))
 | 
			
		||||
              coherent = false;
 | 
			
		||||
              break;
 | 
			
		||||
           }
 | 
			
		||||
       if (!m_AC3Valid || coherent) {
 | 
			
		||||
          m_AC3Valid = true;
 | 
			
		||||
          memcpy(&m_AC3Info, &m_AC3InfoBuffer[0], sizeof(ac3_info_t));
 | 
			
		||||
          }   
 | 
			
		||||
       return;
 | 
			
		||||
       }
 | 
			
		||||
    c++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cFemonReceiver::Activate(bool On)
 | 
			
		||||
{
 | 
			
		||||
  Dprintf("%s(%d)\n", __PRETTY_FUNCTION__, On);
 | 
			
		||||
@@ -183,41 +88,38 @@ void cFemonReceiver::Receive(uchar *Data, int Length)
 | 
			
		||||
{
 | 
			
		||||
  // TS packet length: TS_SIZE
 | 
			
		||||
  if (Length == TS_SIZE) {
 | 
			
		||||
     int pid = ((Data[1] & 0x1f) << 8) | (Data[2]);
 | 
			
		||||
     int len, pid = TsPid(Data);
 | 
			
		||||
     if (pid == m_VideoPid) {
 | 
			
		||||
        m_VideoPacketCount++;
 | 
			
		||||
        if (TsPayloadStart(Data)) {
 | 
			
		||||
           while (const uint8_t *p = m_VideoAssembler.GetPes(len)) {
 | 
			
		||||
             if (m_DetectMPEG.processVideo(p, len) || m_DetectH264.processVideo(p, len)) {
 | 
			
		||||
                m_VideoValid = true;
 | 
			
		||||
                break;
 | 
			
		||||
                }
 | 
			
		||||
             }
 | 
			
		||||
           m_VideoAssembler.Reset();
 | 
			
		||||
         }
 | 
			
		||||
         m_VideoAssembler.PutTs(Data, Length);
 | 
			
		||||
        }
 | 
			
		||||
     else if (pid == m_AudioPid) {
 | 
			
		||||
        m_AudioPacketCount++;
 | 
			
		||||
        if (const uint8_t *p = m_AudioAssembler.GetPes(len)) {
 | 
			
		||||
           if (m_DetectAAC.processAudio(p, len) || m_DetectMPEG.processAudio(p, len))
 | 
			
		||||
              m_AudioValid = true;
 | 
			
		||||
           m_AudioAssembler.Reset();
 | 
			
		||||
           }
 | 
			
		||||
        m_AudioAssembler.PutTs(Data, Length);
 | 
			
		||||
        }
 | 
			
		||||
     else if (pid == m_AC3Pid) {
 | 
			
		||||
        m_AC3PacketCount++;
 | 
			
		||||
        }
 | 
			
		||||
     /* the following originates from libdvbmpeg: */
 | 
			
		||||
     if (!(Data[3] & PAYLOAD)) {
 | 
			
		||||
        return;
 | 
			
		||||
        }
 | 
			
		||||
     uint8_t off = 0;
 | 
			
		||||
     if (Data[3] & ADAPT_FIELD) {
 | 
			
		||||
        off = (uint8_t)(Data[4] + 1);
 | 
			
		||||
        }
 | 
			
		||||
     if (Data[1] & PAY_START) {
 | 
			
		||||
        uint8_t *sb = Data + 4 + off;
 | 
			
		||||
        if (sb[7] & PTS_DTS_FLAGS) {
 | 
			
		||||
           uint8_t *pay = sb + sb[8] + 9; 
 | 
			
		||||
           int l = TS_SIZE - 13 - off - sb[8];
 | 
			
		||||
           if (pid == m_VideoPid) {
 | 
			
		||||
              GetVideoInfo(pay, l);
 | 
			
		||||
              }
 | 
			
		||||
           else if (pid == m_AudioPid) {
 | 
			
		||||
              GetAudioInfo(pay, l);
 | 
			
		||||
              }
 | 
			
		||||
           else if (pid == m_AC3Pid) {
 | 
			
		||||
              GetAC3Info(pay, l);
 | 
			
		||||
              }
 | 
			
		||||
        if (const uint8_t *p = m_AC3Assembler.GetPes(len)) {
 | 
			
		||||
           if (m_DetectAC3.processAudio(p, len))
 | 
			
		||||
              m_AC3Valid = true;
 | 
			
		||||
           m_AC3Assembler.Reset();
 | 
			
		||||
           }
 | 
			
		||||
        m_AC3Assembler.PutTs(Data, Length);
 | 
			
		||||
        }
 | 
			
		||||
     /* end */
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,47 +11,75 @@
 | 
			
		||||
#include <vdr/thread.h>
 | 
			
		||||
#include <vdr/receiver.h>
 | 
			
		||||
 | 
			
		||||
#include "femonh264.h"
 | 
			
		||||
#include "femonmpeg.h"
 | 
			
		||||
#include "femonaac.h"
 | 
			
		||||
#include "femonac3.h"
 | 
			
		||||
#include "femonaudio.h"
 | 
			
		||||
#include "femonvideo.h"
 | 
			
		||||
#include "femontools.h"
 | 
			
		||||
 | 
			
		||||
class cFemonReceiver : public cReceiver, public cThread {
 | 
			
		||||
class cFemonReceiver : public cReceiver, public cThread, public cFemonVideoIf, public cFemonAudioIf, public cFemonAC3If {
 | 
			
		||||
private:
 | 
			
		||||
  cCondWait     m_Sleep;
 | 
			
		||||
  bool          m_Active;
 | 
			
		||||
 | 
			
		||||
  cFemonH264    m_DetectH264;
 | 
			
		||||
  cFemonMPEG    m_DetectMPEG;
 | 
			
		||||
  cFemonAAC     m_DetectAAC;
 | 
			
		||||
  cFemonAC3     m_DetectAC3;
 | 
			
		||||
 | 
			
		||||
  cTsToPes      m_VideoAssembler;
 | 
			
		||||
  int           m_VideoPid;
 | 
			
		||||
  int           m_VideoPacketCount;
 | 
			
		||||
  double        m_VideoBitrate;
 | 
			
		||||
  bool          m_VideoValid;
 | 
			
		||||
  video_info_t  m_VideoInfo;
 | 
			
		||||
  video_info_t  m_VideoInfoBuffer[3];
 | 
			
		||||
  unsigned int  m_VideoInfoBufferIndex;
 | 
			
		||||
 | 
			
		||||
  cTsToPes      m_AudioAssembler;
 | 
			
		||||
  int           m_AudioPid;
 | 
			
		||||
  int           m_AudioPacketCount;
 | 
			
		||||
  double        m_AudioBitrate;
 | 
			
		||||
  bool          m_AudioValid;
 | 
			
		||||
  audio_info_t  m_AudioInfo;
 | 
			
		||||
  audio_info_t  m_AudioInfoBuffer[3];
 | 
			
		||||
  unsigned int  m_AudioInfoBufferIndex;
 | 
			
		||||
 | 
			
		||||
  cTsToPes      m_AC3Assembler;
 | 
			
		||||
  int           m_AC3Pid;
 | 
			
		||||
  int           m_AC3PacketCount;
 | 
			
		||||
  double        m_AC3Bitrate;
 | 
			
		||||
  bool          m_AC3Valid;
 | 
			
		||||
  ac3_info_t    m_AC3Info;
 | 
			
		||||
  ac3_info_t    m_AC3InfoBuffer[3];
 | 
			
		||||
  unsigned int  m_AC3InfoBufferIndex;
 | 
			
		||||
 | 
			
		||||
  void          GetVideoInfo(uint8_t *buf, int len);
 | 
			
		||||
  void          GetAudioInfo(uint8_t *buf, int len);
 | 
			
		||||
  void          GetAC3Info(uint8_t *buf, int len);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual void Activate(bool On);
 | 
			
		||||
  virtual void Receive(uchar *Data, int Length);
 | 
			
		||||
  virtual void Action(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  virtual void SetVideoCodec(eVideoCodec codec)                   { m_VideoInfo.codec       = codec; }
 | 
			
		||||
  virtual void SetVideoFormat(eVideoFormat format)                { m_VideoInfo.format      = format; }
 | 
			
		||||
  virtual void SetVideoScan(eVideoScan scan)                      { m_VideoInfo.scan        = scan; }
 | 
			
		||||
  virtual void SetVideoAspectRatio(eVideoAspectRatio aspectratio) { m_VideoInfo.aspectRatio = aspectratio; }
 | 
			
		||||
  virtual void SetVideoSize(int width, int height)                { m_VideoInfo.width       = width;
 | 
			
		||||
                                                                    m_VideoInfo.height      = height; }
 | 
			
		||||
  virtual void SetVideoFramerate(double framerate)                { m_VideoInfo.frameRate   = framerate; }
 | 
			
		||||
  virtual void SetVideoBitrate(double bitrate)                    { m_VideoInfo.bitrate     = bitrate; }
 | 
			
		||||
 | 
			
		||||
  virtual void SetAudioCodec(eAudioCodec codec)        { m_AudioInfo.codec = codec; }
 | 
			
		||||
  virtual void SetAudioBitrate(double bitrate)         { m_AudioInfo.bitrate = bitrate; }
 | 
			
		||||
  virtual void SetAudioSamplingFrequency(int sampling) { m_AudioInfo.samplingFrequency = sampling; }
 | 
			
		||||
  virtual void SetAudioChannel(eAudioChannelMode mode) { m_AudioInfo.channelMode = mode; }
 | 
			
		||||
 | 
			
		||||
  virtual void SetAC3Bitrate(int bitrate)            { m_AC3Info.bitrate = bitrate; }
 | 
			
		||||
  virtual void SetAC3SamplingFrequency(int sampling) { m_AC3Info.samplingFrequency = sampling; }
 | 
			
		||||
  virtual void SetAC3Bitstream(int mode)             { m_AC3Info.bitstreamMode = mode; }
 | 
			
		||||
  virtual void SetAC3AudioCoding(int mode)           { m_AC3Info.audioCodingMode = mode; }
 | 
			
		||||
  virtual void SetAC3DolbySurround(int mode)         { m_AC3Info.dolbySurroundMode = mode; }
 | 
			
		||||
  virtual void SetAC3CenterMix(int level)            { m_AC3Info.centerMixLevel = level; }
 | 
			
		||||
  virtual void SetAC3SurroundMix(int level)          { m_AC3Info.surroundMixLevel = level; }
 | 
			
		||||
  virtual void SetAC3Dialog(int level)               { m_AC3Info.dialogLevel = level; }
 | 
			
		||||
  virtual void SetAC3LFE(bool onoff)                 { m_AC3Info.lfe = onoff; }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[], int Dpid[]);
 | 
			
		||||
  virtual ~cFemonReceiver();
 | 
			
		||||
@@ -81,8 +109,8 @@ public:
 | 
			
		||||
  int    AC3SamplingFreq(void)      { return m_AC3Info.samplingFrequency; };   // Hz or eAudioSamplingFrequency
 | 
			
		||||
  int    AC3BitStreamMode(void)     { return m_AC3Info.bitstreamMode; };       // 0..7 or eAudioBitstreamMode
 | 
			
		||||
  int    AC3AudioCodingMode(void)   { return m_AC3Info.audioCodingMode; };     // 0..7 or eAudioCodingMode
 | 
			
		||||
  bool   AC3_2_0(void)              { return m_AC3Info.audioCodingMode == AUDIO_CODING_MODE_2_0; }; // boolean
 | 
			
		||||
  bool   AC3_5_1(void)	            { return m_AC3Info.audioCodingMode == AUDIO_CODING_MODE_3_2; }; // boolean
 | 
			
		||||
  bool   AC3_2_0(void)              { return (m_AC3Info.audioCodingMode == AUDIO_CODING_MODE_2_0); }; // boolean
 | 
			
		||||
  bool   AC3_5_1(void)	            { return (m_AC3Info.audioCodingMode == AUDIO_CODING_MODE_3_2); }; // boolean
 | 
			
		||||
  int    AC3DolbySurroundMode(void) { return m_AC3Info.dolbySurroundMode; };   // eAudioDolbySurroundMode
 | 
			
		||||
  int    AC3CenterMixLevel(void)    { return m_AC3Info.centerMixLevel; };      // eAudioCenterMixLevel
 | 
			
		||||
  int    AC3SurroundMixLevel(void)  { return m_AC3Info.surroundMixLevel; };    // eAudioSurroundMixLevel
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										86
									
								
								femontools.c
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								femontools.c
									
									
									
									
									
								
							@@ -306,7 +306,7 @@ cString getTransmission(int value)
 | 
			
		||||
{
 | 
			
		||||
  return cString::sprintf("%s", getUserString(value, TransmissionValues));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
cString getBandwidth(int value)
 | 
			
		||||
{
 | 
			
		||||
  return cString::sprintf("%s", getUserString(value, BandwidthValues));
 | 
			
		||||
@@ -522,7 +522,89 @@ cString getBitrateMbits(double value)
 | 
			
		||||
 | 
			
		||||
cString getBitrateKbits(double value)
 | 
			
		||||
{
 | 
			
		||||
  if (value > 0) 
 | 
			
		||||
  if (value > 0)
 | 
			
		||||
     return cString::sprintf("%.0f %s", value / 1000.0, tr("kbit/s"));
 | 
			
		||||
  return cString::sprintf("---");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cBitStream::cBitStream(const uint8_t *buf, const int len)
 | 
			
		||||
: data(buf),
 | 
			
		||||
  count(len),
 | 
			
		||||
  index(0)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cBitStream::~cBitStream()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cBitStream::getBit()
 | 
			
		||||
{
 | 
			
		||||
  if (index >= count)
 | 
			
		||||
     return (1); // -> no infinite colomb's ...
 | 
			
		||||
 | 
			
		||||
  int r = (data[index >> 3] >> (7 - (index & 7))) & 1;
 | 
			
		||||
  ++index;
 | 
			
		||||
 | 
			
		||||
  return (r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t cBitStream::getBits(uint32_t n)
 | 
			
		||||
{
 | 
			
		||||
  uint32_t r = 0;
 | 
			
		||||
 | 
			
		||||
  while (n--)
 | 
			
		||||
    r = (r | (getBit() << n));
 | 
			
		||||
 | 
			
		||||
  return (r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cBitStream::skipBits(uint32_t n)
 | 
			
		||||
{
 | 
			
		||||
  index += n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t cBitStream::getUeGolomb()
 | 
			
		||||
{
 | 
			
		||||
  int n = 0;
 | 
			
		||||
 | 
			
		||||
  while (!getBit() && (n < 32))
 | 
			
		||||
    n++;
 | 
			
		||||
 | 
			
		||||
  return (n ? ((1 << n) - 1) + getBits(n) : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t cBitStream::getSeGolomb()
 | 
			
		||||
{
 | 
			
		||||
  uint32_t r = getUeGolomb() + 1;
 | 
			
		||||
 | 
			
		||||
  return ((r & 1) ? -(r >> 1) : (r >> 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cBitStream::skipGolomb()
 | 
			
		||||
{
 | 
			
		||||
  int n = 0;
 | 
			
		||||
 | 
			
		||||
  while (!getBit() && (n < 32))
 | 
			
		||||
    n++;
 | 
			
		||||
 | 
			
		||||
  skipBits(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cBitStream::skipUeGolomb()
 | 
			
		||||
{
 | 
			
		||||
  skipGolomb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cBitStream::skipSeGolomb()
 | 
			
		||||
{
 | 
			
		||||
  skipGolomb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cBitStream::byteAlign()
 | 
			
		||||
{
 | 
			
		||||
  int n = index % 8;
 | 
			
		||||
 | 
			
		||||
  if (n > 0)
 | 
			
		||||
     skipBits(8 - n);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								femontools.h
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								femontools.h
									
									
									
									
									
								
							@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <vdr/channels.h>
 | 
			
		||||
#include <vdr/remux.h>
 | 
			
		||||
#include <vdr/tools.h>
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
@@ -68,4 +69,32 @@ cString getVideoBitrate(double value, double stream);
 | 
			
		||||
cString getBitrateMbits(double value);
 | 
			
		||||
cString getBitrateKbits(double value);
 | 
			
		||||
 | 
			
		||||
class cBitStream {
 | 
			
		||||
private:
 | 
			
		||||
  const uint8_t *data;
 | 
			
		||||
  int            count; // in bits
 | 
			
		||||
  int            index; // in bits
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cBitStream(const uint8_t *buf, const int len);
 | 
			
		||||
  ~cBitStream();
 | 
			
		||||
 | 
			
		||||
  int      getBit();
 | 
			
		||||
  uint32_t getBits(uint32_t n);
 | 
			
		||||
  void     skipBits(uint32_t n);
 | 
			
		||||
  uint32_t getUeGolomb();
 | 
			
		||||
  int32_t  getSeGolomb();
 | 
			
		||||
  void     skipGolomb();
 | 
			
		||||
  void     skipUeGolomb();
 | 
			
		||||
  void     skipSeGolomb();
 | 
			
		||||
  void     byteAlign();
 | 
			
		||||
  void     skipBit()      { skipBits(1); }
 | 
			
		||||
  uint32_t getU8()        { return getBits(8); }
 | 
			
		||||
  uint32_t getU16()       { return ((getBits(8) << 8) | getBits(8)); }
 | 
			
		||||
  uint32_t getU24()       { return ((getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); }
 | 
			
		||||
  uint32_t getU32()       { return ((getBits(8) << 24) | (getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); }
 | 
			
		||||
  bool     isEOF()        { return (index >= count); }
 | 
			
		||||
  void     reset()        { index = 0; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // __FEMONTOOLS_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								femonvideo.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								femonvideo.h
									
									
									
									
									
								
							@@ -69,4 +69,25 @@ typedef struct video_info {
 | 
			
		||||
  double            bitrate;     // Mbit/s
 | 
			
		||||
} video_info_t;
 | 
			
		||||
 | 
			
		||||
class cFemonVideoIf {
 | 
			
		||||
public:
 | 
			
		||||
  cFemonVideoIf() {}
 | 
			
		||||
  virtual ~cFemonVideoIf() {}
 | 
			
		||||
 | 
			
		||||
  // eVideoCodec
 | 
			
		||||
  virtual void SetVideoCodec(eVideoCodec codec) = 0;
 | 
			
		||||
  // eVideoFormat
 | 
			
		||||
  virtual void SetVideoFormat(eVideoFormat format) = 0;
 | 
			
		||||
  // eVideoScan
 | 
			
		||||
  virtual void SetVideoScan(eVideoScan scan) = 0;
 | 
			
		||||
  // eVideoAspectRatio
 | 
			
		||||
  virtual void SetVideoAspectRatio(eVideoAspectRatio aspectratio) = 0;
 | 
			
		||||
  // pixels
 | 
			
		||||
  virtual void SetVideoSize(int width, int height) = 0;
 | 
			
		||||
  // Hz
 | 
			
		||||
  virtual void SetVideoFramerate(double framerate) = 0;
 | 
			
		||||
  // Mbit/s
 | 
			
		||||
  virtual void SetVideoBitrate(double bitrate) = 0;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__FEMONVIDEO_H
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user