From 7c4f71e82e1ff2969a4bb5f5c91ad4c9c98bd8b5 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 28 Jul 2013 12:00:47 +0200 Subject: [PATCH] Flush/Reset video decoder pipeline, in case decoder has stalled buffers --- videoomx.cc | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++--- videoomx.h | 4 +++ 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/videoomx.cc b/videoomx.cc index 7a56cc0..fd8a133 100644 --- a/videoomx.cc +++ b/videoomx.cc @@ -46,6 +46,8 @@ VideoOMX::VideoOMX() { omx_h264 = omx_mpeg2 = true; clock_references = 0; + omx_vid_stalled = false; + offsetnotset = true; offsetvideonotset = true; offsetaudionotset = true; @@ -167,7 +169,7 @@ void VideoOMX::AddOmxEvent(VPE_OMX_EVENT new_event) OMX_ERRORTYPE VideoOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){ - //Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone"); +// Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone"); VideoOMX *video=(VideoOMX *)getInstance(); /* long long temp =buffer->nTimeStamp.nLowPart | ((long long) buffer->nTimeStamp.nHighPart << 32); @@ -179,14 +181,14 @@ OMX_ERRORTYPE VideoOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN O void VideoOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){ input_bufs_omx_mutex.Lock(); - //Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d %d %d",input_bufs_omx_free.size(),input_bufs_omx_present.size(),input_bufs_omx_all.size()); + //Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d %d",input_bufs_omx_free.size(),input_bufs_omx_all.size()); input_bufs_omx_free.push_back(buffer); //Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size()); input_bufs_omx_mutex.Unlock(); } OMX_ERRORTYPE VideoOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) { - Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone"); + //Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone"); return OMX_ErrorNone; } @@ -1276,6 +1278,37 @@ int VideoOMX::AllocateCodecsOMX() return 0; } + OMX_CONFIG_BUFFERSTALLTYPE stall_conf; + memset(&stall_conf,0,sizeof(stall_conf)); + stall_conf.nSize=sizeof(stall_conf); + stall_conf.nVersion.nVersion=OMX_VERSION; + stall_conf.nPortIndex=omx_codec_output_port; + stall_conf.nDelay=1500*1000; + error=OMX_SetConfig(omx_vid_dec,OMX_IndexConfigBufferStall,&stall_conf); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigBufferStall failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + omx_vid_stalled = false; + + OMX_CONFIG_REQUESTCALLBACKTYPE req_callback; + memset(&req_callback,0,sizeof(req_callback)); + req_callback.nSize=sizeof(req_callback); + req_callback.nVersion.nVersion=OMX_VERSION; + req_callback.nPortIndex=omx_codec_output_port; + req_callback.nIndex=OMX_IndexConfigBufferStall; + req_callback.bEnable=OMX_TRUE; + error=OMX_SetConfig(omx_vid_dec,OMX_IndexConfigRequestCallback,&req_callback); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigRequestCallback failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!PrepareInputBufsOMX()) { clock_mutex.Unlock(); @@ -1698,6 +1731,48 @@ int VideoOMX::clearEvents() return 1; } +void VideoOMX::checkForStalledBuffers() +{ + //Log::getInstance()->log("Video", Log::DEBUG, "Check stalled"); + omx_event_mutex.Lock(); + list::iterator itty=omx_events.begin(); + while (itty!=omx_events.end()) { + VPE_OMX_EVENT current=*itty; + if (current.event_type==OMX_EventParamOrConfigChanged && current.data1==omx_codec_output_port + && current.handle==omx_vid_dec && current.data2==OMX_IndexConfigBufferStall) { + OMX_ERRORTYPE error; + OMX_CONFIG_BUFFERSTALLTYPE stall_conf; + memset(&stall_conf,0,sizeof(stall_conf)); + stall_conf.nSize=sizeof(stall_conf); + stall_conf.nVersion.nVersion=OMX_VERSION; + stall_conf.nPortIndex=omx_codec_output_port; + stall_conf.nDelay=200000; + clock_mutex.Lock(); + error=OMX_GetConfig(omx_vid_dec,OMX_IndexConfigBufferStall,&stall_conf); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Get OMX_IndexConfigBufferStall failed %x", error); + clock_mutex.Unlock(); + omx_event_mutex.Unlock(); + return ; + } + clock_mutex.Unlock(); + if (stall_conf.bStalled==OMX_TRUE) { + omx_vid_stalled=true; + Log::getInstance()->log("Video", Log::DEBUG, "Video decoder stalled! %d", stall_conf.nDelay); + } else { + omx_vid_stalled=false; + Log::getInstance()->log("Video", Log::DEBUG, "Video decoder unstalled! %d",stall_conf.nDelay); + } + omx_events.erase(itty); + break; + } + itty++; + } + omx_event_mutex.Unlock(); +} + + + int VideoOMX::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2) //needs to be called with locked mutex { @@ -1756,7 +1831,7 @@ int VideoOMX::PrepareInputBufsOMX() //needs to be called with locked mutex port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment);*/ port_def_type.nBufferCountActual=100; - port_def_type.nBufferSize=max(port_def_type.nBufferSize,200000); // for transcoder important + port_def_type.nBufferSize=max(port_def_type.nBufferSize,150000); // for transcoder important error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type); @@ -1831,6 +1906,7 @@ int VideoOMX::DestroyInputBufsOMX() //need s to be called with locked mutex } + int VideoOMX::FlushRenderingPipe() { OMX_ERRORTYPE error; @@ -2667,6 +2743,15 @@ bool VideoOMX::DrainTargetBufferFull() input_bufs_omx_mutex.Lock(); full=(input_bufs_omx_free.size()==0); input_bufs_omx_mutex.Unlock(); + checkForStalledBuffers(); // check if the decoder has a problem + if (full && omx_vid_stalled && !omx_first_frame) { + omx_vid_stalled=false; + Log::getInstance()->log("Video", Log::DEBUG, "Decoder is stalled, do a reset!"); + clock_mutex.Lock(); + FlushRenderingPipe(); + omx_first_frame=true; + clock_mutex.Unlock(); + } return full; } @@ -2718,12 +2803,14 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet, if (!omx_running) return 0; // if we are not runnig do not do this + if (isClockPaused()) return 0; //Block if we pause // Log::getInstance()->log("Video", Log::DEBUG, "DMP mark 1"); //Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX time %lld",packet.presentation_time); + OMX_ERRORTYPE error; /*First Check, if we have an video sample*/ diff --git a/videoomx.h b/videoomx.h index 400b084..66a901c 100644 --- a/videoomx.h +++ b/videoomx.h @@ -206,6 +206,7 @@ class VideoOMX : public Video int EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait); int DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait=true); int clearEvents(); + void checkForStalledBuffers(); int setClockExecutingandRunning(); @@ -249,6 +250,9 @@ class VideoOMX : public Video OMX_U32 omx_shed_clock_port; OMX_U32 omx_clock_output_port; // OMX_NALUFORMATSTYPE omx_nalu_format; + bool omx_vid_stalled; + + -- 2.39.5