Fix major Bug in demuxer, fix audio playback on some channels
authorMarten Richter <marten.richter@freenet.de>
Sun, 16 Sep 2012 07:01:56 +0000 (09:01 +0200)
committerMarten Richter <marten.richter@freenet.de>
Sun, 16 Sep 2012 07:01:56 +0000 (09:01 +0200)
audioomx.cc
audioomx.h
demuxer.cc
player.cc
playerlivetv.cc
videoomx.cc

index ebc313f99dd5de7285c82d37404886fa1f98e612..4b11e8084c23ee5f9a51677712955b38fa787e90 100644 (file)
@@ -53,6 +53,10 @@ AudioOMX::AudioOMX()
   mp23codec_libav=NULL;
   mp23codec_context_libav=NULL;
 
+  decompress_buffer=NULL;
+  decompress_buffer_size=0;
+  decompress_buffer_filled=0;
+
 }
 
 AudioOMX::~AudioOMX()
@@ -73,6 +77,10 @@ int AudioOMX::init(UCHAR tstreamType) {
 
        unMute();
 
+       decompress_buffer_size=20000;
+       decompress_buffer=(UCHAR*)malloc(decompress_buffer_size);
+       decompress_buffer_filled=0;
+
 
 
        av_register_all();
@@ -108,6 +116,11 @@ int AudioOMX::shutdown()
   Log::getInstance()->log("Audio", Log::DEBUG, "audio shutdown called");
   DeAllocateCodecsOMX();
 
+  free(decompress_buffer);
+  decompress_buffer=NULL;
+  decompress_buffer_size=0;
+  decompress_buffer_filled=0;
+
   return 1;
 }
 
@@ -612,6 +625,7 @@ int AudioOMX::InitDecoderLibAV()
         av_init_packet(&incoming_paket_libav);
         decode_frame_libav=avcodec_alloc_frame();
         libav_mutex.Unlock();
+        decompress_buffer_filled=0;
 
 
 
@@ -1230,6 +1244,29 @@ int AudioOMX::test()
 }
 #endif
 
+unsigned int AudioOMX::AdvanceMpAudioSync(UCHAR *data,unsigned int size)
+{
+       if (size<=2) return size; // silly;
+       unsigned int test=0;
+       while (test+1<size) {
+               if (data[test]==0xFF && (data[test+1] &0xe0)==0xe0) return test; // probably FrameSync
+               test++;
+       }
+       return size;
+}
+
+unsigned int AudioOMX::AdvanceAc3AudioSync(UCHAR *data,unsigned int size)
+{
+       if (size<=2) return size; // silly;
+       unsigned int test=0;
+       while (test+1<size) {
+               if (data[test]==0x0B && data[test+1]==0x77) return test; // probably FrameSync
+               test++;
+       }
+       return size;
+}
+
+
 void AudioOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
 {
   packet = mplist.front();
@@ -1299,6 +1336,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
        UINT headerstrip = 0;
        if (packet.disconti) {
                firstsynched = false;
+               decompress_buffer_filled=0;
                if (cur_input_buf_omx) {
                        OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,
                                        cur_input_buf_omx);
@@ -1314,6 +1352,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
                firstsynched = false;
                achange=true;
                lastAType = packet.type;
+               decompress_buffer_filled=0;
 
                if (cur_input_buf_omx) {
                        OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,
@@ -1324,10 +1363,12 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
                        }
                        cur_input_buf_omx = NULL;
                }
+               vw->LockClock();
                if (!ChangeAudioPortConfig()) {
                        Log::getInstance()->log("Audio", Log::DEBUG,
                                        "Changing audio port config failed", error);
                }
+               vw->UnlockClock();
 
        }
 
@@ -1352,9 +1393,11 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
                                cur_input_buf_omx = NULL;//write out old data
                        }
                        firstsynched = true;
+                       //decompress_buffer_filled=0;
                } else {
                        if (!firstsynched) {//
                                *samplepos = packet.length;//if we have not processed at least one
+                               decompress_buffer_filled=0;
                                return packet.length;//synched packet ignore it!
                        }
                }
@@ -1392,7 +1435,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
                        }
                        lastreftimeOMX = packet.presentation_time;
                //      Log::getInstance()->log("Audio", Log::DEBUG,
