From d490ac71f2b015ddd89777657431a934bb49fe65 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sat, 8 Sep 2012 12:35:25 +0200 Subject: [PATCH] Fix deadlocks, due to thread cancel inside omx_emptythisbuffer --- audioomx.cc | 15 ++++++++------- videoomx.cc | 37 ++++++++++++++++++++++++++++--------- videoomx.h | 1 + 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/audioomx.cc b/audioomx.cc index 2d8ec88..aa8da5b 100644 --- a/audioomx.cc +++ b/audioomx.cc @@ -951,11 +951,11 @@ int AudioOMX::DeAllocateCodecsOMX() Log::getInstance()->log("Audio", Log::DEBUG, "enter deallocatecodecsomx"); - video->LockClock(); + Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 1"); if (cur_input_buf_omx) { cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS; - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,cur_input_buf_omx); + OMX_ERRORTYPE error=video->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,cur_input_buf_omx); if (error!=OMX_ErrorNone) { Log::getInstance()->log("Audio", Log::DEBUG, "OMX_EmptyThisBuffer 6 failed %x", error); } @@ -964,6 +964,7 @@ int AudioOMX::DeAllocateCodecsOMX() } Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 2"); + video->LockClock(); if (omx_aud_rend/*dec*/) { // first stop the omx elements /* if (!video->ChangeComponentState(omx_aud_dec,OMX_StateIdle)) { @@ -1299,7 +1300,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, if (packet.disconti) { firstsynched = false; if (cur_input_buf_omx) { - OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/, + OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx); if (error != OMX_ErrorNone) { Log::getInstance()->log("Audio", Log::DEBUG, @@ -1315,7 +1316,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, lastAType = packet.type; if (cur_input_buf_omx) { - OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/, + OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx); if (error != OMX_ErrorNone) { Log::getInstance()->log("Audio", Log::DEBUG, @@ -1339,7 +1340,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, if (packet.synched) { if (cur_input_buf_omx) { cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; - OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/, + OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx); if (error != OMX_ErrorNone) { Log::getInstance()->log("Audio", Log::DEBUG, @@ -1490,7 +1491,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, // I doubt that this will ever happen Log::getInstance()->log("Audio", Log::DEBUG, "P 2 Time code %lld pts %lld", lastreftimeOMX, packet.pts); - OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/, + OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx); if (error != OMX_ErrorNone) { Log::getInstance()->log("Audio", Log::DEBUG, @@ -1540,7 +1541,7 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, if (cur_input_buf_omx->nFilledLen) { Log::getInstance()->log("Audio", Log::DEBUG, "P 3 Time code %lld pts %lld", lastreftimeOMX, packet.pts); - error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx); + error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx); if (error != OMX_ErrorNone) { Log::getInstance()->log("Audio", Log::DEBUG, "OMX_EmptyThisBuffer 5 failed %x", error); diff --git a/videoomx.cc b/videoomx.cc index f15779b..ddd0b55 100644 --- a/videoomx.cc +++ b/videoomx.cc @@ -1194,17 +1194,17 @@ int VideoOMX::DeAllocateCodecsOMX() omx_running=false; Log::getInstance()->log("Video", Log::DEBUG, "enter deallocatecodecsomx"); - clock_mutex.Lock(); + if (cur_input_buf_omx) { cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS; - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); + OMX_ERRORTYPE error=ProtOMXEmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); if (error!=OMX_ErrorNone) { Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); } cur_input_buf_omx=NULL;//write out old data } - + clock_mutex.Lock(); if (omx_vid_dec) { // first stop the omx elements if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) { @@ -1680,6 +1680,23 @@ void VideoOMX::AdjustAudioPTS(long long pts) //} } +OMX_ERRORTYPE VideoOMX::ProtOMXEmptyThisBuffer(OMX_HANDLETYPE handle, OMX_BUFFERHEADERTYPE* buffer) +{ + // protect the call to empty this buffer + int oldcancelstate; + int oldcanceltype; + pthread_testcancel(); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate); + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype); + clock_mutex.Lock(); + OMX_ERRORTYPE ret_val; + ret_val=OMX_EmptyThisBuffer(handle,buffer); + clock_mutex.Unlock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + pthread_testcancel(); + return ret_val; +} void VideoOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) { @@ -1742,7 +1759,7 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet, if (packet.disconti) { firstsynched=false; if (cur_input_buf_omx) { - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); + OMX_ERRORTYPE error=ProtOMXEmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); } @@ -1764,7 +1781,7 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet, if ( packet.synched ) { if (cur_input_buf_omx) { cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_ENDOFFRAME; - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); + OMX_ERRORTYPE error=ProtOMXEmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); } @@ -1842,7 +1859,7 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet, *samplepos+=cancopy; // push old buffer out - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); + OMX_ERRORTYPE error=ProtOMXEmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); } @@ -1935,7 +1952,7 @@ bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) { } cur_input_buf_omx->nTimeStamp = 0; - OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_vid_dec, + OMX_ERRORTYPE error = ProtOMXEmptyThisBuffer(omx_vid_dec, cur_input_buf_omx); if (error != OMX_ErrorNone) { Log::getInstance()->log("Video", Log::DEBUG, @@ -1995,7 +2012,7 @@ bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) { } cur_input_buf_omx->nTimeStamp = 0; - OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_vid_dec, cur_input_buf_omx); + OMX_ERRORTYPE error = ProtOMXEmptyThisBuffer(omx_vid_dec, cur_input_buf_omx); if (error != OMX_ErrorNone) { Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); @@ -2011,8 +2028,10 @@ int VideoOMX::EnterIframePlayback() { clock_mutex.Lock(); if (cur_input_buf_omx) { - OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_vid_dec, + clock_mutex.Unlock(); + OMX_ERRORTYPE error = ProtOMXEmptyThisBuffer(omx_vid_dec, cur_input_buf_omx); + clock_mutex.Lock(); if (error != OMX_ErrorNone) { Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); diff --git a/videoomx.h b/videoomx.h index b006f88..72c52b9 100644 --- a/videoomx.h +++ b/videoomx.h @@ -186,6 +186,7 @@ class VideoOMX : public Video int getClockVideoandInit(); void LockClock() {clock_mutex.Lock();}; void UnlockClock() {clock_mutex.Unlock();}; + OMX_ERRORTYPE ProtOMXEmptyThisBuffer(OMX_HANDLETYPE handle, OMX_BUFFERHEADERTYPE* buffer); void clockPause(); void clockUnpause(); -- 2.39.2