/** This function is used to process the input buffer and provide one output buffer */ void omx_video_scheduler_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* pInputBuffer, OMX_BUFFERHEADERTYPE* pOutputBuffer) { omx_video_scheduler_component_PrivateType* omx_video_scheduler_component_Private = openmaxStandComp->pComponentPrivate; omx_base_video_PortType *inPort = (omx_base_video_PortType *)omx_video_scheduler_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; omx_base_clock_PortType* pClockPort; OMX_BOOL SendFrame; pClockPort = (omx_base_clock_PortType*)omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX]; if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(inPort) && (omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) && ((pInputBuffer->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)){ SendFrame = omx_video_scheduler_component_ClockPortHandleFunction(omx_video_scheduler_component_Private, pInputBuffer); if(!SendFrame) pInputBuffer->nFilledLen = 0; } if((pInputBuffer->pBuffer != pOutputBuffer->pBuffer) && (pInputBuffer->nFilledLen > 0)){ memcpy(pOutputBuffer->pBuffer,pInputBuffer->pBuffer,pInputBuffer->nFilledLen); pOutputBuffer->nOffset = pInputBuffer->nOffset; } pOutputBuffer->nFilledLen = pInputBuffer->nFilledLen; pInputBuffer->nFilledLen=0; }
/** This is the central function for component processing. It * is executed in a separate thread, is synchronized with * semaphores at each port, those are released each time a new buffer * is available on the given port. */ void* omx_base_sink_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_sink_PrivateType* omx_base_sink_Private = (omx_base_sink_PrivateType*)omx_base_component_Private; omx_base_PortType *pInPort = (omx_base_PortType *)omx_base_sink_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; tsem_t* pInputSem = pInPort->pBufferSem; queue_t* pInputQueue = pInPort->pBufferQueue; OMX_BUFFERHEADERTYPE* pInputBuffer = NULL; OMX_COMPONENTTYPE* target_component; OMX_BOOL isInputBufferNeeded = OMX_TRUE; int inBufExchanged = 0; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n", __func__); while(omx_base_component_Private->state == OMX_StateIdle || omx_base_component_Private->state == OMX_StateExecuting || omx_base_component_Private->state == OMX_StatePause || omx_base_component_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pInPort)) { pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); if(isInputBufferNeeded==OMX_FALSE) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning input buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s signalling flush all condition \n", __func__); tsem_up(omx_base_sink_Private->flush_all_condition); tsem_down(omx_base_sink_Private->flush_condition); pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); /*No buffer to process. So wait here*/ if((pInputSem->semval==0 && isInputBufferNeeded==OMX_TRUE ) && (omx_base_sink_Private->state != OMX_StateLoaded && omx_base_sink_Private->state != OMX_StateInvalid)) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer \n"); tsem_down(omx_base_sink_Private->bMgmtSem); } if(omx_base_sink_Private->state == OMX_StateLoaded || omx_base_sink_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_FULL_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer semval=%d \n",pInputSem->semval); if(pInputSem->semval>0 && isInputBufferNeeded==OMX_TRUE ) { tsem_down(pInputSem); if(pInputQueue->nelem>0){ inBufExchanged++; isInputBufferNeeded=OMX_FALSE; pInputBuffer = dequeue(pInputQueue); if(pInputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL input buffer!!\n"); break; } } } if(isInputBufferNeeded==OMX_FALSE) { if(pInputBuffer->nFlags==OMX_BUFFERFLAG_EOS) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Detected EOS flags in input buffer\n"); (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ 0, /* The commands was a OMX_CommandStateSet */ pInputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ NULL); pInputBuffer->nFlags=0; } target_component=(OMX_COMPONENTTYPE*)pInputBuffer->hMarkTargetComponent; if(target_component==(OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ 0, /* The state has been changed in message->messageParam2 */ pInputBuffer->pMarkData); } else if(pInputBuffer->hMarkTargetComponent!=NULL){ /*If this is not the target component then pass the mark*/ DEBUG(DEB_LEV_FULL_SEQ, "Can't Pass Mark. This is a Sink!!\n"); } if (omx_base_sink_Private->BufferMgmtCallback && pInputBuffer->nFilledLen > 0) { (*(omx_base_sink_Private->BufferMgmtCallback))(openmaxStandComp, pInputBuffer); } else { /*If no buffer management call back the explicitly consume input buffer*/ pInputBuffer->nFilledLen = 0; } /*Input Buffer has been completely consumed. So, get new input buffer*/ if(omx_base_sink_Private->state==OMX_StatePause && !PORT_IS_BEING_FLUSHED(pInPort)) { /*Waiting at paused state*/ tsem_wait(omx_base_sink_Private->bStateSem); } /*Input Buffer has been completely consumed. So, return input buffer*/ if(pInputBuffer->nFilledLen==0) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded = OMX_TRUE; } } } DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); return NULL; }
void* omx_clocksrc_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_clocksrc_component_PrivateType* omx_clocksrc_component_Private = (omx_clocksrc_component_PrivateType*)omx_base_component_Private; omx_base_clock_PortType *pOutPort[MAX_CLOCK_PORTS]; tsem_t* pOutputSem[MAX_CLOCK_PORTS]; queue_t* pOutputQueue[MAX_CLOCK_PORTS]; OMX_BUFFERHEADERTYPE* pOutputBuffer[MAX_CLOCK_PORTS]; OMX_BOOL isOutputBufferNeeded[MAX_CLOCK_PORTS],bPortsBeingFlushed = OMX_FALSE; int i,j,outBufExchanged[MAX_CLOCK_PORTS]; for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { pOutPort[i] = (omx_base_clock_PortType *)omx_clocksrc_component_Private->ports[i]; pOutputSem[i] = pOutPort[i]->pBufferSem; pOutputQueue[i] = pOutPort[i]->pBufferQueue; pOutputBuffer[i] = NULL; isOutputBufferNeeded[i] = OMX_TRUE; outBufExchanged[i] = 0; } DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); while(omx_clocksrc_component_Private->state == OMX_StateIdle || omx_clocksrc_component_Private->state == OMX_StateExecuting || omx_clocksrc_component_Private->state == OMX_StatePause || omx_clocksrc_component_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { bPortsBeingFlushed |= PORT_IS_BEING_FLUSHED(pOutPort[i]); } while(bPortsBeingFlushed) { pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { if(isOutputBufferNeeded[i]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[i])) { pOutPort[i]->ReturnBufferFunction((omx_base_PortType*)pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[1]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer for port %i\n",i); } } tsem_up(omx_clocksrc_component_Private->flush_all_condition); tsem_down(omx_clocksrc_component_Private->flush_condition); pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); bPortsBeingFlushed = OMX_FALSE; for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { bPortsBeingFlushed |= PORT_IS_BEING_FLUSHED(pOutPort[i]); } } pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); /*Wait for clock state event*/ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Waiting for clock event\n",__func__); tsem_down(omx_clocksrc_component_Private->clockEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s clock event occured semval=%d \n",__func__,omx_clocksrc_component_Private->clockEventSem->semval); /*If port is not tunneled then simply return the buffer except paused state*/ if(omx_clocksrc_component_Private->transientState == OMX_TransStatePauseToExecuting) { for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { if(!PORT_IS_TUNNELED(pOutPort[i])) { if(pOutputSem[i]->semval>0 && isOutputBufferNeeded[i]==OMX_TRUE ) { tsem_down(pOutputSem[i]); if(pOutputQueue[i]->nelem>0){ outBufExchanged[i]++; isOutputBufferNeeded[i]=OMX_FALSE; pOutputBuffer[i] = dequeue(pOutputQueue[i]); if(pOutputBuffer[i] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!!\n"); break; } } } if(isOutputBufferNeeded[i]==OMX_FALSE) { /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if(pOutputBuffer[i]->nFilledLen!=0) { DEBUG(DEB_LEV_ERR, "In %s Returning Output nFilledLen=%d (line=%d)\n", __func__,(int)pOutputBuffer[i]->nFilledLen,__LINE__); pOutPort[i]->ReturnBufferFunction((omx_base_PortType*)pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[i]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; } } } } omx_clocksrc_component_Private->transientState = OMX_TransStateMax; } if(omx_clocksrc_component_Private->state == OMX_StateLoaded || omx_clocksrc_component_Private->state == OMX_StateInvalid || omx_clocksrc_component_Private->transientState == OMX_TransStateIdleToLoaded || omx_clocksrc_component_Private->transientState == OMX_TransStateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting (line %d)\n",__func__,__LINE__); break; } for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { if(pOutPort[i]->sMediaTime.eUpdateType == OMX_TIME_UpdateClockStateChanged || pOutPort[i]->sMediaTime.eUpdateType == OMX_TIME_UpdateScaleChanged || pOutPort[i]->sMediaTime.eUpdateType == OMX_TIME_UpdateRequestFulfillment) { if((isOutputBufferNeeded[i]==OMX_TRUE && pOutputSem[i]->semval==0) && (omx_clocksrc_component_Private->state != OMX_StateLoaded && omx_clocksrc_component_Private->state != OMX_StateInvalid) && PORT_IS_ENABLED(pOutPort[i])) { //Signalled from EmptyThisBuffer or FillThisBuffer or some where else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer %i\n",i); tsem_down(omx_clocksrc_component_Private->bMgmtSem); } if(omx_clocksrc_component_Private->state == OMX_StateLoaded || omx_clocksrc_component_Private->state == OMX_StateInvalid || omx_clocksrc_component_Private->transientState == OMX_TransStateIdleToLoaded || omx_clocksrc_component_Private->transientState == OMX_TransStateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting (line %d)\n",__func__,__LINE__); break; } if(pOutputSem[i]->semval>0 && isOutputBufferNeeded[i]==OMX_TRUE ) { tsem_down(pOutputSem[i]); if(pOutputQueue[i]->nelem>0){ outBufExchanged[i]++; isOutputBufferNeeded[i]=OMX_FALSE; pOutputBuffer[i] = dequeue(pOutputQueue[i]); if(pOutputBuffer[i] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!!\n"); break; } } } else { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Output buffer not available Port %d (line=%d)\n",__func__,(int)i,__LINE__); /*Check if any dummy bMgmtSem signal and ports are flushing*/ pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); bPortsBeingFlushed = OMX_FALSE; for(j=0;j<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;j++) { bPortsBeingFlushed |= PORT_IS_BEING_FLUSHED(pOutPort[j]); } pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); if(bPortsBeingFlushed) { DEBUG(DEB_LEV_ERR, "In %s Ports are being flushed - breaking (line %d)\n",__func__,__LINE__); break; } } /*Process Output buffer of Port i */ if(isOutputBufferNeeded[i]==OMX_FALSE) { if (omx_clocksrc_component_Private->BufferMgmtCallback) { (*(omx_clocksrc_component_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer[i]); } else { /*If no buffer management call back then don't produce any output buffer*/ pOutputBuffer[i]->nFilledLen = 0; } /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if(pOutputBuffer[i]->nFilledLen!=0) { pOutPort[i]->ReturnBufferFunction((omx_base_PortType*)pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[i]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; } } } } DEBUG(DEB_LEV_SIMPLE_SEQ, "Sent Clock Event for all ports\n"); tsem_up(omx_clocksrc_component_Private->clockEventCompleteSem); } DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); return NULL; }
/** This is the central function for component processing. It * is executed in a separate thread, is synchronized with * semaphores at each port, those are released each time a new buffer * is available on the given port. */ void* omx_base_source_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_source_PrivateType* omx_base_source_Private = (omx_base_source_PrivateType*)omx_base_component_Private; omx_base_PortType *pOutPort = (omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX]; tsem_t* pOutputSem = pOutPort->pBufferSem; queue_t* pOutputQueue = pOutPort->pBufferQueue; OMX_BUFFERHEADERTYPE* pOutputBuffer = NULL; OMX_COMPONENTTYPE* target_component; OMX_BOOL isOutputBufferNeeded = OMX_TRUE; int outBufExchanged = 0; omx_base_source_Private->bellagioThreads->nThreadBufferMngtID = (long int)syscall(__NR_gettid); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s the thread ID is %i\n", __func__, (int)omx_base_source_Private->bellagioThreads->nThreadBufferMngtID); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n", __func__); while(omx_base_component_Private->state == OMX_StateIdle || omx_base_component_Private->state == OMX_StateExecuting || omx_base_component_Private->state == OMX_StatePause || omx_base_component_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_source_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pOutPort)) { pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); if(isOutputBufferNeeded == OMX_FALSE) { pOutPort->ReturnBufferFunction(pOutPort, pOutputBuffer); outBufExchanged--; pOutputBuffer = NULL; isOutputBufferNeeded = OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s signalling flush all condition \n", __func__); tsem_up(omx_base_source_Private->flush_all_condition); tsem_down(omx_base_source_Private->flush_condition); pthread_mutex_lock(&omx_base_source_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); /*No buffer to process. So wait here*/ if((isOutputBufferNeeded==OMX_TRUE && pOutputSem->semval==0) && (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid)) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer \n"); tsem_down(omx_base_source_Private->bMgmtSem); } if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_FULL_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer semval=%d \n",pOutputSem->semval); if(pOutputSem->semval > 0 && isOutputBufferNeeded == OMX_TRUE ) { tsem_down(pOutputSem); if(pOutputQueue->nelem>0){ outBufExchanged++; isOutputBufferNeeded = OMX_FALSE; pOutputBuffer = dequeue(pOutputQueue); if(pOutputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "In %s Had NULL output buffer!!\n",__func__); break; } } } if(isOutputBufferNeeded == OMX_FALSE) { if((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { pOutputBuffer->nFlags = 0; } if(omx_base_source_Private->pMark.hMarkTargetComponent != NULL){ pOutputBuffer->hMarkTargetComponent = omx_base_source_Private->pMark.hMarkTargetComponent; pOutputBuffer->pMarkData = omx_base_source_Private->pMark.pMarkData; omx_base_source_Private->pMark.hMarkTargetComponent = NULL; omx_base_source_Private->pMark.pMarkData = NULL; } target_component = (OMX_COMPONENTTYPE*)pOutputBuffer->hMarkTargetComponent; if(target_component == (OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ 0, /* The state has been changed in message->messageParam2 */ pOutputBuffer->pMarkData); } else if(pOutputBuffer->hMarkTargetComponent != NULL) { /*If this is not the target component then pass the mark*/ DEBUG(DEB_LEV_FULL_SEQ, "Pass Mark. This is a Source!!\n"); } if(omx_base_source_Private->state == OMX_StateExecuting) { if (omx_base_source_Private->BufferMgmtCallback && pOutputBuffer->nFilledLen == 0) { (*(omx_base_source_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer); } else { /*It no buffer management call back then don't produce any output buffer*/ pOutputBuffer->nFilledLen = 0; } } else { DEBUG(DEB_LEV_ERR, "In %s Received Buffer in non-Executing State(%x)\n", __func__, (int)omx_base_source_Private->state); } if(omx_base_source_Private->state == OMX_StatePause && !PORT_IS_BEING_FLUSHED(pOutPort)) { /*Waiting at paused state*/ tsem_wait(omx_base_source_Private->bStateSem); } if((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Detected EOS flags in output buffer\n"); (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ 0, /* The commands was a OMX_CommandStateSet */ pOutputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ NULL); //pOutputBuffer->nFlags = 0; omx_base_source_Private->bIsEOSReached = OMX_TRUE; } /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if((pOutputBuffer->nFilledLen != 0) || ((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) ==OMX_BUFFERFLAG_EOS) || (omx_base_source_Private->bIsEOSReached == OMX_TRUE)) { if((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nFlags=%x Name=%s \n", __func__, (int)pOutputBuffer->nFlags, omx_base_source_Private->name); pOutPort->ReturnBufferFunction(pOutPort, pOutputBuffer); outBufExchanged--; pOutputBuffer = NULL; isOutputBufferNeeded = OMX_TRUE; } } } DEBUG(DEB_LEV_SIMPLE_SEQ, "Exiting Buffer Management Thread\n"); return NULL; }
void* omx_base_source_twoport_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_source_PrivateType* omx_base_source_Private = (omx_base_source_PrivateType*)omx_base_component_Private; omx_base_PortType *pOutPort[2]; tsem_t* pOutputSem[2]; queue_t* pOutputQueue[2]; OMX_BUFFERHEADERTYPE* pOutputBuffer[2]; OMX_COMPONENTTYPE* target_component; OMX_BOOL isOutputBufferNeeded[2]; int i,outBufExchanged[2]; pOutPort[0]=(omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX]; pOutPort[1]=(omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX_1]; pOutputSem[0] = pOutPort[0]->pBufferSem; pOutputSem[1] = pOutPort[1]->pBufferSem; pOutputQueue[0] = pOutPort[0]->pBufferQueue; pOutputQueue[1] = pOutPort[1]->pBufferQueue; pOutputBuffer[1]= pOutputBuffer[0]=NULL; isOutputBufferNeeded[0]=isOutputBufferNeeded[1]=OMX_TRUE; outBufExchanged[0]=outBufExchanged[1]=0; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); while(omx_base_source_Private->state == OMX_StateIdle || omx_base_source_Private->state == OMX_StateExecuting || omx_base_source_Private->state == OMX_StatePause || omx_base_source_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_source_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1])) { pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); DEBUG(DEB_LEV_FULL_SEQ, "In %s 1 signalling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,outBufExchanged[0],isOutputBufferNeeded[0],outBufExchanged[1],isOutputBufferNeeded[1],pOutputSem[0]->semval,pOutputSem[1]->semval); if(isOutputBufferNeeded[1]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[1])) { pOutPort[1]->ReturnBufferFunction(pOutPort[1],pOutputBuffer[1]); outBufExchanged[1]--; pOutputBuffer[1]=NULL; isOutputBufferNeeded[1]=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output 1 buffer\n"); } if(isOutputBufferNeeded[0]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[0])) { pOutPort[0]->ReturnBufferFunction(pOutPort[0],pOutputBuffer[0]); outBufExchanged[0]--; pOutputBuffer[0]=NULL; isOutputBufferNeeded[0]=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output 0 buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s 2 signalling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,outBufExchanged[0],isOutputBufferNeeded[0],outBufExchanged[1],isOutputBufferNeeded[1],pOutputSem[0]->semval,pOutputSem[1]->semval); tsem_up(omx_base_source_Private->flush_all_condition); tsem_down(omx_base_source_Private->flush_condition); pthread_mutex_lock(&omx_base_source_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); /*No buffer to process. So wait here*/ if((isOutputBufferNeeded[0]==OMX_TRUE && pOutputSem[0]->semval==0) && (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid)) { //Signalled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer 0\n"); tsem_down(omx_base_source_Private->bMgmtSem); } if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } if((isOutputBufferNeeded[1]==OMX_TRUE && pOutputSem[1]->semval==0) && (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid) && !(PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1]))) { //Signalled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer 1\n"); tsem_down(omx_base_source_Private->bMgmtSem); } if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer 0 semval=%d \n",pOutputSem[0]->semval); if(pOutputSem[0]->semval>0 && isOutputBufferNeeded[0]==OMX_TRUE ) { tsem_down(pOutputSem[0]); if(pOutputQueue[0]->nelem>0){ outBufExchanged[0]++; isOutputBufferNeeded[0]=OMX_FALSE; pOutputBuffer[0] = dequeue(pOutputQueue[0]); if(pOutputBuffer[0] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!!\n"); break; } } } /*When we have input buffer to process then get one output buffer*/ if(pOutputSem[1]->semval>0 && isOutputBufferNeeded[1]==OMX_TRUE) { tsem_down(pOutputSem[1]); if(pOutputQueue[1]->nelem>0){ outBufExchanged[1]++; isOutputBufferNeeded[1]=OMX_FALSE; pOutputBuffer[1] = dequeue(pOutputQueue[1]); if(pOutputBuffer[1] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!! op is=%d,iq=%d\n",pOutputSem[1]->semval,pOutputQueue[1]->nelem); break; } } } for(i=0;i < (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts -1);i++) { if(omx_base_source_Private->ports[i]->sPortParam.eDomain!=OMX_PortDomainOther){ /* clock ports are not to be processed */ /*Process Output buffer of Port i */ if(isOutputBufferNeeded[i]==OMX_FALSE) { /*Pass the Mark to all outgoing buffers*/ if(omx_base_source_Private->pMark.hMarkTargetComponent != NULL){ pOutputBuffer[i]->hMarkTargetComponent = omx_base_source_Private->pMark.hMarkTargetComponent; pOutputBuffer[i]->pMarkData = omx_base_source_Private->pMark.pMarkData; } target_component=(OMX_COMPONENTTYPE*)pOutputBuffer[i]->hMarkTargetComponent; if(target_component==(OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_source_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_source_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ i, /* The state has been changed in message->messageParam2 */ pOutputBuffer[i]->pMarkData); } else if(pOutputBuffer[i]->hMarkTargetComponent!=NULL){ /*If this is not the target component then pass the mark*/ DEBUG(DEB_LEV_FULL_SEQ, "Pass Mark. This is a Source!!\n"); } if(omx_base_source_Private->state == OMX_StateExecuting) { if (omx_base_source_Private->BufferMgmtCallback && pOutputBuffer[i]->nFilledLen == 0) { (*(omx_base_source_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer[i]); } else { /*If no buffer management call back then don't produce any output buffer*/ pOutputBuffer[i]->nFilledLen = 0; } } else { DEBUG(DEB_LEV_ERR, "In %s Received Buffer in non-Executing State(%x)\n", __func__, (int)omx_base_source_Private->state); } if((pOutputBuffer[i]->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS && pOutputBuffer[i]->nFilledLen==0) { DEBUG(DEB_LEV_FULL_SEQ, "Detected EOS flags in input buffer filled len=%d\n", (int)pOutputBuffer[i]->nFilledLen); (*(omx_base_source_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_source_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ i, /* The commands was a OMX_CommandStateSet */ pOutputBuffer[i]->nFlags, /* The state has been changed in message->messageParam2 */ NULL); } if(omx_base_source_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1]))) { /*Waiting at paused state*/ tsem_wait(omx_base_component_Private->bStateSem); } /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if(pOutputBuffer[i]->nFilledLen!=0 || (pOutputBuffer[i]->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS){ pOutPort[i]->ReturnBufferFunction(pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[i]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; } } } } /*Clear the Mark*/ if(omx_base_source_Private->pMark.hMarkTargetComponent != NULL){ omx_base_source_Private->pMark.hMarkTargetComponent = NULL; omx_base_source_Private->pMark.pMarkData = NULL; } } DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); return NULL; }
OMX_BOOL omx_alsasink_component_ClockPortHandleFunction(omx_alsasink_component_PrivateType* omx_alsasink_component_Private, OMX_BUFFERHEADERTYPE* inputbuffer){ omx_base_clock_PortType* pClockPort; OMX_BUFFERHEADERTYPE* clockBuffer; OMX_TIME_MEDIATIMETYPE* pMediaTime; OMX_HANDLETYPE hclkComponent; OMX_TIME_CONFIG_TIMESTAMPTYPE sClientTimeStamp; OMX_ERRORTYPE err; OMX_BOOL SendFrame=OMX_TRUE; omx_base_audio_PortType *pAudioPort; int static count=0; //frame counter pClockPort = (omx_base_clock_PortType*)omx_alsasink_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX]; pAudioPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; hclkComponent = pClockPort->hTunneledComponent; setHeader(&pClockPort->sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE)); /* if first time stamp is received then notify the clock component */ if((inputbuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) { DEBUG(DEB_LEV_FULL_SEQ,"In %s first time stamp = %llx \n", __func__,inputbuffer->nTimeStamp); inputbuffer->nFlags = 0; hclkComponent = pClockPort->hTunneledComponent; setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeClientStartTime, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } if(!PORT_IS_BEING_FLUSHED(pAudioPort) && !PORT_IS_BEING_FLUSHED(pClockPort)) { tsem_down(pClockPort->pBufferSem); /* wait for state change notification from clock src*/ /* update the clock state and clock scale info into the alsa sink private data */ if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; omx_alsasink_component_Private->eState = pMediaTime->eState; omx_alsasink_component_Private->xScale = pMediaTime->xScale; pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); } } } /* do not send the data to alsa and return back, if the clock is not running or the scale is anything but 1*/ if(!(omx_alsasink_component_Private->eState==OMX_TIME_ClockStateRunning && (omx_alsasink_component_Private->xScale>>16)==1)){ inputbuffer->nFilledLen=0; //return; SendFrame = OMX_FALSE; return SendFrame; } /* check for any scale change information from the clock component */ if(pClockPort->pBufferSem->semval>0){ tsem_down(pClockPort->pBufferSem); if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { if(/*(omx_alsasink_component_Private->xScale>>16)==2 &&*/ (pMediaTime->xScale>>16)==1){ /* check with Q16 format only */ /* rebase the clock time base when turning to normal play mode*/ hclkComponent = pClockPort->hTunneledComponent; setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentAudioReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } } omx_alsasink_component_Private->xScale = pMediaTime->xScale; } pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); }
/** @brief the entry point for sending buffers to the alsa sink port * * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on * the nature of the port, that can be an input or output port. */ OMX_ERRORTYPE omx_alsasink_component_port_SendBufferFunction(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) { OMX_ERRORTYPE err; OMX_U32 portIndex; OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; OMX_BOOL SendFrame; omx_base_clock_PortType* pClockPort; int errQue; #if NO_GST_OMX_PATCH unsigned int i; #endif portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex); if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); return OMX_ErrorInvalidState; } if(omx_base_component_Private->state != OMX_StateExecuting && omx_base_component_Private->state != OMX_StatePause && omx_base_component_Private->state != OMX_StateIdle) { DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); return OMX_ErrorIncorrectStateOperation; } if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); return OMX_ErrorIncorrectStateOperation; } /* Temporarily disable this check for gst-openmax */ #if NO_GST_OMX_PATCH { OMX_BOOL foundBuffer = OMX_FALSE; if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { foundBuffer = OMX_TRUE; break; } } } if (!foundBuffer) { return OMX_ErrorBadParameter; } } #endif if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); return err; } pClockPort = (omx_base_clock_PortType*)omx_base_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX]; if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(openmaxStandPort) && (omx_base_component_Private->transientState != OMX_TransStateExecutingToIdle) && ((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)){ SendFrame = omx_alsasink_component_ClockPortHandleFunction((omx_alsasink_component_PrivateType*)omx_base_component_Private, pBuffer); /* drop the frame */ if(!SendFrame) pBuffer->nFilledLen=0; } /* And notify the buffer management thread we have a fresh new buffer to manage */ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ errQue = queue(openmaxStandPort->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(openmaxStandPort->pBufferSem); DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); tsem_up(omx_base_component_Private->bMgmtSem); }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); errQue = queue(openmaxStandPort->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(openmaxStandPort->pBufferSem); } else { // If port being flushed and not tunneled then return error DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); return OMX_ErrorIncorrectStateOperation; } return OMX_ErrorNone; }
OMX_BOOL omx_video_scheduler_component_ClockPortHandleFunction( omx_video_scheduler_component_PrivateType* omx_video_scheduler_component_Private, OMX_BUFFERHEADERTYPE* pInputBuffer){ omx_base_clock_PortType *pClockPort; OMX_HANDLETYPE hclkComponent; OMX_BUFFERHEADERTYPE* clockBuffer; OMX_TIME_MEDIATIMETYPE* pMediaTime; OMX_TIME_CONFIG_TIMESTAMPTYPE sClientTimeStamp; OMX_ERRORTYPE err; OMX_BOOL SendFrame; omx_base_video_PortType *pInputPort; pClockPort = (omx_base_clock_PortType*) omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX]; pInputPort = (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[0]; hclkComponent = pClockPort->hTunneledComponent; SendFrame = OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "In %s Clock Port is Tunneled. Sending Request\n", __func__); /* if first time stamp is received then notify the clock component */ if((pInputBuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) { DEBUG(DEB_LEV_FULL_SEQ," In %s first time stamp = %llx \n", __func__,pInputBuffer->nTimeStamp); pInputBuffer->nFlags = 0; hclkComponent = pClockPort->hTunneledComponent; setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeClientStartTime, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } tsem_down(pClockPort->pBufferSem); /* wait for state change notification */ /* update the clock state and clock scale info into the fbdev private data */ if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer=dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; omx_video_scheduler_component_Private->eState = pMediaTime->eState; omx_video_scheduler_component_Private->xScale = pMediaTime->xScale; pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); } } /* do not send the data to sink and return back, if the clock is not running*/ if(!omx_video_scheduler_component_Private->eState==OMX_TIME_ClockStateRunning){ pInputBuffer->nFilledLen=0; SendFrame = OMX_FALSE; return SendFrame; } /* check for any scale change information from the clock component */ if(pClockPort->pBufferSem->semval>0) { tsem_down(pClockPort->pBufferSem); if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { /* On scale change update the media time base */ sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } omx_video_scheduler_component_Private->frameDropFlag = OMX_TRUE; omx_video_scheduler_component_Private->dropFrameCount = 0; omx_video_scheduler_component_Private->xScale = pMediaTime->xScale; } pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); } } /* drop next seven frames on scale change and rebase the clock time base */ if(omx_video_scheduler_component_Private->frameDropFlag && omx_video_scheduler_component_Private->dropFrameCount<7) { //TODO - second check cond can be removed verify omx_video_scheduler_component_Private->dropFrameCount ++; if(omx_video_scheduler_component_Private->dropFrameCount==7) { /* rebase the clock time base */ setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } omx_video_scheduler_component_Private->frameDropFlag = OMX_FALSE; omx_video_scheduler_component_Private->dropFrameCount = 0; SendFrame = OMX_TRUE; } SendFrame = OMX_FALSE; } /* frame is not to be dropped so send the request for the timestamp for the data delivery */ if(SendFrame){ if(!PORT_IS_BEING_FLUSHED(pInputPort) && !PORT_IS_BEING_FLUSHED(pClockPort) && omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) { setHeader(&pClockPort->sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE)); pClockPort->sMediaTimeRequest.nMediaTimestamp = pInputBuffer->nTimeStamp; pClockPort->sMediaTimeRequest.nOffset = 100; /*set the requested offset */ pClockPort->sMediaTimeRequest.nPortIndex = pClockPort->nTunneledPort; pClockPort->sMediaTimeRequest.pClientPrivate = NULL; /* fill the appropriate value */ err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeMediaTimeRequest, &pClockPort->sMediaTimeRequest); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } if(!PORT_IS_BEING_FLUSHED(pInputPort) && !PORT_IS_BEING_FLUSHED(pClockPort) && omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) { tsem_down(pClockPort->pBufferSem); /* wait for the request fullfillment */ if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { /* update the media time base */ setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); // do not need to setHeader again do once at the top sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } omx_video_scheduler_component_Private->frameDropFlag = OMX_TRUE; omx_video_scheduler_component_Private->dropFrameCount = 0; omx_video_scheduler_component_Private->xScale = pMediaTime->xScale; } if(pMediaTime->eUpdateType==OMX_TIME_UpdateRequestFulfillment){ if((pMediaTime->nOffset)>0) { SendFrame=OMX_TRUE; }else { SendFrame = OMX_FALSE; } } pClockPort->ReturnBufferFunction((omx_base_PortType *)pClockPort,clockBuffer); } } } } return(SendFrame); }
/** @brief the entry point for sending buffers to the port * * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on * the nature of the port, that can be an input or output port. */ OMX_ERRORTYPE base_clock_port_SendBufferFunction( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) { OMX_ERRORTYPE err; OMX_U32 portIndex; OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; #if NO_GST_OMX_PATCH unsigned int i; #endif portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex); if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); return OMX_ErrorInvalidState; } if(omx_base_component_Private->state != OMX_StateExecuting && omx_base_component_Private->state != OMX_StatePause && omx_base_component_Private->state != OMX_StateIdle) { DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); return OMX_ErrorIncorrectStateOperation; } if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); return OMX_ErrorIncorrectStateOperation; } /* Temporarily disable this check for gst-openmax */ #if NO_GST_OMX_PATCH { OMX_BOOL foundBuffer = OMX_FALSE; if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { foundBuffer = OMX_TRUE; break; } } } if (!foundBuffer) { return OMX_ErrorBadParameter; } } #endif if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); return err; } /*If port is not tunneled then simply return the buffer except paused state*/ if (!PORT_IS_TUNNELED(openmaxStandPort) && (omx_base_component_Private->state != OMX_StatePause)) { openmaxStandPort->ReturnBufferFunction(openmaxStandPort,pBuffer); return OMX_ErrorNone; } /* And notify the buffer management thread we have a fresh new buffer to manage */ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ queue(openmaxStandPort->pBufferQueue, pBuffer); tsem_up(openmaxStandPort->pBufferSem); DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); tsem_up(omx_base_component_Private->bMgmtSem); }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); queue(openmaxStandPort->pBufferQueue, pBuffer); tsem_up(openmaxStandPort->pBufferSem); } else { // If port being flushed and not tunneled then return error DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); return OMX_ErrorIncorrectStateOperation; } return OMX_ErrorNone; }
/** This is the central function for component processing. It * is executed in a separate thread, is synchronized with * semaphores at each port, those are released each time a new buffer * is available on the given port. */ void* omx_base_filter_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_filter_PrivateType* omx_base_filter_Private = (omx_base_filter_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_PortType *pInPort=(omx_base_PortType *)omx_base_filter_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; omx_base_PortType *pOutPort=(omx_base_PortType *)omx_base_filter_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; tsem_t* pInputSem = pInPort->pBufferSem; tsem_t* pOutputSem = pOutPort->pBufferSem; queue_t* pInputQueue = pInPort->pBufferQueue; queue_t* pOutputQueue = pOutPort->pBufferQueue; OMX_BUFFERHEADERTYPE* pOutputBuffer=NULL; OMX_BUFFERHEADERTYPE* pInputBuffer=NULL; OMX_BOOL isInputBufferNeeded=OMX_TRUE,isOutputBufferNeeded=OMX_TRUE; int inBufExchanged=0,outBufExchanged=0; omx_base_filter_Private->bellagioThreads->nThreadBufferMngtID = (long int)syscall(__NR_gettid); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s of component %p\n", __func__, openmaxStandComp); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s the thread ID is %i\n", __func__, (int)omx_base_filter_Private->bellagioThreads->nThreadBufferMngtID); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); /* checks if the component is in a state able to receive buffers */ while(omx_base_filter_Private->state == OMX_StateIdle || omx_base_filter_Private->state == OMX_StateExecuting || omx_base_filter_Private->state == OMX_StatePause || omx_base_filter_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_filter_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort)) { pthread_mutex_unlock(&omx_base_filter_Private->flush_mutex); DEBUG(DEB_LEV_FULL_SEQ, "In %s 1 signaling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,inBufExchanged,isInputBufferNeeded,outBufExchanged,isOutputBufferNeeded,pInputSem->semval,pOutputSem->semval); if(isOutputBufferNeeded==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort)) { pOutPort->ReturnBufferFunction(pOutPort,pOutputBuffer); outBufExchanged--; pOutputBuffer=NULL; isOutputBufferNeeded=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer\n"); } if(isInputBufferNeeded==OMX_FALSE && PORT_IS_BEING_FLUSHED(pInPort)) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning input buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s 2 signaling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,inBufExchanged,isInputBufferNeeded,outBufExchanged,isOutputBufferNeeded,pInputSem->semval,pOutputSem->semval); tsem_up(omx_base_filter_Private->flush_all_condition); tsem_down(omx_base_filter_Private->flush_condition); pthread_mutex_lock(&omx_base_filter_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_filter_Private->flush_mutex); /*No buffer to process. So wait here*/ if((isInputBufferNeeded==OMX_TRUE && pInputSem->semval==0) && (omx_base_filter_Private->state != OMX_StateLoaded && omx_base_filter_Private->state != OMX_StateInvalid)) { //Signaled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next input/output buffer\n"); tsem_down(omx_base_filter_Private->bMgmtSem); } if(omx_base_filter_Private->state == OMX_StateLoaded || omx_base_filter_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } if((isOutputBufferNeeded==OMX_TRUE && pOutputSem->semval==0) && (omx_base_filter_Private->state != OMX_StateLoaded && omx_base_filter_Private->state != OMX_StateInvalid) && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { //Signaled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next input/output buffer\n"); tsem_down(omx_base_filter_Private->bMgmtSem); } if(omx_base_filter_Private->state == OMX_StateLoaded || omx_base_filter_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_FULL_SEQ, "Waiting for input buffer semval=%d in %s\n",pInputSem->semval, __func__); if(pInputSem->semval>0 && isInputBufferNeeded==OMX_TRUE ) { tsem_down(pInputSem); if(pInputQueue->nelem>0){ inBufExchanged++; isInputBufferNeeded=OMX_FALSE; pInputBuffer = dequeue(pInputQueue); if(pInputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL input buffer!!\n"); break; } } } /*When we have input buffer to process then get one output buffer*/ if(pOutputSem->semval>0 && isOutputBufferNeeded==OMX_TRUE) { tsem_down(pOutputSem); if(pOutputQueue->nelem>0){ outBufExchanged++; isOutputBufferNeeded=OMX_FALSE; pOutputBuffer = dequeue(pOutputQueue); if(pOutputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!! op is=%d,iq=%d\n",pOutputSem->semval,pOutputQueue->nelem); break; } } } if(isInputBufferNeeded==OMX_FALSE) { if(pInputBuffer->hMarkTargetComponent != NULL){ if((OMX_COMPONENTTYPE*)pInputBuffer->hMarkTargetComponent ==(OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_filter_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_filter_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ 0, /* The state has been changed in message->messageParam2 */ pInputBuffer->pMarkData); } else { /*If this is not the target component then pass the mark*/ omx_base_filter_Private->pMark.hMarkTargetComponent = pInputBuffer->hMarkTargetComponent; omx_base_filter_Private->pMark.pMarkData = pInputBuffer->pMarkData; } pInputBuffer->hMarkTargetComponent = NULL; } } if(isInputBufferNeeded==OMX_FALSE && isOutputBufferNeeded==OMX_FALSE) { if(omx_base_filter_Private->pMark.hMarkTargetComponent != NULL){ pOutputBuffer->hMarkTargetComponent = omx_base_filter_Private->pMark.hMarkTargetComponent; pOutputBuffer->pMarkData = omx_base_filter_Private->pMark.pMarkData; omx_base_filter_Private->pMark.hMarkTargetComponent = NULL; omx_base_filter_Private->pMark.pMarkData = NULL; } pOutputBuffer->nTimeStamp = pInputBuffer->nTimeStamp; if((pInputBuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) { DEBUG(DEB_LEV_FULL_SEQ, "Detected START TIME flag in the input buffer filled len=%d\n", (int)pInputBuffer->nFilledLen); pOutputBuffer->nFlags = pInputBuffer->nFlags; pInputBuffer->nFlags = 0; } if(omx_base_filter_Private->state == OMX_StateExecuting) { if (omx_base_filter_Private->BufferMgmtCallback && pInputBuffer->nFilledLen > 0) { (*(omx_base_filter_Private->BufferMgmtCallback))(openmaxStandComp, pInputBuffer, pOutputBuffer); } else { /*It no buffer management call back the explicitly consume input buffer*/ pInputBuffer->nFilledLen = 0; } } else if(!(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { DEBUG(DEB_LEV_ERR, "In %s Received Buffer in non-Executing State(%x)\n", __func__, (int)omx_base_filter_Private->state); } else { pInputBuffer->nFilledLen = 0; } if((pInputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS && pInputBuffer->nFilledLen==0) { DEBUG(DEB_LEV_FULL_SEQ, "Detected EOS flags in input buffer filled len=%d\n", (int)pInputBuffer->nFilledLen); pOutputBuffer->nFlags=pInputBuffer->nFlags; pInputBuffer->nFlags=0; (*(omx_base_filter_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_filter_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ pOutputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ NULL); omx_base_filter_Private->bIsEOSReached = OMX_TRUE; } if(omx_base_filter_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { /*Waiting at paused state*/ tsem_wait(omx_base_filter_Private->bStateSem); } /*If EOS and Input buffer Filled Len Zero then Return output buffer immediately*/ if((pOutputBuffer->nFilledLen != 0) || ((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) || (omx_base_filter_Private->bIsEOSReached == OMX_TRUE)) { pOutPort->ReturnBufferFunction(pOutPort,pOutputBuffer); outBufExchanged--; pOutputBuffer=NULL; isOutputBufferNeeded=OMX_TRUE; } } if(omx_base_filter_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { /*Waiting at paused state*/ tsem_wait(omx_base_filter_Private->bStateSem); } /*Input Buffer has been completely consumed. So, return input buffer*/ if((isInputBufferNeeded == OMX_FALSE) && (pInputBuffer->nFilledLen==0)) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded=OMX_TRUE; } } DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s of component %p\n", __func__, openmaxStandComp); return NULL; }
/** * Returns Input/Output Buffer to the IL client or Tunneled Component */ OMX_ERRORTYPE videoenc_port_ReturnBufferFunction( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE *pBuffer) { int errQue; OMX_ERRORTYPE eError = OMX_ErrorNone; omx_base_component_PrivateType *omx_base_component_Private = openmaxStandPort->standCompContainer->pComponentPrivate; omx_videoenc_PortType *omx_videoenc_Port = (omx_videoenc_PortType *)openmaxStandPort; queue_t *pQueue = omx_videoenc_Port->pBufferQueue; tsem_t *pSem = omx_videoenc_Port->pBufferSem; OMX_VCE_Buffers_List *pBuffersMng_List= &(omx_videoenc_Port->BuffersMng_List); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s for port %p\n", __func__, omx_videoenc_Port); OMX_BUFFERHEADERTYPE *pBuffer_ACTEXT = (OMX_BUFFERHEADERTYPE *)pBuffer; if( omx_videoenc_Port->sPortParam.eDir == OMX_DirOutput ) { eError = ReturnBuffer_BuffersMng(pBuffersMng_List, pBuffer_ACTEXT, omx_videoenc_Port->bIsStoreMediaData); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!ReturnBuffer_BuffersMng fail!%s,%d\n",__FILE__,__LINE__); return eError; } } #ifdef enable_gralloc if(pBuffer->nFilledLen == 0 && ((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) ) { DEBUG(DEB_LEV_ERR, "ReturnBufferFunction,input buffer is eos now!"); } else { eError = UnLock_VirAddr_BuffersMng(pBuffersMng_List, pBuffer_ACTEXT, omx_videoenc_Port->bIsStoreMediaData); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!UnLock_VirAddr_BuffersMng fail!%s,%d\n", __FILE__, __LINE__); return eError; } } #endif if (PORT_IS_TUNNELED(omx_videoenc_Port) && ! PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port)) { if (omx_videoenc_Port->sPortParam.eDir == OMX_DirInput) { pBuffer->nOutputPortIndex = omx_videoenc_Port->nTunneledPort; pBuffer->nInputPortIndex = omx_videoenc_Port->sPortParam.nPortIndex; eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->FillThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s eError %08x in FillThis Buffer from Component %s Non-Supplier\n", __func__, eError,omx_base_component_Private->name); } } else { pBuffer->nInputPortIndex = omx_videoenc_Port->nTunneledPort; pBuffer->nOutputPortIndex = omx_videoenc_Port->sPortParam.nPortIndex; eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->EmptyThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s eError %08x in EmptyThis Buffer from Component %s Non-Supplier\n", __func__, eError, omx_base_component_Private->name); } } } else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port) && !PORT_IS_BEING_FLUSHED(omx_videoenc_Port)) { if (omx_videoenc_Port->sPortParam.eDir == OMX_DirInput) { eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->FillThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in FillThis Buffer from Component %s Supplier\n", __func__, eError,omx_base_component_Private->name); /*If Error Occured then queue the buffer*/ errQue = queue(pQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(pSem); } } else { eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->EmptyThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in EmptyThis Buffer from Component %s Supplier\n", __func__, eError,omx_base_component_Private->name); /*If Error Occured then queue the buffer*/ errQue = queue(pQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(pSem); } } } else if (!PORT_IS_TUNNELED(omx_videoenc_Port)) { //here (*(omx_videoenc_Port->BufferProcessedCallback))( omx_videoenc_Port->standCompContainer, omx_base_component_Private->callbackData, pBuffer); } else { errQue = queue(pQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } omx_videoenc_Port->nNumBufferFlushed++; } DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s for port %p\n", __func__, omx_videoenc_Port); return OMX_ErrorNone; }
/** @brief the entry point for sending buffers to the port * * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on * the nature of the port, that can be an input or output port. */ OMX_ERRORTYPE videoenc_port_SendBufferFunction( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE *pBuffer) { int errQue; OMX_U32 portIndex; OMX_ERRORTYPE err = OMX_ErrorNone; OMX_COMPONENTTYPE *omxComponent = openmaxStandPort->standCompContainer; omx_videoenc_PortType *omx_videoenc_Port = (omx_videoenc_PortType *)openmaxStandPort; omx_base_component_PrivateType *omx_base_component_Private = (omx_base_component_PrivateType *)omxComponent->pComponentPrivate; OMX_VCE_Buffers_List *pBuffersMng_List= &(omx_videoenc_Port->BuffersMng_List); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s for port %p\n", __func__, omx_videoenc_Port); #if NO_GST_OMX_PATCH unsigned int i; #endif portIndex = (omx_videoenc_Port->sPortParam.eDir == OMX_DirInput) ? pBuffer->nInputPortIndex : pBuffer->nOutputPortIndex; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %d\n", __func__, portIndex); if (portIndex != omx_videoenc_Port->sPortParam.nPortIndex) { DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)omx_videoenc_Port->sPortParam.nPortIndex); return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); return OMX_ErrorInvalidState; } if(omx_base_component_Private->state != OMX_StateExecuting && omx_base_component_Private->state != OMX_StatePause && omx_base_component_Private->state != OMX_StateIdle) { DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); return OMX_ErrorIncorrectStateOperation; } if (!PORT_IS_ENABLED(omx_videoenc_Port) || (PORT_IS_BEING_DISABLED(omx_videoenc_Port) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port)) || ((omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle || omx_base_component_Private->transientState == OMX_TransStatePauseToIdle) && (PORT_IS_TUNNELED(omx_videoenc_Port) && !PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port)))) { DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex, omx_base_component_Private->name); return OMX_ErrorIncorrectStateOperation; } /* Temporarily disable this check for gst-openmax */ #if NO_GST_OMX_PATCH { OMX_BOOL foundBuffer = OMX_FALSE; if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { for(i=0; i < omx_videoenc_Port->sPortParam.nBufferCountActual; i++) { if (pBuffer->pBuffer == omx_videoenc_Port->pInternalBufferStorage[i]->pBuffer) { foundBuffer = OMX_TRUE; break; } } } if (!foundBuffer) { return OMX_ErrorBadParameter; } } #endif if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); return err; } /* And notify the buffer management thread we have a fresh new buffer to manage */ if(!PORT_IS_BEING_FLUSHED(omx_videoenc_Port) && \ !(PORT_IS_BEING_DISABLED(omx_videoenc_Port) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port))) { //here if(omx_videoenc_Port->bIsStoreMediaData == OMX_TRUE) { if((*(OMX_U32 *)pBuffer->pBuffer != kMetadataBufferTypeCameraSource_act) && \ (*(OMX_U32 *)pBuffer->pBuffer != kMetadataBufferTypeGrallocSource_act)) { DEBUG(DEB_LEV_ERR, "Warning!in StoreMediaData mode,but the buffer (%x) is not kMetadataBufferTypeCameraSource_act!\n", (int)*(OMX_U32 *)pBuffer->pBuffer); } } if(omx_videoenc_Port->ringbuffer == OMX_TRUE && omx_videoenc_Port->sPortParam.nPortIndex == OMX_BASE_FILTER_OUTPUTPORT_INDEX) { err = Free_UseRingBuffer_BuffersMng(&omx_videoenc_Port->BuffersMng_List,omx_videoenc_Port->bufferpool,pBuffer, omx_videoenc_Port->sPortParam.nBufferSize); if( err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!In %s: SendBuffer_BuffersMng\n", __func__); return err; } } else { err = SendBuffer_BuffersMng(pBuffersMng_List,pBuffer,omx_videoenc_Port->bIsStoreMediaData,omx_videoenc_Port->sPortParam.eDir); if( err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!In %s: SendBuffer_BuffersMng\n", __func__); return err; } } errQue = queue(omx_videoenc_Port->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(omx_videoenc_Port->pBufferSem); DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n", __func__, (int)portIndex); tsem_up(omx_base_component_Private->bMgmtSem); } else if(PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port)) { DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", __func__, omx_base_component_Private->name, (int)omx_videoenc_Port->sPortParam.nPortIndex); errQue = queue(omx_videoenc_Port->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(omx_videoenc_Port->pBufferSem); } else { // If port being flushed and not tunneled then return error DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); return OMX_ErrorIncorrectStateOperation; } DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s for port %p\n", __func__, omx_videoenc_Port); return OMX_ErrorNone; }