-                       //              "Time code %lld pts %lld dts %lld", lastreftimeOMX, packet.pts,packet.dts);
+               //                      "Time code %lld pts %lld dts %lld", lastreftimeOMX, packet.pts,packet.dts);
                        lastreftimePTS = packet.pts;
                        cur_input_buf_omx->nTimeStamp =0;// lastreftimeOMX; // the clock component is faulty;
                } else {
@@ -1433,14 +1476,58 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
                }break;
                };
 
-               incoming_paket_libav.data =(uint8_t*) buffer+packet.pos_buffer+*samplepos;
-               incoming_paket_libav.size = haveToCopy;
+               if (decompress_buffer_filled) { // have a remaining paket
+                       incoming_paket_libav.data =(uint8_t*) decompress_buffer;
+                       memcpy(decompress_buffer+decompress_buffer_filled,
+                                       buffer+packet.pos_buffer+*samplepos,
+                                       min(haveToCopy,decompress_buffer_size-decompress_buffer_filled));
+                       incoming_paket_libav.size = decompress_buffer_filled
+                                       +min(haveToCopy,decompress_buffer_size-decompress_buffer_filled);
+                       //Log::getInstance()->log("Audio", Log::DEBUG,"Use saved audio buffer %d",packet.type);
+               } else {
+                       incoming_paket_libav.data =(uint8_t*) buffer+packet.pos_buffer+*samplepos;
+                       incoming_paket_libav.size = haveToCopy;
+               }
 
-               while (haveToCopy> 0 && errcount<2) {
+               while (haveToCopy> 0 && errcount<3) {
 
                        //Log::getInstance()->log("Audio", Log::DEBUG,"libav in %d %d",framesize,current_context->frame_size);
                        //Log::getInstance()->log("Audio", Log::DEBUG, "libav in %d %d",
                                //      framesize, current_context->frame_size);
+
+                       if (!decompress_buffer_filled) { // only do this if no old data is present
+                               int adv = 0;
+                               switch (packet.type) {
+                               case MPTYPE_MPEG_AUDIO:
+                               case MPTYPE_MPEG_AUDIO_LAYER3: {
+                                       adv = AdvanceMpAudioSync(incoming_paket_libav.data,
+                                                       incoming_paket_libav.size);
+                               }
+                                       break;
+                               case MPTYPE_AC3:
+                               case MPTYPE_AC3_PRE13: {
+                                       adv = AdvanceAc3AudioSync(incoming_paket_libav.data,
+                                                       incoming_paket_libav.size);
+                               }
+                                       break;
+                               };
+                               if (adv > 0) {
+                                       incoming_paket_libav.data += adv;
+                                       haveToCopy -= adv;
+                                       *samplepos += adv;
+                                       if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
+                                       else framesize=haveToCopy;
+                                       //Log::getInstance()->log("Audio", Log::DEBUG,"Advance by %d %d from %d",adv,packet.type,*samplepos );
+                                       if (haveToCopy <= 0) {
+                                       //       Log::getInstance()->log("Audio", Log::DEBUG,"No sync code in packet remove %d",packet.type);
+                                                *samplepos=packet.length;
+                                                return packet.length;
+                                       }
+                                               break;
+                               } //
+                       //      else Log::getInstance()->log("Audio", Log::DEBUG,"Loop run" );
+                       }
+
                        int oldcancelstate;
                        int oldcanceltype;
                        pthread_testcancel();
@@ -1467,16 +1554,32 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
                                return *samplepos;
                        }
 
-                       if (len>0) {
-                               incoming_paket_libav.data += len;
-                               haveToCopy -= len;
-                               *samplepos += len;
+                       if (decompress_buffer_filled) { // reset to normal decoding
+                               if (len>0) {
+                                       Log::getInstance()->log("Audio", Log::DEBUG,"saved audio: %d",len);
+                                       haveToCopy -= min(len-decompress_buffer_filled,0);
+                                       *samplepos += min(len-decompress_buffer_filled,0);
+                                       if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
+                                       else framesize=haveToCopy;
+                               } else {
+                                       framesize=haveToCopy;
+                               }
+                               incoming_paket_libav.data =(uint8_t*) buffer+packet.pos_buffer+*samplepos;
                                errcount=0;
-                               if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
-                               else framesize=haveToCopy;
+                               decompress_buffer_filled=0;
                        } else {
-                               errcount++;
-                               framesize=haveToCopy;
+
+                               if (len>0) {
+                                       incoming_paket_libav.data += len;
+                                       haveToCopy -= len;
+                                       *samplepos += len;
+                                       errcount=0;
+                                       if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
+                                       else framesize=haveToCopy;
+                               } else {
+                                       errcount++;
+                                       framesize=haveToCopy;
+                               }
                        }
 
                        incoming_paket_libav.size =framesize;
@@ -1531,11 +1634,25 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
                                //Log::getInstance()->log("Audio", Log::DEBUG,"memcpy out");
                                cur_input_buf_omx->nFilledLen += dsize;
                        } else {
-                               //Log::getInstance()->log("Audio", Log::DEBUG,"Incomplete mpeg frames in pes packet %d",incoming_paket_libav.size);
+                               //Log::getInstance()->log("Audio", Log::DEBUG,"Incomplete mpeg frames in pes packet %d %d",incoming_paket_libav.size,packet.length);
+                       /*      uint8_t a1=incoming_paket_libav.data[0];
+                               uint8_t a2=incoming_paket_libav.data[1];
+                               uint8_t a3=incoming_paket_libav.data[2];
+                               uint8_t a4=incoming_paket_libav.data[3];*/
+                       //      Log::getInstance()->log("Audio", Log::DEBUG,"Header %x %x %x %x",a1,a2,
+                               //              a3,a4);
                        }
 
                }
 
