mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	More changes from Reinhard Nissl
This commit is contained in:
		
							
								
								
									
										186
									
								
								remux.c
									
									
									
									
									
								
							
							
						
						
									
										186
									
								
								remux.c
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ | |||||||
|  * The cDolbyRepacker code was originally written by Reinhard Nissl <rnissl@gmx.de>, |  * The cDolbyRepacker code was originally written by Reinhard Nissl <rnissl@gmx.de>, | ||||||
|  * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. |  * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. | ||||||
|  * |  * | ||||||
|  * $Id: remux.c 1.40 2005/08/27 09:03:56 kls Exp $ |  * $Id: remux.c 1.41 2005/08/28 11:23:23 kls Exp $ | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "remux.h" | #include "remux.h" | ||||||
| @@ -90,14 +90,15 @@ ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, | |||||||
|  |  | ||||||
| class cRepacker { | class cRepacker { | ||||||
| protected: | protected: | ||||||
|  |   bool initiallySyncing; | ||||||
|   int maxPacketSize; |   int maxPacketSize; | ||||||
|   uint8_t subStreamId; |   uint8_t subStreamId; | ||||||
|   static void DroppedData(const char *Reason, int Count) { esyslog("%s (dropped %d bytes)", Reason, Count); } |   static void DroppedData(const char *Reason, int Count) { esyslog("%s (dropped %d bytes)", Reason, Count); } | ||||||
| public: | public: | ||||||
|   static int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded); |   static int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded); | ||||||
|   cRepacker(void) { maxPacketSize = 6 + 65535; subStreamId = 0; } |   cRepacker(void) { initiallySyncing = true; maxPacketSize = 6 + 65535; subStreamId = 0; } | ||||||
|   virtual ~cRepacker() {} |   virtual ~cRepacker() {} | ||||||
|   virtual void Reset(void) {} |   virtual void Reset(void) { /* initiallySyncing = true; */ } | ||||||
|   virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) = 0; |   virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) = 0; | ||||||
|   virtual int BreakAt(const uchar *Data, int Count) = 0; |   virtual int BreakAt(const uchar *Data, int Count) = 0; | ||||||
|   virtual int QuerySnoopSize(void) { return 0; } |   virtual int QuerySnoopSize(void) { return 0; } | ||||||
| @@ -139,6 +140,7 @@ protected: | |||||||
|  |  | ||||||
| void cCommonRepacker::Reset(void) | void cCommonRepacker::Reset(void) | ||||||
| { | { | ||||||
|  |   cRepacker::Reset(); | ||||||
|   skippedBytes = 0; |   skippedBytes = 0; | ||||||
|   packetTodo = maxPacketSize - 6 - 3; |   packetTodo = maxPacketSize - 6 - 3; | ||||||
|   fragmentLen = 0; |   fragmentLen = 0; | ||||||
| @@ -293,16 +295,14 @@ void cVideoRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|                      // the byte count get's negative then the current buffer ends in a |                      // the byte count get's negative then the current buffer ends in a | ||||||
|                      // partitial start code that must be stripped off, as it shall be put |                      // partitial start code that must be stripped off, as it shall be put | ||||||
|                      // in the next packet. |                      // in the next packet. | ||||||
|                      if (!PushOutPacket(ResultBuffer, payload, data - 3 - payload)) { |                      PushOutPacket(ResultBuffer, payload, data - 3 - payload); | ||||||
|                         DroppedData("cVideoRepacker: result buffer overflow", Count - (done - 3)); |  | ||||||
|                         return; |  | ||||||
|                         } |  | ||||||
|                      // go on with syncing to the next picture |                      // go on with syncing to the next picture | ||||||
|                      state = syncing; |                      state = syncing; | ||||||
|                      } |                      } | ||||||
|                   if (state == syncing) { |                   if (state == syncing) { | ||||||
|                      // report that syncing dropped some bytes |                      if (initiallySyncing) // omit report for the typical initial case | ||||||
|                      if (skippedBytes > SkippedBytesLimit) |                         initiallySyncing = false; | ||||||
|  |                      else if (skippedBytes > SkippedBytesLimit) // report that syncing dropped some bytes | ||||||
|                         esyslog("cVideoRepacker: skipped %d bytes to sync on next picture", skippedBytes - SkippedBytesLimit); |                         esyslog("cVideoRepacker: skipped %d bytes to sync on next picture", skippedBytes - SkippedBytesLimit); | ||||||
|                      skippedBytes = 0; |                      skippedBytes = 0; | ||||||
|                      // if there is a PES header available, then use it ... |                      // if there is a PES header available, then use it ... | ||||||
| @@ -408,10 +408,7 @@ void cVideoRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|               const uchar *excessData = fragmentData + fragmentLen + bite; |               const uchar *excessData = fragmentData + fragmentLen + bite; | ||||||
|               // a negative byte count means to drop some bytes from the current |               // a negative byte count means to drop some bytes from the current | ||||||
|               // fragment's tail, to not exceed the maximum packet size. |               // fragment's tail, to not exceed the maximum packet size. | ||||||
|               if (!PushOutPacket(ResultBuffer, payload, bite)) { |               PushOutPacket(ResultBuffer, payload, bite); | ||||||
|                  DroppedData("cVideoRepacker: result buffer overflow", Count - done); |  | ||||||
|                  return; |  | ||||||
|                  } |  | ||||||
|               // create a continuation PES header |               // create a continuation PES header | ||||||
|               pesHeaderLen = 0; |               pesHeaderLen = 0; | ||||||
|               pesHeader[pesHeaderLen++] = 0x00; |               pesHeader[pesHeaderLen++] = 0x00; | ||||||
| @@ -463,6 +460,7 @@ void cVideoRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|      } |      } | ||||||
|   // report that syncing dropped some bytes |   // report that syncing dropped some bytes | ||||||
|   if (skippedBytes > SkippedBytesLimit) { |   if (skippedBytes > SkippedBytesLimit) { | ||||||
|  |      if (!initiallySyncing) // omit report for the typical initial case | ||||||
|         esyslog("cVideoRepacker: skipped %d bytes while syncing on next picture", skippedBytes - SkippedBytesLimit); |         esyslog("cVideoRepacker: skipped %d bytes while syncing on next picture", skippedBytes - SkippedBytesLimit); | ||||||
|      skippedBytes = SkippedBytesLimit; |      skippedBytes = SkippedBytesLimit; | ||||||
|      } |      } | ||||||
| @@ -508,14 +506,14 @@ int cVideoRepacker::BreakAt(const uchar *Data, int Count) | |||||||
|  |  | ||||||
| class cAudioRepacker : public cCommonRepacker { | class cAudioRepacker : public cCommonRepacker { | ||||||
| private: | private: | ||||||
|   static int bitRates[]; |   static int bitRates[2][3][16]; | ||||||
|   enum eState { |   enum eState { | ||||||
|     syncing, |     syncing, | ||||||
|     scanFrame |     scanFrame | ||||||
|     } state; |     } state; | ||||||
|   int frameTodo; |   int frameTodo; | ||||||
|   int frameSize; |   int frameSize; | ||||||
|   bool IsValidAudioHeader(uint32_t Header, int *FrameSize = NULL); |   static bool IsValidAudioHeader(uint32_t Header, bool Mpeg2, int *FrameSize = NULL); | ||||||
| public: | public: | ||||||
|   cAudioRepacker(void); |   cAudioRepacker(void); | ||||||
|   virtual void Reset(void); |   virtual void Reset(void); | ||||||
| @@ -523,13 +521,19 @@ public: | |||||||
|   virtual int BreakAt(const uchar *Data, int Count); |   virtual int BreakAt(const uchar *Data, int Count); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| int cAudioRepacker::bitRates[] = { // all values are specified as kbits/s | int cAudioRepacker::bitRates[2][3][16] = { // all values are specified as kbits/s | ||||||
|   // Layer I |   // MPEG 1, Layer I | ||||||
|   0,  32,  64,  96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1, |   0,  32,  64,  96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1, | ||||||
|   // Layer II |   // MPEG 1, Layer II | ||||||
|   0,  32,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1, |   0,  32,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1, | ||||||
|   // Layer III |   // MPEG 1, Layer III | ||||||
|   0,  32,  40,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, -1 |   0,  32,  40,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, -1, | ||||||
|  |   // MPEG 2, Layer I | ||||||
|  |   0,  32,  48,  56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, -1, | ||||||
|  |   // MPEG 2, Layer II/III | ||||||
|  |   0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, -1, | ||||||
|  |   // MPEG 2, Layer II/III | ||||||
|  |   0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, -1 | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| cAudioRepacker::cAudioRepacker(void) | cAudioRepacker::cAudioRepacker(void) | ||||||
| @@ -546,7 +550,7 @@ void cAudioRepacker::Reset(void) | |||||||
|   frameSize = 0; |   frameSize = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool cAudioRepacker::IsValidAudioHeader(uint32_t Header, int *FrameSize) | bool cAudioRepacker::IsValidAudioHeader(uint32_t Header, bool Mpeg2, int *FrameSize) | ||||||
| { | { | ||||||
|   int syncword           = (Header & 0xFFF00000) >> 20; |   int syncword           = (Header & 0xFFF00000) >> 20; | ||||||
|   int id                 = (Header & 0x00080000) >> 19; |   int id                 = (Header & 0x00080000) >> 19; | ||||||
| @@ -565,7 +569,7 @@ bool cAudioRepacker::IsValidAudioHeader(uint32_t Header, int *FrameSize) | |||||||
|   if (syncword != 0xFFF) |   if (syncword != 0xFFF) | ||||||
|      return false; |      return false; | ||||||
|  |  | ||||||
|   if (id == 0) // reserved |   if (id == 0 && !Mpeg2) // reserved in MPEG 1 | ||||||
|      return false; |      return false; | ||||||
|  |  | ||||||
|   if (layer == 0) // reserved |   if (layer == 0) // reserved | ||||||
| @@ -584,16 +588,32 @@ bool cAudioRepacker::IsValidAudioHeader(uint32_t Header, int *FrameSize) | |||||||
|      if (bitrate_index == 0) |      if (bitrate_index == 0) | ||||||
|         *FrameSize = 0; |         *FrameSize = 0; | ||||||
|      else { |      else { | ||||||
|         static int samplingFrequencies[] = { 44100, 48000, 32000 }; // Hz |         static int samplingFrequencies[2][4] = { // all values are specified in Hz | ||||||
|  |           // MPEG 1 | ||||||
|  |           44100, 48000, 32000, -1, | ||||||
|  |           // MPEG 2 | ||||||
|  |           22050, 24000, 16000, -1 | ||||||
|  |           }; | ||||||
|  |  | ||||||
|         int br = 1000 * bitRates[ (3 - layer) * 0x10 + bitrate_index ]; // bits/s |         static int slots_per_frame[2][3] = { | ||||||
|         int sf = samplingFrequencies[sampling_frequency]; |           // MPEG 1, Layer I, II, III | ||||||
|  |           12, 144, 144, | ||||||
|  |           // MPEG 2, Layer I, II, III | ||||||
|  |           12, 144,  72 | ||||||
|  |           }; | ||||||
|  |  | ||||||
|         bool layerI = (layer == 3); |         int mpegIndex = 1 - id; | ||||||
|  |         int layerIndex = 3 - layer; | ||||||
|  |  | ||||||
|         int N = (layerI ? 12 : 144) * br / sf; // slots |         // Layer I (i. e., layerIndex == 0) has a larger slot size | ||||||
|  |         int slotSize = (layerIndex == 0) ? 4 : 1; // bytes | ||||||
|  |  | ||||||
|         *FrameSize = (N + padding_bit) * (layerI ? 4 : 1); // bytes |         int br = 1000 * bitRates[mpegIndex][layerIndex][bitrate_index]; // bits/s | ||||||
|  |         int sf = samplingFrequencies[mpegIndex][sampling_frequency]; | ||||||
|  |  | ||||||
|  |         int N = slots_per_frame[mpegIndex][layerIndex] * br / sf; // slots | ||||||
|  |  | ||||||
|  |         *FrameSize = (N + padding_bit) * slotSize; // bytes | ||||||
|         } |         } | ||||||
|      } |      } | ||||||
|  |  | ||||||
| @@ -632,29 +652,35 @@ void cAudioRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|         // collect number of skipped bytes while syncing |         // collect number of skipped bytes while syncing | ||||||
|         if (state <= syncing) |         if (state <= syncing) | ||||||
|            skippedBytes++; |            skippedBytes++; | ||||||
|         else if (frameTodo > 0) |         else if (frameTodo > 0) { | ||||||
|            frameTodo--; |            frameTodo--; | ||||||
|  |            if (frameTodo == 0 && state == scanFrame) { | ||||||
|  |               // the current audio frame is is done now. So push out the packet to | ||||||
|  |               // start a new packet for the next audio frame. | ||||||
|  |               PushOutPacket(ResultBuffer, payload, data - payload); | ||||||
|  |               // go on with syncing to the next audio frame | ||||||
|  |               state = syncing; | ||||||
|  |               } | ||||||
|  |            } | ||||||
|         // did we reach an audio frame header? |         // did we reach an audio frame header? | ||||||
|         scanner <<= 8; |         scanner <<= 8; | ||||||
|         scanner |= *data; |         scanner |= *data; | ||||||
|         if ((scanner & 0xFFF00000) == 0xFFF00000) { |         if ((scanner & 0xFFF00000) == 0xFFF00000) { | ||||||
|            if (frameTodo <= 0 && IsValidAudioHeader(scanner, &frameSize)) { |            if (frameTodo <= 0 && IsValidAudioHeader(scanner, mpegLevel == phMPEG2, &frameSize)) { | ||||||
|               if (state == scanFrame) { |               if (state == scanFrame) { | ||||||
|                  // As a new audio frame starts here, the previous one is done. So push |                  // As a new audio frame starts here, the previous one is done. So push | ||||||
|                  // out the packet to start a new packet for the next audio frame. If |                  // out the packet to start a new packet for the next audio frame. If | ||||||
|                  // the byte count gets negative then the current buffer ends in a |                  // the byte count gets negative then the current buffer ends in a | ||||||
|                  // partitial audio frame header that must be stripped off, as it shall |                  // partitial audio frame header that must be stripped off, as it shall | ||||||
|                  // be put in the next packet. |                  // be put in the next packet. | ||||||
|                  if (!PushOutPacket(ResultBuffer, payload, data - 3 - payload)) { |                  PushOutPacket(ResultBuffer, payload, data - 3 - payload); | ||||||
|                     DroppedData("cAudioRepacker: result buffer overflow", Count - (done - 3)); |  | ||||||
|                     return; |  | ||||||
|                     } |  | ||||||
|                  // go on with syncing to the next audio frame |                  // go on with syncing to the next audio frame | ||||||
|                  state = syncing; |                  state = syncing; | ||||||
|                  } |                  } | ||||||
|               if (state == syncing) { |               if (state == syncing) { | ||||||
|                  // report that syncing dropped some bytes |                  if (initiallySyncing) // omit report for the typical initial case | ||||||
|                  if (skippedBytes > SkippedBytesLimit) |                     initiallySyncing = false; | ||||||
|  |                  else if (skippedBytes > SkippedBytesLimit) // report that syncing dropped some bytes | ||||||
|                     esyslog("cAudioRepacker: skipped %d bytes to sync on next audio frame", skippedBytes - SkippedBytesLimit); |                     esyslog("cAudioRepacker: skipped %d bytes to sync on next audio frame", skippedBytes - SkippedBytesLimit); | ||||||
|                  skippedBytes = 0; |                  skippedBytes = 0; | ||||||
|                  // if there is a PES header available, then use it ... |                  // if there is a PES header available, then use it ... | ||||||
| @@ -693,11 +719,10 @@ void cAudioRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|                  // the next packet's payload will begin with the fourth byte of |                  // the next packet's payload will begin with the fourth byte of | ||||||
|                  // the audio frame header (= the actual byte) |                  // the audio frame header (= the actual byte) | ||||||
|                  payload = data; |                  payload = data; | ||||||
|                  // as there is no length information available, assume the |  | ||||||
|                  // maximum we can hold in one PES packet |                  // maximum we can hold in one PES packet | ||||||
|                  packetTodo = maxPacketSize - pesHeaderLen; |                  packetTodo = maxPacketSize - pesHeaderLen; | ||||||
|                  // setup expected audio frame size to omit false audio header detection |                  // expected remainder of audio frame: so far we have read 3 bytes from the frame header  | ||||||
|                  frameTodo = frameSize; |                  frameTodo = frameSize - 3; | ||||||
|                  // go on with collecting the frame's data |                  // go on with collecting the frame's data | ||||||
|                  ((int &)state)++; |                  ((int &)state)++; | ||||||
|                  } |                  } | ||||||
| @@ -751,10 +776,7 @@ void cAudioRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|               const uchar *excessData = fragmentData + fragmentLen + bite; |               const uchar *excessData = fragmentData + fragmentLen + bite; | ||||||
|               // A negative byte count means to drop some bytes from the current |               // A negative byte count means to drop some bytes from the current | ||||||
|               // fragment's tail, to not exceed the maximum packet size. |               // fragment's tail, to not exceed the maximum packet size. | ||||||
|               if (!PushOutPacket(ResultBuffer, payload, bite)) { |               PushOutPacket(ResultBuffer, payload, bite); | ||||||
|                  DroppedData("cAudioRepacker: result buffer overflow", Count - done); |  | ||||||
|                  return; |  | ||||||
|                  } |  | ||||||
|               // create a continuation PES header |               // create a continuation PES header | ||||||
|               pesHeaderLen = 0; |               pesHeaderLen = 0; | ||||||
|               pesHeader[pesHeaderLen++] = 0x00; |               pesHeader[pesHeaderLen++] = 0x00; | ||||||
| @@ -806,6 +828,7 @@ void cAudioRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|      } |      } | ||||||
|   // report that syncing dropped some bytes |   // report that syncing dropped some bytes | ||||||
|   if (skippedBytes > SkippedBytesLimit) { |   if (skippedBytes > SkippedBytesLimit) { | ||||||
|  |      if (!initiallySyncing) // omit report for the typical initial case | ||||||
|         esyslog("cAudioRepacker: skipped %d bytes while syncing on next audio frame", skippedBytes - SkippedBytesLimit); |         esyslog("cAudioRepacker: skipped %d bytes while syncing on next audio frame", skippedBytes - SkippedBytesLimit); | ||||||
|      skippedBytes = SkippedBytesLimit; |      skippedBytes = SkippedBytesLimit; | ||||||
|      } |      } | ||||||
| @@ -815,7 +838,8 @@ int cAudioRepacker::BreakAt(const uchar *Data, int Count) | |||||||
| { | { | ||||||
|   int PesPayloadOffset = 0; |   int PesPayloadOffset = 0; | ||||||
|  |  | ||||||
|   if (AnalyzePesHeader(Data, Count, PesPayloadOffset) <= phInvalid) |   ePesHeader MpegLevel = AnalyzePesHeader(Data, Count, PesPayloadOffset); | ||||||
|  |   if (MpegLevel <= phInvalid) | ||||||
|      return -1; // not enough data for test |      return -1; // not enough data for test | ||||||
|  |  | ||||||
|   // determine amount of data to fill up packet and to append next audio frame header |   // determine amount of data to fill up packet and to append next audio frame header | ||||||
| @@ -845,7 +869,7 @@ int cAudioRepacker::BreakAt(const uchar *Data, int Count) | |||||||
|            localScanner <<= 8; |            localScanner <<= 8; | ||||||
|            localScanner |= *data++; |            localScanner |= *data++; | ||||||
|            // check whether the next audio frame follows |            // check whether the next audio frame follows | ||||||
|            if ((localScanner & 0xFFF00000) == 0xFFF00000 && IsValidAudioHeader(localScanner)) |            if (((localScanner & 0xFFF00000) == 0xFFF00000) && IsValidAudioHeader(localScanner, MpegLevel == phMPEG2)) | ||||||
|               return data - Data; |               return data - Data; | ||||||
|            } |            } | ||||||
|      } |      } | ||||||
| @@ -879,8 +903,8 @@ private: | |||||||
|   int skippedBytes; |   int skippedBytes; | ||||||
|   void ResetPesHeader(bool ContinuationFrame = false); |   void ResetPesHeader(bool ContinuationFrame = false); | ||||||
|   void AppendSubStreamID(bool ContinuationFrame = false); |   void AppendSubStreamID(bool ContinuationFrame = false); | ||||||
|   bool FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite); |   bool FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Bite); | ||||||
|   bool StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite); |   bool StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Bite); | ||||||
| public: | public: | ||||||
|   cDolbyRepacker(void); |   cDolbyRepacker(void); | ||||||
|   virtual void Reset(void); |   virtual void Reset(void); | ||||||
| @@ -947,6 +971,7 @@ void cDolbyRepacker::ResetPesHeader(bool ContinuationFrame) | |||||||
|  |  | ||||||
| void cDolbyRepacker::Reset(void) | void cDolbyRepacker::Reset(void) | ||||||
| { | { | ||||||
|  |   cRepacker::Reset(); | ||||||
|   ResetPesHeader(); |   ResetPesHeader(); | ||||||
|   state = find_0b; |   state = find_0b; | ||||||
|   ac3todo = 0; |   ac3todo = 0; | ||||||
| @@ -958,26 +983,24 @@ void cDolbyRepacker::Reset(void) | |||||||
|   skippedBytes = 0; |   skippedBytes = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite) | bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Bite) | ||||||
| { | { | ||||||
|  |   bool success = true; | ||||||
|   // enough data available to put PES packet into buffer? |   // enough data available to put PES packet into buffer? | ||||||
|   if (fragmentTodo <= Todo) { |   if (fragmentTodo <= Todo) { | ||||||
|      // output a previous fragment first |      // output a previous fragment first | ||||||
|      if (fragmentLen > 0) { |      if (fragmentLen > 0) { | ||||||
|         Bite = fragmentLen; |         Bite = fragmentLen; | ||||||
|         int n = Put(ResultBuffer, fragmentData, Bite, fragmentLen + fragmentTodo); |         int n = Put(ResultBuffer, fragmentData, Bite, fragmentLen + fragmentTodo); | ||||||
|         if (Bite != n) { |         if (Bite != n) | ||||||
|            Reset(); |            success = false; | ||||||
|            return false; |  | ||||||
|            } |  | ||||||
|         fragmentLen = 0; |         fragmentLen = 0; | ||||||
|         } |         } | ||||||
|      Bite = fragmentTodo; |      Bite = fragmentTodo; | ||||||
|  |      if (success) { | ||||||
|         int n = Put(ResultBuffer, Data, Bite, Bite); |         int n = Put(ResultBuffer, Data, Bite, Bite); | ||||||
|      if (Bite != n) { |         if (Bite != n) | ||||||
|         Reset(); |            success = false; | ||||||
|         Done += n; |  | ||||||
|         return false; |  | ||||||
|         } |         } | ||||||
|      fragmentTodo = 0; |      fragmentTodo = 0; | ||||||
|      // ac3 frame completely processed? |      // ac3 frame completely processed? | ||||||
| @@ -987,19 +1010,16 @@ bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const ucha | |||||||
|   else { |   else { | ||||||
|      // copy the fragment into separate buffer for later processing |      // copy the fragment into separate buffer for later processing | ||||||
|      Bite = Todo; |      Bite = Todo; | ||||||
|      if (fragmentLen + Bite > (int)sizeof(fragmentData)) { |  | ||||||
|         Reset(); |  | ||||||
|         return false; |  | ||||||
|         } |  | ||||||
|      memcpy(fragmentData + fragmentLen, Data, Bite); |      memcpy(fragmentData + fragmentLen, Data, Bite); | ||||||
|      fragmentLen += Bite; |      fragmentLen += Bite; | ||||||
|      fragmentTodo -= Bite; |      fragmentTodo -= Bite; | ||||||
|      } |      } | ||||||
|   return true; |   return success; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool cDolbyRepacker::StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite) | bool cDolbyRepacker::StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Bite) | ||||||
| { | { | ||||||
|  |   bool success = true; | ||||||
|   int packetLen = pesHeaderLen + ac3todo; |   int packetLen = pesHeaderLen + ac3todo; | ||||||
|   // limit packet to maximum size |   // limit packet to maximum size | ||||||
|   if (packetLen > maxPacketSize) |   if (packetLen > maxPacketSize) | ||||||
| @@ -1010,16 +1030,13 @@ bool cDolbyRepacker::StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar | |||||||
|   // enough data available to put PES packet into buffer? |   // enough data available to put PES packet into buffer? | ||||||
|   if (packetLen - pesHeaderLen <= Todo) { |   if (packetLen - pesHeaderLen <= Todo) { | ||||||
|      int n = Put(ResultBuffer, pesHeader, Bite, packetLen); |      int n = Put(ResultBuffer, pesHeader, Bite, packetLen); | ||||||
|      if (Bite != n) { |      if (Bite != n) | ||||||
|         Reset(); |         success = false; | ||||||
|         return false; |  | ||||||
|         } |  | ||||||
|      Bite = packetLen - pesHeaderLen; |      Bite = packetLen - pesHeaderLen; | ||||||
|  |      if (success) { | ||||||
|         n = Put(ResultBuffer, Data, Bite, Bite); |         n = Put(ResultBuffer, Data, Bite, Bite); | ||||||
|      if (Bite != n) { |         if (Bite != n) | ||||||
|         Reset(); |            success = false; | ||||||
|         Done += n; |  | ||||||
|         return false; |  | ||||||
|         } |         } | ||||||
|      // ac3 frame completely processed? |      // ac3 frame completely processed? | ||||||
|      if (Bite >= ac3todo) |      if (Bite >= ac3todo) | ||||||
| @@ -1028,24 +1045,16 @@ bool cDolbyRepacker::StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar | |||||||
|   else { |   else { | ||||||
|      fragmentTodo = packetLen; |      fragmentTodo = packetLen; | ||||||
|      // copy the pesheader into separate buffer for later processing |      // copy the pesheader into separate buffer for later processing | ||||||
|      if (fragmentLen + Bite > (int)sizeof(fragmentData)) { |  | ||||||
|         Reset(); |  | ||||||
|         return false; |  | ||||||
|         } |  | ||||||
|      memcpy(fragmentData + fragmentLen, pesHeader, Bite); |      memcpy(fragmentData + fragmentLen, pesHeader, Bite); | ||||||
|      fragmentLen += Bite; |      fragmentLen += Bite; | ||||||
|      fragmentTodo -= Bite; |      fragmentTodo -= Bite; | ||||||
|      // copy the fragment into separate buffer for later processing |      // copy the fragment into separate buffer for later processing | ||||||
|      Bite = Todo; |      Bite = Todo; | ||||||
|      if (fragmentLen + Bite > (int)sizeof(fragmentData)) { |  | ||||||
|         Reset(); |  | ||||||
|         return false; |  | ||||||
|         } |  | ||||||
|      memcpy(fragmentData + fragmentLen, Data, Bite); |      memcpy(fragmentData + fragmentLen, Data, Bite); | ||||||
|      fragmentLen += Bite; |      fragmentLen += Bite; | ||||||
|      fragmentTodo -= Bite; |      fragmentTodo -= Bite; | ||||||
|      } |      } | ||||||
|   return true; |   return success; | ||||||
| } | } | ||||||
|  |  | ||||||
| void cDolbyRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) | void cDolbyRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) | ||||||
| @@ -1139,8 +1148,9 @@ void cDolbyRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|                   state = find_0b; |                   state = find_0b; | ||||||
|                   continue; |                   continue; | ||||||
|                   } |                   } | ||||||
|                // report that syncing dropped some bytes |                if (initiallySyncing) // omit report for the typical initial case | ||||||
|                if (skippedBytes > SkippedBytesLimit) |                   initiallySyncing = false; | ||||||
|  |                else if (skippedBytes > SkippedBytesLimit) // report that syncing dropped some bytes | ||||||
|                   esyslog("cDolbyRepacker: skipped %d bytes to sync on next AC3 frame", skippedBytes - SkippedBytesLimit); |                   esyslog("cDolbyRepacker: skipped %d bytes to sync on next AC3 frame", skippedBytes - SkippedBytesLimit); | ||||||
|                skippedBytes = 0; |                skippedBytes = 0; | ||||||
|                // append read data to header for common output processing |                // append read data to header for common output processing | ||||||
| @@ -1154,18 +1164,11 @@ void cDolbyRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|           case output_packet: { |           case output_packet: { | ||||||
|                int bite = 0; |                int bite = 0; | ||||||
|                // finish remainder of ac3 frame? |                // finish remainder of ac3 frame? | ||||||
|                if (fragmentTodo > 0) { |                if (fragmentTodo > 0) | ||||||
|                   if (!FinishRemainder(ResultBuffer, data, todo, done, bite)) { |                   FinishRemainder(ResultBuffer, data, todo, bite); | ||||||
|                      DroppedData("cDolbyRepacker: result buffer overflow", Count - done); |  | ||||||
|                      return; |  | ||||||
|                      } |  | ||||||
|                   } |  | ||||||
|                else { |                else { | ||||||
|                   // start a new packet |                   // start a new packet | ||||||
|                   if (!StartNewPacket(ResultBuffer, data, todo, done, bite)) { |                   StartNewPacket(ResultBuffer, data, todo, bite); | ||||||
|                      DroppedData("cDolbyRepacker: result buffer overflow", Count - done); |  | ||||||
|                      return; |  | ||||||
|                      } |  | ||||||
|                   // prepare for next (continuation) packet |                   // prepare for next (continuation) packet | ||||||
|                   ResetPesHeader(state == output_packet); |                   ResetPesHeader(state == output_packet); | ||||||
|                   } |                   } | ||||||
| @@ -1178,6 +1181,7 @@ void cDolbyRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, | |||||||
|         } |         } | ||||||
|   // report that syncing dropped some bytes |   // report that syncing dropped some bytes | ||||||
|   if (skippedBytes > SkippedBytesLimit) { |   if (skippedBytes > SkippedBytesLimit) { | ||||||
|  |      if (!initiallySyncing) // omit report for the typical initial case | ||||||
|         esyslog("cDolbyRepacker: skipped %d bytes while syncing on next AC3 frame", skippedBytes - 4); |         esyslog("cDolbyRepacker: skipped %d bytes while syncing on next AC3 frame", skippedBytes - 4); | ||||||
|      skippedBytes = SkippedBytesLimit; |      skippedBytes = SkippedBytesLimit; | ||||||
|      } |      } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user