From 0c1fc978146aeb80d968d0b27abe70bf84c62ed4 Mon Sep 17 00:00:00 2001 From: Benny Wong Date: Wed, 30 Sep 2009 08:21:56 -0500 Subject: To get GetState to block for pending state transitions to complete for video encode Originally from: https://partner.source.android.com/g/#change,1200 --- .../video_encode/inc/OMX_VideoEnc_Utils.h | 31 +++--- .../video_encode/src/OMX_VideoEnc_Utils.c | 105 ++++++++++++++++++--- .../openmax_il/video_encode/src/OMX_VideoEncoder.c | 96 +++++++++++++++---- 3 files changed, 191 insertions(+), 41 deletions(-) (limited to 'omx') diff --git a/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h b/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h index 9788089..a4f3b9d 100644 --- a/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h +++ b/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h @@ -653,20 +653,26 @@ typedef struct VIDENC_COMPONENT_PRIVATE OMX_Event InIdle_event; OMX_U8 InIdle_goingtoloaded; #endif - unsigned int nEncodingPreset; - VIDENC_AVC_NAL_FORMAT AVCNALFormat; - OMX_BOOL bMVDataEnable; - OMX_BOOL bResyncDataEnable; - IH264VENC_Intra4x4Params intra4x4EnableIdc; - OMX_U32 maxMVperMB; - #ifdef RESOURCE_MANAGER_ENABLED - RMPROXY_CALLBACKTYPE cRMCallBack; - #endif - OMX_BOOL bPreempted; - OMX_VIDEO_CODINGTYPE compressionFormats[3]; + unsigned int nEncodingPreset; + VIDENC_AVC_NAL_FORMAT AVCNALFormat; + OMX_BOOL bMVDataEnable; + OMX_BOOL bResyncDataEnable; + IH264VENC_Intra4x4Params intra4x4EnableIdc; + OMX_U32 maxMVperMB; +#ifdef RESOURCE_MANAGER_ENABLED + RMPROXY_CALLBACKTYPE cRMCallBack; +#endif + OMX_BOOL bPreempted; + OMX_VIDEO_CODINGTYPE compressionFormats[3]; OMX_COLOR_FORMATTYPE colorFormats[3]; struct OMX_TI_Debug dbg; PV_OMXComponentCapabilityFlagsType* pCapabilityFlags; + + /* Reference count for pending state change requests */ + OMX_U32 nPendingStateChangeRequests; + pthread_mutex_t mutexStateChangeRequest; + pthread_cond_t StateChangeCondition; + } VIDENC_COMPONENT_PRIVATE; typedef OMX_ERRORTYPE (*fpo)(OMX_HANDLETYPE); @@ -731,4 +737,7 @@ void OMX_VIDENC_ResourceManagerCallBack(RMPROXY_COMMANDDATATYPE cbData); OMX_U32 GetMaxAVCBufferSize(OMX_U32 width, OMX_U32 height); +OMX_ERRORTYPE AddStateTransition(VIDENC_COMPONENT_PRIVATE* pComponentPrivate); +OMX_ERRORTYPE RemoveStateTransition(VIDENC_COMPONENT_PRIVATE* pComponentPrivate, OMX_BOOL bEnableSignal); + #endif diff --git a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c index 391a724..4982cf4 100644 --- a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c +++ b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c @@ -1504,21 +1504,27 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetIdle(VIDENC_COMPONENT_PRIVATE* pCo } if (eError != OMX_ErrorNone) { - OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, + OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventError, OMX_ErrorHardware, OMX_TI_ErrorSevere, NULL); } - if (eError == OMX_ErrorNone) - { - pComponentPrivate->eState = OMX_StateIdle; + if (eError == OMX_ErrorNone) { + + pComponentPrivate->eState = OMX_StateIdle; #ifdef __PERF_INSTRUMENTATION__ PERF_Boundary(pComponentPrivate->pPERFcomp, PERF_BoundaryComplete | PERF_BoundarySetup); #endif - OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, + + /* Decrement reference count with signal enabled */ + if(RemoveStateTransition(pComponentPrivate, 1) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } + + OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateIdle, @@ -1539,6 +1545,12 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetIdle(VIDENC_COMPONENT_PRIVATE* pCo PERF_Boundary(pComponentPrivate->pPERFcomp, PERF_BoundaryComplete | PERF_BoundarySetup); #endif + + /* Decrement reference count with signal enabled */ + if(RemoveStateTransition(pComponentPrivate, 1) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } + OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventCmdComplete, OMX_CommandStateSet, @@ -1741,17 +1753,24 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetIdle(VIDENC_COMPONENT_PRIVATE* pCo #endif OMX_PRBUFFER2(pComponentPrivate->dbg, "Flushing Pipes!\n"); - eError = OMX_VIDENC_EmptyDataPipes (pComponentPrivate); + eError = OMX_VIDENC_EmptyDataPipes (pComponentPrivate); OMX_DBG_BAIL_IF_ERROR(eError, pComponentPrivate->dbg, OMX_PRBUFFER3, "Flushing pipes failed (%x).\n", eError); - pComponentPrivate->eState = OMX_StateIdle; - OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, + pComponentPrivate->eState = OMX_StateIdle; + + /* Decrement reference count with signal enabled */ + if(RemoveStateTransition(pComponentPrivate, 1) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } + + OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateIdle, NULL); - break; + break; + default: OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventError, @@ -1864,6 +1883,12 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetExecuting(VIDENC_COMPONENT_PRIVATE PERF_Boundary(pComponentPrivate->pPERFcomp, PERF_BoundaryStart | PERF_BoundarySteadyState); #endif + + /* Decrement reference count with signal enabled */ + if(RemoveStateTransition(pComponentPrivate, 1) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } + /*Send state change notificaiton to Application*/ OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventCmdComplete, @@ -1954,6 +1979,10 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetPause (VIDENC_COMPONENT_PRIVATE* p pComponentPrivate->eState = OMX_StatePause; + /* Decrement reference count with signal enabled */ + if(RemoveStateTransition(pComponentPrivate, 1) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventCmdComplete, @@ -2008,7 +2037,7 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetLoaded (VIDENC_COMPONENT_PRIVATE* break; case OMX_StateWaitForResources: OMX_PRSTATE2(pComponentPrivate->dbg, "Transitioning from WFR to Loaded\n"); - #ifdef RESOURCE_MANAGER_ENABLED +#ifdef RESOURCE_MANAGER_ENABLED if (pPortDefOut->format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) { /* TODO: Disable RM Send for now */ @@ -2054,8 +2083,13 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetLoaded (VIDENC_COMPONENT_PRIVATE* NULL); break; } - #endif - pComponentPrivate->eState = OMX_StateLoaded; +#endif + pComponentPrivate->eState = OMX_StateLoaded; + /* Decrement reference count with signal enabled */ + if(RemoveStateTransition(pComponentPrivate, 1) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } + #ifdef __PERF_INSTRUMENTATION__ PERF_Boundary(pComponentPrivate->pPERFcomp, @@ -2165,6 +2199,12 @@ OMX_ERRORTYPE OMX_VIDENC_HandleCommandStateSetLoaded (VIDENC_COMPONENT_PRIVATE* PERF_Boundary(pComponentPrivate->pPERFcomp, PERF_BoundaryComplete | PERF_BoundaryCleanup); #endif + + /* Decrement reference count with signal enabled */ + if(RemoveStateTransition(pComponentPrivate, 1) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } + OMX_VIDENC_EVENT_HANDLER(pComponentPrivate, OMX_EventCmdComplete, OMX_CommandStateSet, @@ -4053,3 +4093,44 @@ OMX_U32 GetMaxAVCBufferSize(OMX_U32 width, OMX_U32 height) /*150(bytes) = 1200(bits)/8 SN release notes*/ return 150*MaxCPB; } + +OMX_ERRORTYPE AddStateTransition(VIDENC_COMPONENT_PRIVATE* pComponentPrivate) { + + OMX_ERRORTYPE eError = OMX_ErrorNone; + + if(pthread_mutex_lock(&pComponentPrivate->mutexStateChangeRequest)) { + return OMX_ErrorUndefined; + } + + /* Increment state change request reference count */ + pComponentPrivate->nPendingStateChangeRequests++; + + if(pthread_mutex_unlock(&pComponentPrivate->mutexStateChangeRequest)) { + return OMX_ErrorUndefined; + } + + return eError; +} + +OMX_ERRORTYPE RemoveStateTransition(VIDENC_COMPONENT_PRIVATE* pComponentPrivate, OMX_BOOL bEnableSignal) { + OMX_ERRORTYPE eError = OMX_ErrorNone; + + /* Decrement state change request reference count*/ + if(pthread_mutex_lock(&pComponentPrivate->mutexStateChangeRequest)) { + return OMX_ErrorUndefined; + } + + pComponentPrivate->nPendingStateChangeRequests--; + + /* If there are no more pending requests, signal the thread waiting on this*/ + if(!pComponentPrivate->nPendingStateChangeRequests && bEnableSignal) { + pthread_cond_signal(&(pComponentPrivate->StateChangeCondition)); + } + + if(pthread_mutex_unlock(&pComponentPrivate->mutexStateChangeRequest)) { + return OMX_ErrorUndefined; + } + + return eError; +} + diff --git a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c index 05c5f4e..3998db3 100644 --- a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c +++ b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c @@ -998,6 +998,15 @@ sDynamicFormat = getenv("FORMAT"); OMX_CreateEvent(&(pComponentPrivate->InLoaded_event)); OMX_CreateEvent(&(pComponentPrivate->InIdle_event)); #endif + + if(pthread_mutex_init(&pComponentPrivate->mutexStateChangeRequest, NULL)) { + return OMX_ErrorUndefined; + } + + if(pthread_cond_init (&pComponentPrivate->StateChangeCondition, NULL)) { + return OMX_ErrorUndefined; + } + OMX_CONF_CMD_BAIL: OMX_PRINT2(dbg, "Component Init Exit\n"); return eError; @@ -1158,30 +1167,32 @@ static OMX_ERRORTYPE SendCommand (OMX_IN OMX_HANDLETYPE hComponent, switch (Cmd) { case OMX_CommandStateSet: + /* Add a pending transition */ + if(AddStateTransition(pComponentPrivate) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } #ifdef __KHRONOS_CONF__ - if(nParam1 == OMX_StateLoaded && - pComponentPrivate->eState == OMX_StateIdle) - { + if(nParam1 == OMX_StateLoaded && pComponentPrivate->eState == OMX_StateIdle) { pComponentPrivate->bPassingIdleToLoaded = OMX_TRUE; } #endif OMX_PRCOMM2(pComponentPrivate->dbg, "Write to cmd pipe!\n"); nRet = write(pComponentPrivate->nCmdPipe[1], &Cmd, sizeof(Cmd)); - if (nRet == -1) - { - OMX_DBG_SET_ERROR_BAIL(eError, OMX_ErrorUndefined, - pComponentPrivate->dbg, OMX_PRCOMM4, - "Failed to write to cmd pipe.\n"); + if (nRet == -1) { + /* Decrement reference count without generating any signal */ + if(RemoveStateTransition(pComponentPrivate, 0) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } } nRet = write(pComponentPrivate->nCmdDataPipe[1], &nParam1, sizeof(nParam1)); - if (nRet == -1) - { - OMX_DBG_SET_ERROR_BAIL(eError, OMX_ErrorUndefined, - pComponentPrivate->dbg, OMX_PRCOMM4, - "Failed to write to cmd pipe.\n"); + if (nRet == -1) { + /* Decrement reference count without generating any signal */ + if(RemoveStateTransition(pComponentPrivate, 0) != OMX_ErrorNone) { + return OMX_ErrorUndefined; + } } break; case OMX_CommandFlush: @@ -2618,17 +2629,63 @@ static OMX_ERRORTYPE GetState (OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_STATETYPE* pState) { OMX_ERRORTYPE eError = OMX_ErrorNone; + OMX_COMPONENTTYPE* pHandle = NULL; VIDENC_COMPONENT_PRIVATE* pComponentPrivate = NULL; + struct timespec abs_time = {0,0}; + int nPendingStateChangeRequests = 0; + int ret = 0; + /* Set to sufficiently high value */ + int mutex_timeout = 3; - OMX_CONF_CHECK_CMD(hComponent, ((OMX_COMPONENTTYPE *) hComponent)->pComponentPrivate, 1); + if(hComponent == NULL || pState == NULL) { + return OMX_ErrorBadParameter; + } - pComponentPrivate = (VIDENC_COMPONENT_PRIVATE*)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate); - OMX_DBG_CHECK_CMD(pComponentPrivate->dbg, pState, 1, 1); + pHandle = (OMX_COMPONENTTYPE*)hComponent; + pComponentPrivate = (VIDENC_COMPONENT_PRIVATE*)pHandle->pComponentPrivate; + /* Retrieve current state */ + if (pHandle && pHandle->pComponentPrivate) { + /* Check for any pending state transition requests */ + if(pthread_mutex_lock(&pComponentPrivate->mutexStateChangeRequest)) { + return OMX_ErrorUndefined; + } + nPendingStateChangeRequests = pComponentPrivate->nPendingStateChangeRequests; + if(!nPendingStateChangeRequests) { + if(pthread_mutex_unlock(&pComponentPrivate->mutexStateChangeRequest)) { + return OMX_ErrorUndefined; + } - *pState = pComponentPrivate->eState; + /* No pending state transitions */ + *pState = ((VIDENC_COMPONENT_PRIVATE*)pHandle->pComponentPrivate)->eState; + eError = OMX_ErrorNone; + } + else { + /* Wait for component to complete state transition */ + clock_gettime(CLOCK_REALTIME, &abs_time); + abs_time.tv_sec += mutex_timeout; + abs_time.tv_nsec = 0; + ret = pthread_cond_timedwait(&(pComponentPrivate->StateChangeCondition), &(pComponentPrivate->mutexStateChangeRequest), &abs_time); + if (!ret) { + /* Component has completed state transitions*/ + *pState = ((VIDENC_COMPONENT_PRIVATE*)pHandle->pComponentPrivate)->eState; + if(pthread_mutex_unlock(&pComponentPrivate->mutexStateChangeRequest)) { + return OMX_ErrorUndefined; + } + eError = OMX_ErrorNone; + } + else if(ret == ETIMEDOUT) { + /* Unlock mutex in case of timeout */ + pthread_mutex_unlock(&pComponentPrivate->mutexStateChangeRequest); + return OMX_ErrorTimeout; + } + } + } + else { + eError = OMX_ErrorInvalidComponent; + *pState = OMX_StateInvalid; + } -OMX_CONF_CMD_BAIL: return eError; } @@ -3098,6 +3155,9 @@ static OMX_ERRORTYPE ComponentDeInit(OMX_IN OMX_HANDLETYPE hComponent) PERF_Done(pComponentPrivate->pPERF); #endif + pthread_mutex_destroy(&pComponentPrivate->mutexStateChangeRequest); + pthread_cond_destroy(&pComponentPrivate->StateChangeCondition); + if (pComponentPrivate != NULL) { VIDENC_FREE(pComponentPrivate, pMemoryListHead, dbg); -- cgit v1.2.3