From 0a60e48af83ab9bda1708448c29988889d84025b Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 16 Sep 2012 09:01:56 +0200 Subject: [PATCH] Fix major Bug in demuxer, fix audio playback on some channels --- audioomx.cc | 144 +++++++++++++++++++++++++++++++++++++++++++----- audioomx.h | 7 +++ demuxer.cc | 14 ++++- player.cc | 5 +- playerlivetv.cc | 11 +++- videoomx.cc | 12 +++- 6 files changed, 171 insertions(+), 22 deletions(-) diff --git a/audioomx.cc b/audioomx.cc index ebc313f..4b11e80 100644 --- a/audioomx.cc +++ b/audioomx.cc @@ -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+1ProtOMXEmptyThisBuffer(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; diff --git a/audioomx.h b/audioomx.h index 526e3d7..bd72c56 100644 --- a/audioomx.h +++ b/audioomx.h @@ -116,6 +116,10 @@ class AudioOMX : public Audio + unsigned int AdvanceAc3AudioSync(UCHAR *data,unsigned int size); + unsigned int AdvanceMpAudioSync(UCHAR *data,unsigned int size); + + void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver); // OMX_HANDLETYPE omx_aud_dec; @@ -159,6 +163,9 @@ class AudioOMX : public Audio AVPacket incoming_paket_libav; AVFrame *decode_frame_libav; + UCHAR * decompress_buffer; + unsigned int decompress_buffer_size; + unsigned int decompress_buffer_filled; int InitDecoderLibAV(); diff --git a/demuxer.cc b/demuxer.cc index 9884f36..305c1a1 100644 --- a/demuxer.cc +++ b/demuxer.cc @@ -651,9 +651,17 @@ void Demuxer::parsePacketDetails(PESPacket& packet) pre_1_3_19_Recording: //This is for old recordings stuff and live TV if (ispre_1_3_19) { - substream_id = PESTYPE_PRIVATE_1; - substream_type = 0x80; - substream_index = 0; + int old_substream=packet.getSubstream(); + if (old_substream){ //someone else already set it, this is live tv + substream_id = old_substream; + substream_type = substream_id & 0xF0; + substream_index = substream_id & 0x1F; + } else { + substream_id = PESTYPE_PRIVATE_1; + substream_type = 0x80; + substream_index = 0; + } + } switch (substream_type) { diff --git a/player.cc b/player.cc index a16f63e..f2c9d10 100644 --- a/player.cc +++ b/player.cc @@ -94,7 +94,10 @@ int Player::init(bool p_isPesRecording,double framespersecond) unsigned int demux_audio_size=524288; if (video->supportsh264()) { demux_video_size*=5*1;//5; - demux_audio_size*=1; + + } + if (audio->maysupportAc3()) { + demux_audio_size*=2; } if (!demuxer->init(this, audio, video,teletext, demux_video_size,demux_audio_size,65536, framespersecond, subtitles)) diff --git a/playerlivetv.cc b/playerlivetv.cc index 64daa78..cd48c55 100644 --- a/playerlivetv.cc +++ b/playerlivetv.cc @@ -75,12 +75,19 @@ int PlayerLiveTV::init() teletext = new TeletextDecoderVBIEBU(); unsigned int demux_video_size=2097152; - if (video->supportsh264()) demux_video_size*=5; + unsigned int demux_audio_size=524288; + if (video->supportsh264()) { + demux_video_size*=5*1;//5; + + } + if (audio->maysupportAc3()) { + demux_audio_size*=2; + } int text_fak=video->getTeletextBufferFaktor(); - if (!demuxer->init(this, audio, video, teletext, demux_video_size,524288, 65536*text_fak,25./*unimportant*/,subtitles)) + if (!demuxer->init(this, audio, video, teletext, demux_video_size,demux_audio_size, 65536*text_fak,25./*unimportant*/,subtitles)) { logger->log("PlayerLiveTV", Log::ERR, "Demuxer failed to init"); shutdown(); diff --git a/videoomx.cc b/videoomx.cc index a6d6708..cd4d242 100644 --- a/videoomx.cc +++ b/videoomx.cc @@ -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); } -- 2.39.2