omx_base_source.c

Go to the documentation of this file.
00001 
00032 #include <omxcore.h>
00033 #include <omx_base_source.h>
00034 
00035 OMX_ERRORTYPE omx_base_source_Constructor(OMX_COMPONENTTYPE *openmaxStandComp, OMX_STRING cComponentName) {
00036 
00037   OMX_ERRORTYPE err = OMX_ErrorNone;  
00038   omx_base_source_PrivateType* omx_base_source_Private;
00039 
00040   if (openmaxStandComp->pComponentPrivate) {
00041     omx_base_source_Private = (omx_base_source_PrivateType*)openmaxStandComp->pComponentPrivate;
00042   } else {
00043     omx_base_source_Private = malloc(sizeof(omx_base_source_PrivateType));
00044     if (!omx_base_source_Private) {
00045       return OMX_ErrorInsufficientResources;
00046     }
00047   }
00048 
00049   // we could create our own port structures here
00050   // fixme maybe the base class could use a "port factory" function pointer?  
00051   err = omx_base_component_Constructor(openmaxStandComp, cComponentName);
00052 
00053   /* here we can override whatever defaults the base_component constructor set
00054   * e.g. we can override the function pointers in the private struct  */
00055   omx_base_source_Private = openmaxStandComp->pComponentPrivate;
00056   omx_base_source_Private->BufferMgmtFunction = omx_base_source_BufferMgmtFunction;
00057 
00058   return err;
00059 }
00060 
00061 OMX_ERRORTYPE omx_base_source_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) {
00062 
00063   return omx_base_component_Destructor(openmaxStandComp);
00064 }
00065 
00071 void* omx_base_source_BufferMgmtFunction (void* param) {
00072 
00073   OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param;
00074   omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate;
00075   omx_base_source_PrivateType* omx_base_source_Private = (omx_base_source_PrivateType*)omx_base_component_Private;
00076   omx_base_PortType *pOutPort = (omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX];
00077   tsem_t* pOutputSem = pOutPort->pBufferSem;
00078   queue_t* pOutputQueue = pOutPort->pBufferQueue;
00079   OMX_BUFFERHEADERTYPE* pOutputBuffer = NULL;
00080   OMX_COMPONENTTYPE* target_component;
00081   OMX_BOOL isOutputBufferNeeded = OMX_TRUE;
00082   int outBufExchanged = 0;
00083 
00084   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n", __func__);
00085   while(omx_base_component_Private->state == OMX_StateIdle || omx_base_component_Private->state == OMX_StateExecuting ||  
00086     omx_base_component_Private->state == OMX_StatePause || omx_base_component_Private->transientState == OMX_TransStateLoadedToIdle){
00087 
00088     /*Wait till the ports are being flushed*/
00089     pthread_mutex_lock(&omx_base_source_Private->flush_mutex);
00090     while( PORT_IS_BEING_FLUSHED(pOutPort)) {
00091       pthread_mutex_unlock(&omx_base_source_Private->flush_mutex);
00092 
00093       if(isOutputBufferNeeded == OMX_FALSE) {
00094         pOutPort->ReturnBufferFunction(pOutPort, pOutputBuffer);
00095         outBufExchanged--;
00096         pOutputBuffer = NULL;
00097         isOutputBufferNeeded = OMX_TRUE;
00098         DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer\n");
00099       }
00100       DEBUG(DEB_LEV_FULL_SEQ, "In %s signalling flush all condition \n", __func__);
00101       
00102       pthread_mutex_lock(&omx_base_source_Private->flush_mutex);
00103       pthread_cond_signal(&omx_base_source_Private->flush_all_condition);
00104       pthread_cond_wait(&omx_base_source_Private->flush_condition, &omx_base_source_Private->flush_mutex);
00105     }
00106     pthread_mutex_unlock(&omx_base_source_Private->flush_mutex);
00107 
00108     /*No buffer to process. So wait here*/
00109     if((isOutputBufferNeeded==OMX_TRUE && pOutputSem->semval==0) && 
00110       (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid)) {
00111       DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer \n");
00112       tsem_down(omx_base_source_Private->bMgmtSem);
00113     }
00114 
00115     if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) {
00116       DEBUG(DEB_LEV_FULL_SEQ, "In %s Buffer Management Thread is exiting\n",__func__);
00117       break;
00118     }
00119 
00120     DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer semval=%d \n",pOutputSem->semval);
00121     if(pOutputSem->semval > 0 && isOutputBufferNeeded == OMX_TRUE ) {
00122       tsem_down(pOutputSem);
00123       if(pOutputQueue->nelem>0){
00124         outBufExchanged++;
00125         isOutputBufferNeeded = OMX_FALSE;
00126         pOutputBuffer = dequeue(pOutputQueue);
00127         if(pOutputBuffer == NULL){
00128           DEBUG(DEB_LEV_ERR, "In %s Had NULL output buffer!!\n",__func__);
00129           break;
00130         }
00131       }
00132     }
00133     
00134     if(isOutputBufferNeeded == OMX_FALSE) {
00135       if(pOutputBuffer->nFlags == OMX_BUFFERFLAG_EOS) {
00136         DEBUG(DEB_LEV_SIMPLE_SEQ, "Detected EOS flags in output buffer\n");
00137         
00138         (*(omx_base_component_Private->callbacks->EventHandler))
00139           (openmaxStandComp,
00140           omx_base_component_Private->callbackData,
00141           OMX_EventBufferFlag, /* The command was completed */
00142           0, /* The commands was a OMX_CommandStateSet */
00143           pOutputBuffer->nFlags, /* The state has been changed in message->messageParam2 */
00144           NULL);
00145         pOutputBuffer->nFlags = 0;
00146       }
00147       if(omx_base_source_Private->pMark!=NULL){
00148          omx_base_source_Private->pMark=NULL;
00149       }
00150       target_component = (OMX_COMPONENTTYPE*)pOutputBuffer->hMarkTargetComponent;
00151       if(target_component == (OMX_COMPONENTTYPE *)openmaxStandComp) {
00152         /*Clear the mark and generate an event*/
00153         (*(omx_base_component_Private->callbacks->EventHandler))
00154           (openmaxStandComp,
00155           omx_base_component_Private->callbackData,
00156           OMX_EventMark, /* The command was completed */
00157           1, /* The commands was a OMX_CommandStateSet */
00158           0, /* The state has been changed in message->messageParam2 */
00159           pOutputBuffer->pMarkData);
00160       } else if(pOutputBuffer->hMarkTargetComponent != NULL) {
00161         /*If this is not the target component then pass the mark*/
00162         DEBUG(DEB_LEV_FULL_SEQ, "Can't Pass Mark. This is a Source!!\n");
00163       }
00164 
00165       if (omx_base_source_Private->BufferMgmtCallback && pOutputBuffer->nFilledLen == 0) {
00166         (*(omx_base_source_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer);
00167       } else {
00168         /*It no buffer management call back then don't produce any output buffer*/
00169         pOutputBuffer->nFilledLen = 0;
00170       }
00171       if(omx_base_source_Private->state == OMX_StatePause && !PORT_IS_BEING_FLUSHED(pOutPort)) {
00172         /*Waiting at paused state*/
00173         tsem_wait(omx_base_source_Private->bStateSem);
00174       }
00175 
00176       /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/
00177       if(pOutputBuffer->nFilledLen != 0 || pOutputBuffer->nFlags == OMX_BUFFERFLAG_EOS) {
00178         pOutPort->ReturnBufferFunction(pOutPort, pOutputBuffer);
00179         outBufExchanged--;
00180         pOutputBuffer = NULL;
00181         isOutputBufferNeeded = OMX_TRUE;
00182       }
00183 
00184     }
00185   }
00186   DEBUG(DEB_LEV_SIMPLE_SEQ, "Exiting Buffer Management Thread\n");
00187   return NULL;
00188 }
00189 
00196 void* omx_base_source_twoport_BufferMgmtFunction (void* param) {
00197   OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param;
00198   omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate;
00199   omx_base_source_PrivateType* omx_base_source_Private = (omx_base_source_PrivateType*)omx_base_component_Private;
00200   omx_base_PortType *pOutPort[2];
00201   tsem_t* pOutputSem[2];
00202   queue_t* pOutputQueue[2];
00203   OMX_BUFFERHEADERTYPE* pOutputBuffer[2];
00204   OMX_COMPONENTTYPE* target_component;
00205   OMX_BOOL isOutputBufferNeeded[2];
00206   int i,outBufExchanged[2];
00207 
00208   pOutPort[0]=(omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX];
00209   pOutPort[1]=(omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX_1];
00210   pOutputSem[0] = pOutPort[0]->pBufferSem;
00211   pOutputSem[1] = pOutPort[1]->pBufferSem;
00212   pOutputQueue[0] = pOutPort[0]->pBufferQueue;
00213   pOutputQueue[1] = pOutPort[1]->pBufferQueue;
00214   pOutputBuffer[1]= pOutputBuffer[0]=NULL;
00215   isOutputBufferNeeded[0]=isOutputBufferNeeded[1]=OMX_TRUE;
00216   outBufExchanged[0]=outBufExchanged[1]=0;
00217 
00218   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00219   while(omx_base_source_Private->state == OMX_StateIdle || omx_base_source_Private->state == OMX_StateExecuting ||  omx_base_source_Private->state == OMX_StatePause || 
00220     omx_base_source_Private->transientState == OMX_TransStateLoadedToIdle){
00221 
00222     /*Wait till the ports are being flushed*/
00223     pthread_mutex_lock(&omx_base_source_Private->flush_mutex);
00224     while( PORT_IS_BEING_FLUSHED(pOutPort[0]) || 
00225            PORT_IS_BEING_FLUSHED(pOutPort[1])) {
00226       pthread_mutex_unlock(&omx_base_source_Private->flush_mutex);
00227       
00228       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", 
00229         __func__,outBufExchanged[0],isOutputBufferNeeded[0],outBufExchanged[1],isOutputBufferNeeded[1],pOutputSem[0]->semval,pOutputSem[1]->semval);
00230 
00231       if(isOutputBufferNeeded[1]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[1])) {
00232         pOutPort[1]->ReturnBufferFunction(pOutPort[1],pOutputBuffer[1]);
00233         outBufExchanged[1]--;
00234         pOutputBuffer[1]=NULL;
00235         isOutputBufferNeeded[1]=OMX_TRUE;
00236         DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output 1 buffer\n");
00237       }
00238 
00239       if(isOutputBufferNeeded[0]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[0])) {
00240         pOutPort[0]->ReturnBufferFunction(pOutPort[0],pOutputBuffer[0]);
00241         outBufExchanged[0]--;
00242         pOutputBuffer[0]=NULL;
00243         isOutputBufferNeeded[0]=OMX_TRUE;
00244         DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output 0 buffer\n");
00245       }
00246 
00247       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", 
00248         __func__,outBufExchanged[0],isOutputBufferNeeded[0],outBufExchanged[1],isOutputBufferNeeded[1],pOutputSem[0]->semval,pOutputSem[1]->semval);
00249   
00250       pthread_mutex_lock(&omx_base_source_Private->flush_mutex);
00251       pthread_cond_signal(&omx_base_source_Private->flush_all_condition);
00252       pthread_cond_wait(&omx_base_source_Private->flush_condition,&omx_base_source_Private->flush_mutex);
00253     }
00254     pthread_mutex_unlock(&omx_base_source_Private->flush_mutex);
00255 
00256     /*No buffer to process. So wait here*/
00257     if((isOutputBufferNeeded[0]==OMX_TRUE && pOutputSem[0]->semval==0) && 
00258       (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid)) {
00259       //Signalled from EmptyThisBuffer or FillThisBuffer or some thing else
00260       DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer 0\n");
00261       tsem_down(omx_base_source_Private->bMgmtSem);
00262       
00263     }
00264     if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) {
00265       DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__);
00266       break;
00267     }
00268     if((isOutputBufferNeeded[1]==OMX_TRUE && pOutputSem[1]->semval==0) && 
00269       (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid) &&
00270        !(PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1]))) {
00271       //Signalled from EmptyThisBuffer or FillThisBuffer or some thing else
00272       DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer 1\n");
00273       tsem_down(omx_base_source_Private->bMgmtSem);
00274       
00275     }
00276     if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) {
00277       DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__);
00278       break;
00279     }
00280  
00281     DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer 0 semval=%d \n",pOutputSem[0]->semval);
00282     if(pOutputSem[0]->semval>0 && isOutputBufferNeeded[0]==OMX_TRUE ) {
00283       tsem_down(pOutputSem[0]);
00284       if(pOutputQueue[0]->nelem>0){
00285         outBufExchanged[0]++;
00286         isOutputBufferNeeded[0]=OMX_FALSE;
00287         pOutputBuffer[0] = dequeue(pOutputQueue[0]);
00288         if(pOutputBuffer[0] == NULL){
00289           DEBUG(DEB_LEV_ERR, "Had NULL output buffer!!\n");
00290           break;
00291         }
00292       }
00293     }
00294     /*When we have input buffer to process then get one output buffer*/
00295     if(pOutputSem[1]->semval>0 && isOutputBufferNeeded[1]==OMX_TRUE) {
00296       tsem_down(pOutputSem[1]);
00297       if(pOutputQueue[1]->nelem>0){
00298         outBufExchanged[1]++;
00299         isOutputBufferNeeded[1]=OMX_FALSE;
00300         pOutputBuffer[1] = dequeue(pOutputQueue[1]);
00301         if(pOutputBuffer[1] == NULL){
00302           DEBUG(DEB_LEV_ERR, "Had NULL output buffer!! op is=%d,iq=%d\n",pOutputSem[1]->semval,pOutputQueue[1]->nelem);
00303           break;
00304         }
00305       }
00306     }
00307 
00308     for(i=0;i < (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts  +
00309                  omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts +
00310                  omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts +
00311                  omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts -1);i++) {
00312 
00313       if(omx_base_source_Private->ports[i]->sPortParam.eDomain!=OMX_PortDomainOther){ /* clock ports are not to be processed */
00314         /*Process Output buffer of Port i */
00315         if(isOutputBufferNeeded[i]==OMX_FALSE) {
00316           if(omx_base_source_Private->pMark!=NULL){
00317             pOutputBuffer[i]->hMarkTargetComponent=omx_base_source_Private->pMark->hMarkTargetComponent;
00318             pOutputBuffer[i]->pMarkData=omx_base_source_Private->pMark->pMarkData;
00319             omx_base_source_Private->pMark=NULL;
00320           }
00321           target_component=(OMX_COMPONENTTYPE*)pOutputBuffer[i]->hMarkTargetComponent;
00322           if(target_component==(OMX_COMPONENTTYPE *)openmaxStandComp) {
00323             /*Clear the mark and generate an event*/
00324             (*(omx_base_source_Private->callbacks->EventHandler))
00325               (openmaxStandComp,
00326               omx_base_source_Private->callbackData,
00327               OMX_EventMark, /* The command was completed */
00328               1, /* The commands was a OMX_CommandStateSet */
00329               i, /* The state has been changed in message->messageParam2 */
00330               pOutputBuffer[i]->pMarkData);
00331           } else if(pOutputBuffer[i]->hMarkTargetComponent!=NULL){
00332             /*If this is not the target component then pass the mark*/
00333             pOutputBuffer[i]->pMarkData=NULL;
00334           }
00335 
00336           if (omx_base_source_Private->BufferMgmtCallback && pOutputBuffer[i]->nFilledLen == 0) {
00337             //(*(omx_base_source_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer[0], pOutputBuffer[1]);
00338             (*(omx_base_source_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer[i]);
00339           } else {
00340             /*If no buffer management call back then don't produce any output buffer*/
00341             pOutputBuffer[i]->nFilledLen = 0;
00342           }
00343       
00344           if(pOutputBuffer[i]->nFlags==OMX_BUFFERFLAG_EOS && pOutputBuffer[i]->nFilledLen==0) {
00345             DEBUG(DEB_LEV_FULL_SEQ, "Detected EOS flags in input buffer filled len=%d\n", (int)pOutputBuffer[i]->nFilledLen);
00346             (*(omx_base_source_Private->callbacks->EventHandler))
00347               (openmaxStandComp,
00348               omx_base_source_Private->callbackData,
00349               OMX_EventBufferFlag, /* The command was completed */
00350               i, /* The commands was a OMX_CommandStateSet */
00351               pOutputBuffer[i]->nFlags, /* The state has been changed in message->messageParam2 */
00352               NULL);
00353           }
00354           if(omx_base_source_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1]))) {
00355             /*Waiting at paused state*/
00356             tsem_wait(omx_base_component_Private->bStateSem);
00357           }
00358 
00359            /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/
00360           if(pOutputBuffer[i]->nFilledLen!=0 || pOutputBuffer[i]->nFlags==OMX_BUFFERFLAG_EOS){
00361             pOutPort[i]->ReturnBufferFunction(pOutPort[i],pOutputBuffer[i]);
00362             outBufExchanged[i]--;
00363             pOutputBuffer[i]=NULL;
00364             isOutputBufferNeeded[i]=OMX_TRUE;
00365           }
00366         }
00367       }
00368     }
00369   }
00370   DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n");
00371   return NULL;
00372 }

Generated for OpenMAX Bellagio rel. 0.9.0 by  doxygen 1.5.1
SourceForge.net Logo