+       }
+       decompress_buffer_filled=0;
+       if (haveToCopy ) {
+               Log::getInstance()->log("Audio", Log::DEBUG,"We can not decompress %d save for later %d %x %x",haveToCopy,packet.type,incoming_paket_libav.data,packet.pos_buffer);
+               memcpy(decompress_buffer,incoming_paket_libav.data,min(haveToCopy,decompress_buffer_size));
+
+           decompress_buffer_filled=min(haveToCopy,decompress_buffer_size);
+
        }
 
        if (cur_input_buf_omx->nFilledLen) {
@@ -1552,6 +1669,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
 
 
 
+
        *samplepos=packet.length;
        return packet.length;
 
index 526e3d782f0b2d620cc60816e57dc6782105f8d5..bd72c562719117d16d9601ff6fc1a0dcbb4e4bfd 100644 (file)
@@ -116,6 +116,10 @@ class AudioOMX : public Audio
 \r
 \r
 \r
+       unsigned int AdvanceAc3AudioSync(UCHAR *data,unsigned int size);\r
+       unsigned int AdvanceMpAudioSync(UCHAR *data,unsigned int size);\r
+\r
+\r
     void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver);\r
 \r
    // OMX_HANDLETYPE omx_aud_dec;\r
@@ -159,6 +163,9 @@ class AudioOMX : public Audio
     AVPacket incoming_paket_libav;\r
     AVFrame *decode_frame_libav;\r
 \r
+    UCHAR * decompress_buffer;\r
+    unsigned int decompress_buffer_size;\r
+    unsigned int decompress_buffer_filled;\r
 \r
 \r
         int InitDecoderLibAV();\r
