OpenMAXBellagio 0.9.3
omx_base_filter.c
Go to the documentation of this file.
00001 
00028 #include <unistd.h>
00029 #include <asm/unistd.h>
00030 #include <omxcore.h>
00031 
00032 #include "omx_base_filter.h"
00033 
00034 OSCL_EXPORT_REF OMX_ERRORTYPE omx_base_filter_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName) {
00035   OMX_ERRORTYPE err;
00036   omx_base_filter_PrivateType* omx_base_filter_Private;
00037 
00038   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s of component %p\n", __func__, openmaxStandComp);
00039   if (openmaxStandComp->pComponentPrivate) {
00040     omx_base_filter_Private = (omx_base_filter_PrivateType*)openmaxStandComp->pComponentPrivate;
00041   } else {
00042     omx_base_filter_Private = calloc(1,sizeof(omx_base_filter_PrivateType));
00043     if (!omx_base_filter_Private) {
00044         DEBUG(DEB_LEV_ERR, "Insufficient memory in %s\n", __func__);
00045         return OMX_ErrorInsufficientResources;
00046     }
00047     openmaxStandComp->pComponentPrivate=omx_base_filter_Private;
00048   }
00049 
00050   /* Call the base class constructor */
00051   err = omx_base_component_Constructor(openmaxStandComp,cComponentName);
00052   if (err != OMX_ErrorNone) {
00053       DEBUG(DEB_LEV_ERR, "The base constructor failed in %s\n", __func__);
00054       return err;
00055   }
00056   /* here we can override whatever defaults the base_component constructor set
00057   * e.g. we can override the function pointers in the private struct */
00058   omx_base_filter_Private = openmaxStandComp->pComponentPrivate;
00059 
00060   omx_base_filter_Private->BufferMgmtFunction = omx_base_filter_BufferMgmtFunction;
00061 
00062   DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s of component %p\n", __func__, openmaxStandComp);
00063   return OMX_ErrorNone;
00064 }
00065 
00066 OSCL_EXPORT_REF OMX_ERRORTYPE omx_base_filter_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) {
00067     OMX_ERRORTYPE err;
00068       DEBUG(DEB_LEV_FUNCTION_NAME, "In %s of component %p\n", __func__, openmaxStandComp);
00069       err = omx_base_component_Destructor(openmaxStandComp);
00070       if (err != OMX_ErrorNone) {
00071           DEBUG(DEB_LEV_ERR, "The base component destructor failed\n");
00072           return err;
00073       }
00074       DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s of component %p\n", __func__, openmaxStandComp);
00075       return OMX_ErrorNone;
00076 }
00077 
00083 void* omx_base_filter_BufferMgmtFunction (void* param) {
00084   OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param;
00085   omx_base_filter_PrivateType* omx_base_filter_Private = (omx_base_filter_PrivateType*)openmaxStandComp->pComponentPrivate;
00086   omx_base_PortType *pInPort=(omx_base_PortType *)omx_base_filter_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
00087   omx_base_PortType *pOutPort=(omx_base_PortType *)omx_base_filter_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
00088   tsem_t* pInputSem = pInPort->pBufferSem;
00089   tsem_t* pOutputSem = pOutPort->pBufferSem;
00090   queue_t* pInputQueue = pInPort->pBufferQueue;
00091   queue_t* pOutputQueue = pOutPort->pBufferQueue;
00092   OMX_BUFFERHEADERTYPE* pOutputBuffer=NULL;
00093   OMX_BUFFERHEADERTYPE* pInputBuffer=NULL;
00094   OMX_BOOL isInputBufferNeeded=OMX_TRUE,isOutputBufferNeeded=OMX_TRUE;
00095   int inBufExchanged=0,outBufExchanged=0;
00096 
00097   omx_base_filter_Private->bellagioThreads->nThreadBufferMngtID = (long int)syscall(__NR_gettid);
00098   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s of component %p\n", __func__, openmaxStandComp);
00099   DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s the thread ID is %i\n", __func__, (int)omx_base_filter_Private->bellagioThreads->nThreadBufferMngtID);
00100 
00101   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00102   /* checks if the component is in a state able to receive buffers */
00103   while(omx_base_filter_Private->state == OMX_StateIdle || omx_base_filter_Private->state == OMX_StateExecuting ||  omx_base_filter_Private->state == OMX_StatePause ||
00104     omx_base_filter_Private->transientState == OMX_TransStateLoadedToIdle){
00105 
00106     /*Wait till the ports are being flushed*/
00107     pthread_mutex_lock(&omx_base_filter_Private->flush_mutex);
00108     while( PORT_IS_BEING_FLUSHED(pInPort) ||
00109            PORT_IS_BEING_FLUSHED(pOutPort)) {
00110       pthread_mutex_unlock(&omx_base_filter_Private->flush_mutex);
00111 
00112       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",
00113         __func__,inBufExchanged,isInputBufferNeeded,outBufExchanged,isOutputBufferNeeded,pInputSem->semval,pOutputSem->semval);
00114 
00115       if(isOutputBufferNeeded==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort)) {
00116         pOutPort->ReturnBufferFunction(pOutPort,pOutputBuffer);
00117         outBufExchanged--;
00118         pOutputBuffer=NULL;
00119         isOutputBufferNeeded=OMX_TRUE;
00120         DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer\n");
00121       }
00122 
00123       if(isInputBufferNeeded==OMX_FALSE && PORT_IS_BEING_FLUSHED(pInPort)) {
00124         pInPort->ReturnBufferFunction(pInPort,pInputBuffer);
00125         inBufExchanged--;
00126         pInputBuffer=NULL;
00127         isInputBufferNeeded=OMX_TRUE;
00128         DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning input buffer\n");
00129       }
00130 
00131       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",
00132         __func__,inBufExchanged,isInputBufferNeeded,outBufExchanged,isOutputBufferNeeded,pInputSem->semval,pOutputSem->semval);
00133 
00134       tsem_up(omx_base_filter_Private->flush_all_condition);
00135       tsem_down(omx_base_filter_Private->flush_condition);
00136       pthread_mutex_lock(&omx_base_filter_Private->flush_mutex);
00137     }
00138     pthread_mutex_unlock(&omx_base_filter_Private->flush_mutex);
00139 
00140     /*No buffer to process. So wait here*/
00141     if((isInputBufferNeeded==OMX_TRUE && pInputSem->semval==0) &&
00142       (omx_base_filter_Private->state != OMX_StateLoaded && omx_base_filter_Private->state != OMX_StateInvalid)) {
00143       //Signaled from EmptyThisBuffer or FillThisBuffer or some thing else
00144       DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next input/output buffer\n");
00145       tsem_down(omx_base_filter_Private->bMgmtSem);
00146 
00147     }
00148     if(omx_base_filter_Private->state == OMX_StateLoaded || omx_base_filter_Private->state == OMX_StateInvalid) {
00149       DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__);
00150       break;
00151     }
00152     if((isOutputBufferNeeded==OMX_TRUE && pOutputSem->semval==0) &&
00153       (omx_base_filter_Private->state != OMX_StateLoaded && omx_base_filter_Private->state != OMX_StateInvalid) &&
00154        !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) {
00155       //Signaled from EmptyThisBuffer or FillThisBuffer or some thing else
00156       DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next input/output buffer\n");
00157       tsem_down(omx_base_filter_Private->bMgmtSem);
00158 
00159     }
00160     if(omx_base_filter_Private->state == OMX_StateLoaded || omx_base_filter_Private->state == OMX_StateInvalid) {
00161       DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__);
00162       break;
00163     }
00164 
00165     DEBUG(DEB_LEV_FULL_SEQ, "Waiting for input buffer semval=%d in %s\n",pInputSem->semval, __func__);
00166     if(pInputSem->semval>0 && isInputBufferNeeded==OMX_TRUE ) {
00167       tsem_down(pInputSem);
00168       if(pInputQueue->nelem>0){
00169         inBufExchanged++;
00170         isInputBufferNeeded=OMX_FALSE;
00171         pInputBuffer = dequeue(pInputQueue);
00172         if(pInputBuffer == NULL){
00173           DEBUG(DEB_LEV_ERR, "Had NULL input buffer!!\n");
00174           break;
00175         }
00176       }
00177     }
00178     /*When we have input buffer to process then get one output buffer*/
00179     if(pOutputSem->semval>0 && isOutputBufferNeeded==OMX_TRUE) {
00180       tsem_down(pOutputSem);
00181       if(pOutputQueue->nelem>0){
00182         outBufExchanged++;
00183         isOutputBufferNeeded=OMX_FALSE;
00184         pOutputBuffer = dequeue(pOutputQueue);
00185         if(pOutputBuffer == NULL){
00186           DEBUG(DEB_LEV_ERR, "Had NULL output buffer!! op is=%d,iq=%d\n",pOutputSem->semval,pOutputQueue->nelem);
00187           break;
00188         }
00189       }
00190     }
00191 
00192     if(isInputBufferNeeded==OMX_FALSE) {
00193       if(pInputBuffer->hMarkTargetComponent != NULL){
00194         if((OMX_COMPONENTTYPE*)pInputBuffer->hMarkTargetComponent ==(OMX_COMPONENTTYPE *)openmaxStandComp) {
00195           /*Clear the mark and generate an event*/
00196           (*(omx_base_filter_Private->callbacks->EventHandler))
00197             (openmaxStandComp,
00198             omx_base_filter_Private->callbackData,
00199             OMX_EventMark, /* The command was completed */
00200             1, /* The commands was a OMX_CommandStateSet */
00201             0, /* The state has been changed in message->messageParam2 */
00202             pInputBuffer->pMarkData);
00203         } else {
00204           /*If this is not the target component then pass the mark*/
00205           omx_base_filter_Private->pMark.hMarkTargetComponent = pInputBuffer->hMarkTargetComponent;
00206           omx_base_filter_Private->pMark.pMarkData            = pInputBuffer->pMarkData;
00207         }
00208         pInputBuffer->hMarkTargetComponent = NULL;
00209       }
00210     }
00211 
00212     if(isInputBufferNeeded==OMX_FALSE && isOutputBufferNeeded==OMX_FALSE) {
00213 
00214       if(omx_base_filter_Private->pMark.hMarkTargetComponent != NULL){
00215         pOutputBuffer->hMarkTargetComponent = omx_base_filter_Private->pMark.hMarkTargetComponent;
00216         pOutputBuffer->pMarkData            = omx_base_filter_Private->pMark.pMarkData;
00217         omx_base_filter_Private->pMark.hMarkTargetComponent = NULL;
00218         omx_base_filter_Private->pMark.pMarkData            = NULL;
00219       }
00220 
00221       pOutputBuffer->nTimeStamp = pInputBuffer->nTimeStamp;
00222       if((pInputBuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) {
00223          DEBUG(DEB_LEV_FULL_SEQ, "Detected  START TIME flag in the input buffer filled len=%d\n", (int)pInputBuffer->nFilledLen);
00224          pOutputBuffer->nFlags = pInputBuffer->nFlags;
00225          pInputBuffer->nFlags = 0;
00226       }
00227 
00228       if(omx_base_filter_Private->state == OMX_StateExecuting)  {
00229         if (omx_base_filter_Private->BufferMgmtCallback && pInputBuffer->nFilledLen > 0) {
00230           (*(omx_base_filter_Private->BufferMgmtCallback))(openmaxStandComp, pInputBuffer, pOutputBuffer);
00231         } else {
00232           /*It no buffer management call back the explicitly consume input buffer*/
00233           pInputBuffer->nFilledLen = 0;
00234         }
00235       } else if(!(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) {
00236         DEBUG(DEB_LEV_ERR, "In %s Received Buffer in non-Executing State(%x)\n", __func__, (int)omx_base_filter_Private->state);
00237       } else {
00238           pInputBuffer->nFilledLen = 0;
00239       }
00240 
00241       if((pInputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS && pInputBuffer->nFilledLen==0) {
00242         DEBUG(DEB_LEV_FULL_SEQ, "Detected EOS flags in input buffer filled len=%d\n", (int)pInputBuffer->nFilledLen);
00243         pOutputBuffer->nFlags=pInputBuffer->nFlags;
00244         pInputBuffer->nFlags=0;
00245         (*(omx_base_filter_Private->callbacks->EventHandler))
00246           (openmaxStandComp,
00247           omx_base_filter_Private->callbackData,
00248           OMX_EventBufferFlag, /* The command was completed */
00249           1, /* The commands was a OMX_CommandStateSet */
00250           pOutputBuffer->nFlags, /* The state has been changed in message->messageParam2 */
00251           NULL);
00252         omx_base_filter_Private->bIsEOSReached = OMX_TRUE;
00253       }
00254       if(omx_base_filter_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) {
00255         /*Waiting at paused state*/
00256         tsem_wait(omx_base_filter_Private->bStateSem);
00257       }
00258 
00259       /*If EOS and Input buffer Filled Len Zero then Return output buffer immediately*/
00260       if((pOutputBuffer->nFilledLen != 0) || ((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) || (omx_base_filter_Private->bIsEOSReached == OMX_TRUE)) {
00261         pOutPort->ReturnBufferFunction(pOutPort,pOutputBuffer);
00262         outBufExchanged--;
00263         pOutputBuffer=NULL;
00264         isOutputBufferNeeded=OMX_TRUE;
00265       }
00266     }
00267 
00268     if(omx_base_filter_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) {
00269       /*Waiting at paused state*/
00270       tsem_wait(omx_base_filter_Private->bStateSem);
00271     }
00272 
00273     /*Input Buffer has been completely consumed. So, return input buffer*/
00274     if((isInputBufferNeeded == OMX_FALSE) && (pInputBuffer->nFilledLen==0)) {
00275       pInPort->ReturnBufferFunction(pInPort,pInputBuffer);
00276       inBufExchanged--;
00277       pInputBuffer=NULL;
00278       isInputBufferNeeded=OMX_TRUE;
00279     }
00280   }
00281   DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s of component %p\n", __func__, openmaxStandComp);
00282   return NULL;
00283 }