QUEUE_ERRORTYPE Queue::Get(fsl_osal_ptr pMsg) { QNODE *pQNode = NULL; if(bBlocking == E_FSL_OSAL_TRUE) fsl_osal_sem_wait(usedNodesSem); else { if(fsl_osal_sem_trywait(usedNodesSem) != E_FSL_OSAL_SUCCESS) return QUEUE_NOT_READY; } fsl_osal_mutex_lock(lock); if(pHead == NULL) { fsl_osal_mutex_unlock(lock); return QUEUE_OVERFLOW; } pQNode = pHead; pHead = pHead->NextNode; fsl_osal_memcpy(pMsg, pQNode->pMsg, nMsgSize); pQNode->NextNode = pFreeNodes; pFreeNodes = pQNode; nQSize --; if(pHead == NULL) pTail = NULL; fsl_osal_sem_post(freeNodesSem); fsl_osal_mutex_unlock(lock); return QUEUE_SUCCESS; }
fsl_osal_u32 Queue::Size() { fsl_osal_u32 ret = 0; fsl_osal_mutex_lock(lock); ret = nQSize; fsl_osal_mutex_unlock(lock); return ret; }
OMX_ERRORTYPE Clock::SetStartTime( OMX_TIME_CONFIG_TIMESTAMPTYPE *pStartTime) { OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_TIME_MEDIATIMETYPE UpdateType; OMX_U32 nPortIndex; OMX_U32 i; if(CurState != OMX_TIME_ClockStateWaitingForStartTime) return OMX_ErrorIncorrectStateOperation; OMX_CHECK_STRUCT(pStartTime, OMX_TIME_CONFIG_TIMESTAMPTYPE, ret); if(ret != OMX_ErrorNone) return ret; nPortIndex = pStartTime->nPortIndex; if(nPortIndex >= nPorts) { LOG_ERROR("Bad port index[%d] when set start time to clock.\n", nPortIndex); return OMX_ErrorBadPortIndex; } fsl_osal_mutex_lock(lock); SegmentStartTime = MIN(SegmentStartTime, (OMX_U64)pStartTime->nTimestamp); LOG_DEBUG("%s,%d,set start time from port %d, ts %lld,SegmentStartTime %lld\n",__FUNCTION__,__LINE__,nPortIndex,pStartTime->nTimestamp,SegmentStartTime); StartTimeWaitMask &= ~(1 << nPortIndex); if(StartTimeWaitMask) { fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; } /* start media clock now */ CurState = OMX_TIME_ClockStateRunning; sState.eState = CurState; MediaTimeBase = SegmentStartTime; LOG_DEBUG("%s,%d,start new segment,set media time base to %lld\n",__FUNCTION__,__LINE__,MediaTimeBase); CurMediaAndWallTime(NULL, &WallTimeBase); OMX_INIT_STRUCT(&UpdateType, OMX_TIME_MEDIATIMETYPE); UpdateType.eUpdateType = OMX_TIME_UpdateClockStateChanged; UpdateType.eState = sState.eState; UpdateType.nMediaTimestamp = SegmentStartTime; SegmentStartTime = -1L; fsl_osal_mutex_unlock(lock); for(i=0; i<PORT_NUM; i++) { if(ports[i]->IsEnabled() == OMX_TRUE) MediaTimeUpdate(&UpdateType, i); } return OMX_ErrorNone; }
QUEUE_ERRORTYPE Queue::Get(fsl_osal_ptr pMsg, fsl_osal_u32 nIndex) { QNODE *pQNode, *pQNodePrev = NULL; fsl_osal_u32 i; if(nIndex > nQSize) { fsl_osal_memset(pMsg, 0, nMsgSize); return QUEUE_FAILURE; } if(nIndex == 1) return Get(pMsg); if(bBlocking == E_FSL_OSAL_TRUE) fsl_osal_sem_wait(usedNodesSem); else { if(fsl_osal_sem_trywait(usedNodesSem) != E_FSL_OSAL_SUCCESS) return QUEUE_NOT_READY; } fsl_osal_mutex_lock(lock); if(pHead == NULL) { fsl_osal_mutex_unlock(lock); return QUEUE_OVERFLOW; } pQNodePrev = pHead; pQNode = pQNodePrev->NextNode; for(i=2; i<nIndex; i++){ pQNodePrev = pQNodePrev->NextNode; pQNode = pQNode->NextNode; } fsl_osal_memcpy(pMsg, pQNode->pMsg, nMsgSize); pQNodePrev->NextNode = pQNode->NextNode; pQNode->NextNode = pFreeNodes; pFreeNodes = pQNode; nQSize --; if(pTail == pQNode) pTail = pQNodePrev; fsl_osal_sem_post(freeNodesSem); fsl_osal_mutex_unlock(lock); return QUEUE_SUCCESS; }
OMX_ERRORTYPE Clock::SetRefTime( OMX_TIME_CONFIG_TIMESTAMPTYPE *pTs, OMX_TIME_REFCLOCKTYPE eClock) { if(eClock != RefClock) return OMX_ErrorNone; fsl_osal_mutex_lock(lock); CurMediaAndWallTime(NULL, &WallTimeBase); if(pTs->nTimestamp >= 0) MediaTimeBase = pTs->nTimestamp; fsl_osal_mutex_unlock(lock); LOG_DEBUG("%s,%d,Set reference time with ts %lld,from ref clock %d, result wall time base %lld\n",__FUNCTION__,__LINE__,MediaTimeBase, RefClock,WallTimeBase); return OMX_ErrorNone; }
OMX_ERRORTYPE IpulibRender::ResetDevice() { fsl_osal_mutex_lock(lock); CloseDevice(); OMX_STATETYPE eState = OMX_StateInvalid; GetState(&eState); if(eState == OMX_StatePause && bSuspend != OMX_TRUE) StartDeviceInPause(); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; }
OMX_PTR PlatformResourceMgr::GetHwBuffer( OMX_PTR pVirtualAddr) { PLATFORM_DATA *pData = NULL; OMX_PTR ptr = NULL; fsl_osal_mutex_lock(lock); pData = (PLATFORM_DATA*) SearchData(pVirtualAddr); if(pData == NULL) { fsl_osal_mutex_unlock(lock); return NULL; } ptr = pData->pPhyiscAddr; fsl_osal_mutex_unlock(lock); return ptr; }
OMX_ERRORTYPE PlatformResourceMgr::RemoveHwBuffer( OMX_PTR pVirtualAddr) { PLATFORM_DATA *pData = NULL; fsl_osal_mutex_lock(lock); pData = (PLATFORM_DATA*) SearchData(pVirtualAddr); if(pData == NULL) { fsl_osal_mutex_unlock(lock); return OMX_ErrorUndefined; } PlatformDataList->Remove(pData); FSL_FREE(pData); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; }
OMX_ERRORTYPE V4lRender::SetDeviceDisplayRegion() { OMX_ERRORTYPE ret = OMX_ErrorNone; if(device <= 0) return OMX_ErrorNotReady; fsl_osal_mutex_lock(lock); V4lStreamOff(OMX_FALSE); ret = V4lSetOutputCrop(); if(ret != OMX_ErrorNone) { fsl_osal_mutex_unlock(lock); return ret; } fsl_osal_mutex_unlock(lock); return ret; }
OMX_ERRORTYPE Clock::SetTimeScale( OMX_TIME_CONFIG_SCALETYPE *pScale) { OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_TIME_MEDIATIMETYPE UpdateType; OMX_U32 i; OMX_CHECK_STRUCT(pScale, OMX_TIME_CONFIG_SCALETYPE, ret); if(ret != OMX_ErrorNone) return ret; if(pScale->xScale == Scale) { LOG_INFO("Set same scale value:[%d:%d]\n", pScale->xScale, Scale); return OMX_ErrorNone; } fsl_osal_mutex_lock(lock); CurMediaAndWallTime(&MediaTimeBase, NULL); CurMediaAndWallTime(NULL, &WallTimeBase); Scale = pScale->xScale; OMX_INIT_STRUCT(&UpdateType, OMX_TIME_MEDIATIMETYPE); UpdateType.eUpdateType = OMX_TIME_UpdateScaleChanged; UpdateType.xScale = Scale; fsl_osal_mutex_unlock(lock); for(i=0; i<PORT_NUM; i++) { if(ports[i]->IsEnabled() == OMX_TRUE) MediaTimeUpdate(&UpdateType, i); } fsl_osal_cond_broadcast(Cond); return ret; }
OMX_ERRORTYPE PlatformResourceMgr::AddHwBuffer( OMX_PTR pPhyiscAddr, OMX_PTR pVirtualAddr) { PLATFORM_DATA *pData = NULL; pData = (PLATFORM_DATA*)FSL_MALLOC(sizeof(PLATFORM_DATA)); if(pData == NULL) return OMX_ErrorInsufficientResources; pData->pVirtualAddr = pVirtualAddr; pData->pPhyiscAddr = pPhyiscAddr; fsl_osal_mutex_lock(lock); if(LIST_SUCCESS != PlatformDataList->Add(pData)) { FSL_FREE(pData); fsl_osal_mutex_unlock(lock); return OMX_ErrorUndefined; } fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; }
OMX_ERRORTYPE Clock::SetRefClock( OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE *pRefClock) { OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_CHECK_STRUCT(pRefClock, OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE, ret); if(ret != OMX_ErrorNone) return ret; LOG_DEBUG("%s,%d,Set reference clock %d, curr ref clock %d\n",__FUNCTION__,__LINE__, pRefClock->eClock, RefClock); if(RefClock == pRefClock->eClock) { LOG_INFO("Set same reference clock:[%d:%d]\n", pRefClock->eClock, RefClock); return OMX_ErrorNone; } fsl_osal_mutex_lock(lock); RefClock = pRefClock->eClock; fsl_osal_cond_broadcast(Cond); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; }
OMX_ERRORTYPE IpulibRender::WriteDevice( OMX_BUFFERHEADERTYPE *pBufferHdr) { OMX_ERRORTYPE ret = OMX_ErrorNone; fsl_osal_mutex_lock(lock); if(sCapture.eType == CAP_THUMBNAL) { fsl_osal_memcpy(sCapture.pBuffer, pBufferHdr->pBuffer, pBufferHdr->nFilledLen); sCapture.nFilledLen = pBufferHdr->nFilledLen; bCaptureFrameDone = OMX_TRUE; ports[0]->SendBuffer(pBufferHdr); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; } if(pBufferHdr->nFilledLen == 0) { ports[0]->SendBuffer(pBufferHdr); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; } pShowFrame = pBufferHdr->pBuffer; nFrameLen = pBufferHdr->nFilledLen; if(bSuspend == OMX_TRUE) { ports[0]->SendBuffer(pBufferHdr); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; } OMX_PTR pFrame = NULL; GetHwBuffer(pBufferHdr->pBuffer, &pFrame); if(bInitDev != OMX_TRUE) { ret = Init(); if(ret != OMX_ErrorNone) { ports[0]->SendBuffer(pBufferHdr); fsl_osal_mutex_unlock(lock); return ret; } bInitDev = OMX_TRUE; } ret = RenderFrame(pFrame); if(ret != OMX_ErrorNone) { ports[0]->SendBuffer(pBufferHdr); fsl_osal_mutex_unlock(lock); return ret; } ports[0]->SendBuffer(pBufferHdr); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; }
OMX_ERRORTYPE V4lRender::SetOutputMode() { OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_S32 output; OMX_STATETYPE eState = OMX_StateInvalid; if(device <= 0) return OMX_ErrorNotReady; if (bInTransitState == OMX_TRUE) return OMX_ErrorNotReady; fsl_osal_mutex_lock(lock); bInTransitState == OMX_TRUE; GetState(&eState); if(eState == OMX_StatePause) V4lStreamOff(OMX_TRUE); else V4lStreamOff(OMX_FALSE); output = 3; if(sOutputMode.bTv == OMX_TRUE) { if(sOutputMode.eFbLayer == LAYER1) output = 5; if(sOutputMode.eFbLayer == LAYER2) switch_to_tv(sOutputMode.eTvMode); } else { if(sOutputMode.eFbLayer == LAYER2) switch_to_lcd(); } fsl_osal_memcpy(&sRectOut, &sOutputMode.sRectOut, sizeof(OMX_CONFIG_RECTTYPE)); fsl_osal_memcpy(&sRectIn, &sOutputMode.sRectIn, sizeof(OMX_CONFIG_RECTTYPE)); ret = V4lSetOutputLayer(output); if(ret != OMX_ErrorNone) goto err; ret = V4lSetInputCrop(); if(ret != OMX_ErrorNone) goto err; ret = V4lSetOutputCrop(); if(ret != OMX_ErrorNone) goto err; eRotation = sOutputMode.eRotation; ret = V4lSetRotation(); if(ret != OMX_ErrorNone) goto err; if(eState == OMX_StatePause) V4lStreamOnInPause(); fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; err: fsl_osal_mutex_unlock(lock); return ret; }
OMX_ERRORTYPE IpulibRender::RenderSetConfig( OMX_INDEXTYPE nParamIndex, OMX_PTR pStructure) { OMX_ERRORTYPE ret = OMX_ErrorNone; switch (nParamIndex) { case OMX_IndexOutputMode: { OMX_CONFIG_OUTPUTMODE *pOutputMode; pOutputMode = (OMX_CONFIG_OUTPUTMODE*)pStructure; CHECK_STRUCT(pOutputMode, OMX_CONFIG_OUTPUTMODE, ret); fsl_osal_memcpy(&sOutputMode, pOutputMode, sizeof(OMX_CONFIG_OUTPUTMODE)); fsl_osal_memcpy(&sRectIn, &pOutputMode->sRectIn, sizeof(OMX_CONFIG_RECTTYPE)); fsl_osal_memcpy(&sRectOut, &pOutputMode->sRectOut, sizeof(OMX_CONFIG_RECTTYPE)); eRotation = pOutputMode->eRotation; ResetDevice(); } break; case OMX_IndexConfigCaptureFrame: { OMX_CONFIG_CAPTUREFRAME *pCapture; pCapture = (OMX_CONFIG_CAPTUREFRAME*)pStructure; CHECK_STRUCT(pCapture, OMX_CONFIG_CAPTUREFRAME, ret); sCapture.eType = pCapture->eType; sCapture.pBuffer = pCapture->pBuffer; bCaptureFrameDone = OMX_FALSE; if (sCapture.eType == CAP_SNAPSHOT) { if(pShowFrame == NULL) { ret = OMX_ErrorUndefined; break; } fsl_osal_memcpy(sCapture.pBuffer, pShowFrame, nFrameLen); sCapture.nFilledLen = nFrameLen; bCaptureFrameDone = OMX_TRUE; } } break; case OMX_IndexSysSleep: OMX_CONFIG_SYSSLEEP *pSysSleep; pSysSleep = (OMX_CONFIG_SYSSLEEP *)pStructure; bSuspend = pSysSleep->bSleep; fsl_osal_mutex_lock(lock); if(OMX_TRUE == bSuspend) { CloseDevice(); } else { OMX_STATETYPE eState = OMX_StateInvalid; GetState(&eState); if(eState == OMX_StatePause) StartDeviceInPause(); } fsl_osal_mutex_unlock(lock); break; default: ret = OMX_ErrorUnsupportedIndex; break; } return ret; }
OMX_ERRORTYPE V4lRender::WriteDevice( OMX_BUFFERHEADERTYPE *pBufferHdr) { OMX_ERRORTYPE ret = OMX_ErrorNone; FB_DATA *fb; OMX_U32 nIndex; fsl_osal_mutex_lock(lock); LOG_DEBUG("WriteDevice: %p, nAllocating %d, FilledLen %d, nRenderFrames %d, nFrameBuffer %d, hMarkTargetComponent %p\n", pBufferHdr, nAllocating, pBufferHdr->nFilledLen, nRenderFrames, nFrameBuffer, pBufferHdr->hMarkTargetComponent); if(nAllocating > 0) { V4lSearchBuffer(pBufferHdr->pBuffer, &nIndex); BufferHdrs[nIndex] = pBufferHdr; //LOG_DEBUG("nIndex %d, nQueuedBuffer %d\n", nIndex, nQueuedBuffer); } else { nIndex = (nRenderFrames % (nFrameBuffer-V4L_DUMMY_BUF_NUM)); fb = &fb_data[nIndex]; fsl_osal_memcpy(fb->pVirtualAddr, pBufferHdr->pBuffer, pBufferHdr->nFilledLen); BufferHdrs[nIndex] = pBufferHdr; } if(sCapture.eType == CAP_THUMBNAL) { CaptureFrame(nIndex); bCaptureFrameDone = OMX_TRUE; ports[IN_PORT]->SendBuffer(BufferHdrs[nIndex]); BufferHdrs[nIndex] = NULL; fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; } V4lQueueBuffer(nIndex); #ifdef USING_DUMMY_WORKAROUND if((2==nQueuedBuffer)&&(bFlushState==OMX_TRUE)) { OMX_U32 nTmp; //make sure: always one valid buffer(except dummy buffer) will be dequeue later //otherwise: pause+seek will be very slow or timeout ASSERT(OMX_TRUE==bDummyValid); V4lDeQueueBuffer(&nTmp); ASSERT(nTmp==(nFrameBuffer-V4L_DUMMY_BUF_NUM)); memcpy(fb_data[nFrameBuffer-V4L_DUMMY_BUF_NUM].pVirtualAddr,fb_data[nIndex].pVirtualAddr,fb_data[nIndex].nLength); V4lQueueBuffer(nFrameBuffer-V4L_DUMMY_BUF_NUM); bFlushState=OMX_FALSE; } #else if(pBufferHdr->hMarkTargetComponent != NULL) { LOG_DEBUG("requeue current buffer to steam on v4l\n"); if(bV4lNewApi) { //will bring unrecoverable error if the same buffer is queue twice //no display : pause -> seek -> no display -> resume -> display V4lQueueBuffer((nIndex+1)%nFrameBuffer); //enable another buffer if you want to have display when pause+seek } else { V4lQueueBuffer(nIndex); } //nQueuedBuffer--; //nRenderFrames--; } #endif nIndex = 0; ret = V4lDeQueueBuffer(&nIndex); if(ret == OMX_ErrorNone) { OMX_BUFFERHEADERTYPE *pHdr = NULL; pHdr = BufferHdrs[nIndex]; BufferHdrs[nIndex] = NULL; ports[IN_PORT]->SendBuffer(pHdr); //LOG_DEBUG("dequeued nIndex %d\n", nIndex); } #ifndef USING_DUMMY_WORKAROUND // when seeking in pause state, previous frame has been flushed in FlushComponent(), here no chance to call SendBuffer() and // OMX_EventMark will not be sent , and then seek action fails. So we add this SendEventMark() to trigger OMX_EventMark. if(pBufferHdr->hMarkTargetComponent != NULL) { LOG_DEBUG("Send eventMark in pause state\n"); ports[0]->SendEventMark(pBufferHdr); } #endif fsl_osal_mutex_unlock(lock); return OMX_ErrorNone; }
OMX_ERRORTYPE Clock::SetState( OMX_TIME_CONFIG_CLOCKSTATETYPE *pState) { OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_TIME_CLOCKSTATE NewState; OMX_TIME_MEDIATIMETYPE UpdateType; OMX_U32 i; OMX_CHECK_STRUCT(pState, OMX_TIME_CONFIG_CLOCKSTATETYPE, ret); if(ret != OMX_ErrorNone) return ret; NewState = pState->eState; if(NewState == CurState) { LOG_INFO("Set same state to clock: [%d:%d]\n", pState->eState, CurState); return OMX_ErrorNone; } fsl_osal_mutex_lock(lock); switch (NewState) { case OMX_TIME_ClockStateRunning: if(CurState == OMX_TIME_ClockStateWaitingForStartTime) { LOG_ERROR("Clock can't switch from WaitForStartTime to Running directly.\n"); ret = OMX_ErrorIncorrectStateTransition; goto err; } /* Stop -> Running */ fsl_osal_memcpy(&sState, pState, sizeof(OMX_TIME_CONFIG_CLOCKSTATETYPE)); SegmentStartTime = sState.nStartTime; break; case OMX_TIME_ClockStateWaitingForStartTime: if(CurState == OMX_TIME_ClockStateRunning) { LOG_ERROR("Clock can't switch from Running to WaitForStartTime.\n"); ret = OMX_ErrorIncorrectStateTransition; goto err; } /* Stop -> WaitForStartTime */ fsl_osal_memcpy(&sState, pState, sizeof(OMX_TIME_CONFIG_CLOCKSTATETYPE)); StartTimeWaitMask = sState.nWaitMask; break; case OMX_TIME_ClockStateStopped: /* Running->Stop / WaitForStartTime->Stop */ sState.eState = OMX_TIME_ClockStateStopped; break; default : LOG_ERROR("Invalid clock state setting: %d\n", pState->eState); ret = OMX_ErrorIncorrectStateTransition; goto err; } CurState = sState.eState; OMX_INIT_STRUCT(&UpdateType, OMX_TIME_MEDIATIMETYPE); UpdateType.eUpdateType = OMX_TIME_UpdateClockStateChanged; UpdateType.eState = sState.eState; fsl_osal_mutex_unlock(lock); for(i=0; i<PORT_NUM; i++) { if(ports[i]->IsEnabled() == OMX_TRUE) MediaTimeUpdate(&UpdateType, i); } if(sState.eState == OMX_TIME_ClockStateStopped) fsl_osal_cond_broadcast(Cond); return ret; err: fsl_osal_mutex_unlock(lock); return ret; }