index 9884f36f1b191e8e8d2870ae3d810770b2c67fd1..305c1a15f82702ceeab0ff2d4dc6fafecd6ecc8d 100644 (file)
@@ -651,9 +651,17 @@ void Demuxer::parsePacketDetails(PESPacket& packet)
 pre_1_3_19_Recording: //This is for old recordings stuff and live TV\r
         if (ispre_1_3_19)\r
         {\r
-            substream_id = PESTYPE_PRIVATE_1;\r
-            substream_type = 0x80;\r
-            substream_index = 0;\r
+               int old_substream=packet.getSubstream();\r
+               if (old_substream){ //someone else already set it, this is live tv\r
+                       substream_id = old_substream;\r
+                       substream_type = substream_id & 0xF0;\r
+                       substream_index = substream_id & 0x1F;\r
+               } else {\r
+                substream_id = PESTYPE_PRIVATE_1;\r
+                substream_type = 0x80;\r
+                substream_index = 0;\r
+               }\r
+\r
         }\r
         switch (substream_type)\r
         {\r
index a16f63e53d6c13b00b2443fc3eada26279d2b0e1..f2c9d10a3fdc9fd08b93e1c76a4eeb2e8269f36e 100644 (file)
--- a/player.cc
+++ b/player.cc
@@ -94,7 +94,10 @@ int Player::init(bool p_isPesRecording,double framespersecond)
   unsigned int demux_audio_size=524288;\r
   if (video->supportsh264()) {\r
          demux_video_size*=5*1;//5;\r
-         demux_audio_size*=1;\r
+\r
+  }\r
+  if (audio->maysupportAc3()) {\r
+         demux_audio_size*=2;\r
   }\r
  \r
   if (!demuxer->init(this, audio, video,teletext, demux_video_size,demux_audio_size,65536, framespersecond, subtitles))\r
index 64daa78ba9483675d709b4f84080fa96f44222a6..cd48c55b9a53923da55bbf5801e927317bb64929 100644 (file)
@@ -75,12 +75,19 @@ int PlayerLiveTV::init()
   teletext = new TeletextDecoderVBIEBU();\r
   \r
   unsigned int demux_video_size=2097152;\r
-  if (video->supportsh264()) demux_video_size*=5;\r
+   unsigned int demux_audio_size=524288;\r
+   if (video->supportsh264()) {\r
+         demux_video_size*=5*1;//5;\r
+\r
+   }\r
+   if (audio->maysupportAc3()) {\r
+         demux_audio_size*=2;\r
+   }\r
 \r
   int text_fak=video->getTeletextBufferFaktor();\r
 \r
  \r
-  if (!demuxer->init(this, audio, video, teletext, demux_video_size,524288, 65536*text_fak,25./*unimportant*/,subtitles))\r
+  if (!demuxer->init(this, audio, video, teletext, demux_video_size,demux_audio_size, 65536*text_fak,25./*unimportant*/,subtitles))\r
   {\r
     logger->log("PlayerLiveTV", Log::ERR, "Demuxer failed to init");\r
     shutdown();\r
index a6d670860f32c5f4a7fac4d0ce24a88bc4d73b81..cd4d242334ab9af00007b4a881d79c00fffc37de 100644 (file)
@@ -2127,9 +2127,11 @@ void VideoOMX::FrameWaitforDisplay(long long pts)
        if (offset==0) offset=25;
        offset=-2*10000000LL/offset;
        target_time+=offset;
-       if ((target_time-current_time)>1000000LL) target_time=current_time+1000000LL; // something is wrong do not wait too long
-       //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
-       //              target_time-current_time);
+       //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld tg: %lld sys: %lld off: %lld diff %lld po: %lld",pts,target_time,current_time,offset,
+       //                      target_time-current_time,playbacktimeoffset);
+       if ((target_time-current_time)>2000000LL) target_time=current_time+2000000LL; // something is wrong do not wait too long
+       //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld tg: %lld sys: %lld off: %lld diff %lld po: %lld",pts,target_time,current_time,offset,
+       //              target_time-current_time,playbacktimeoffset);
 
        WaitUntil(target_time);
        //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display out %lld",GetCurrentSystemTime());
@@ -2190,11 +2192,15 @@ void VideoOMX::threadMethod()
                                //Log::getInstance()->log("Video", Log::DEBUG, "threadMethod Frameskip");
 
                        } else {
+                       //      Log::getInstance()->log("Video", Log::DEBUG,
+                       //                                                                                      "prot empty this buffer in");
                                OMX_ERRORTYPE error = ProtOMXEmptyThisBuffer(omx_vid_dec, pict);
                                if (error != OMX_ErrorNone) {
                                        Log::getInstance()->log("Video", Log::DEBUG,
                                                        "OMX_EmptyThisBuffer failed %x", error);
                                }
+                       //      Log::getInstance()->log("Video", Log::DEBUG,
+                       //                                                                                                                      "prot empty this buffer out");
                                if (deint_first_frame && dodeint) DeinterlaceFix();
                                if (islast) FrameWaitforDisplay(time);
                        }