OpenMAXBellagio 0.9.3
omx_video_scheduler_component.c
Go to the documentation of this file.
00001 
00026 #include <omxcore.h>
00027 #include <omx_video_scheduler_component.h>
00028 
00029 #define DEFAULT_WIDTH   352
00030 #define DEFAULT_HEIGHT  288
00031 #define CLOCKPORT_INDEX 2
00032 
00034 #define DEFAULT_VIDEO_INPUT_BUF_SIZE DEFAULT_WIDTH*DEFAULT_HEIGHT*3/2
00035 
00040 OMX_ERRORTYPE omx_video_scheduler_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp, OMX_STRING cComponentName) {
00041   OMX_ERRORTYPE                                err = OMX_ErrorNone;
00042   omx_video_scheduler_component_PrivateType*   omx_video_scheduler_component_Private;
00043   omx_base_video_PortType       *inPort,*outPort;
00044   OMX_U32                                      i;
00045 
00046 
00047     RM_RegisterComponent(VIDEO_SCHEDULER_COMP_NAME, MAX_VIDEOSCHED_COMPONENTS);
00048   if (!openmaxStandComp->pComponentPrivate) {
00049     DEBUG(DEB_LEV_FUNCTION_NAME, "In %s, allocating component\n", __func__);
00050     openmaxStandComp->pComponentPrivate = calloc(1, sizeof(omx_video_scheduler_component_PrivateType));
00051     if(openmaxStandComp->pComponentPrivate == NULL) {
00052       return OMX_ErrorInsufficientResources;
00053     }
00054   } else {
00055     DEBUG(DEB_LEV_FUNCTION_NAME, "In %s, Error Component %p Already Allocated\n", __func__, openmaxStandComp->pComponentPrivate);
00056   }
00057 
00058   omx_video_scheduler_component_Private        = openmaxStandComp->pComponentPrivate;
00059   omx_video_scheduler_component_Private->ports = NULL;
00060 
00064   err = omx_base_filter_Constructor(openmaxStandComp, cComponentName);
00065 
00066   omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0;
00067   omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2;
00068 
00069   omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainOther].nStartPortNumber = CLOCKPORT_INDEX;
00070   omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts = 1;
00071 
00073  if ((omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts
00074        + omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)
00075        && !omx_video_scheduler_component_Private->ports) {
00076     omx_video_scheduler_component_Private->ports = calloc((omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts
00077                                                            + omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts),
00078                                                            sizeof(omx_base_PortType *));
00079     if (!omx_video_scheduler_component_Private->ports) {
00080       return OMX_ErrorInsufficientResources;
00081     }
00082     for (i=0; i < omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts; i++) {
00083       omx_video_scheduler_component_Private->ports[i] = calloc(1, sizeof(omx_base_video_PortType));
00084       if (!omx_video_scheduler_component_Private->ports[i]) {
00085         return OMX_ErrorInsufficientResources;
00086       }
00087     }
00088     base_video_port_Constructor(openmaxStandComp, &omx_video_scheduler_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX], 0, OMX_TRUE);
00089     base_video_port_Constructor(openmaxStandComp, &omx_video_scheduler_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX], 1, OMX_FALSE);
00090 
00091     omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX] = calloc(1, sizeof(omx_base_clock_PortType));
00092     if (!omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX]) {
00093       return OMX_ErrorInsufficientResources;
00094     }
00095     base_clock_port_Constructor(openmaxStandComp, &omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX], 2, OMX_TRUE);
00096     omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX]->sPortParam.bEnabled = OMX_TRUE;
00097   }
00098 
00099   inPort = (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
00100   outPort= (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
00101 
00104   //input port parameter settings
00105   inPort->sVideoParam.eColorFormat             = OMX_COLOR_Format24bitRGB888;
00106   inPort->sPortParam.format.video.nFrameWidth  = DEFAULT_WIDTH;
00107   inPort->sPortParam.format.video.nFrameHeight = DEFAULT_HEIGHT;
00108   inPort->sPortParam.nBufferSize               = DEFAULT_VIDEO_INPUT_BUF_SIZE * 2 ;
00109   inPort->sPortParam.format.video.eColorFormat = OMX_COLOR_Format24bitRGB888;
00110 
00111   outPort->sVideoParam.eColorFormat             = OMX_COLOR_Format24bitRGB888;
00112   outPort->sPortParam.format.video.nFrameWidth  = DEFAULT_WIDTH;
00113   outPort->sPortParam.format.video.nFrameHeight = DEFAULT_HEIGHT;
00114   outPort->sPortParam.nBufferSize               = DEFAULT_VIDEO_INPUT_BUF_SIZE * 2;
00115   outPort->sPortParam.format.video.eColorFormat = OMX_COLOR_Format24bitRGB888;
00116 
00117   omx_video_scheduler_component_Private->destructor         = omx_video_scheduler_component_Destructor;
00118   omx_video_scheduler_component_Private->BufferMgmtCallback = omx_video_scheduler_component_BufferMgmtCallback;
00119 
00120   inPort->FlushProcessingBuffers  = omx_video_scheduler_component_port_FlushProcessingBuffers;
00121   openmaxStandComp->SetParameter  = omx_video_scheduler_component_SetParameter;
00122   openmaxStandComp->GetParameter  = omx_video_scheduler_component_GetParameter;
00123 
00124   /* resource management special section */
00125   omx_video_scheduler_component_Private->nqualitylevels = VIDEOSCHED_QUALITY_LEVELS;
00126   omx_video_scheduler_component_Private->currentQualityLevel = 1;
00127   omx_video_scheduler_component_Private->multiResourceLevel = malloc(sizeof(multiResourceDescriptor *) * VIDEOSCHED_QUALITY_LEVELS);
00128   for (i = 0; i<VIDEOSCHED_QUALITY_LEVELS; i++) {
00129       omx_video_scheduler_component_Private->multiResourceLevel[i] = malloc(sizeof(multiResourceDescriptor));
00130       omx_video_scheduler_component_Private->multiResourceLevel[i]->CPUResourceRequested = videoSchedQualityLevels[i * 2];
00131       omx_video_scheduler_component_Private->multiResourceLevel[i]->MemoryResourceRequested = videoSchedQualityLevels[i * 2 + 1];
00132   }
00133 
00134   return err;
00135 }
00136 
00139 OMX_ERRORTYPE omx_video_scheduler_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) {
00140   omx_video_scheduler_component_PrivateType*   omx_video_scheduler_component_Private = openmaxStandComp->pComponentPrivate;
00141   OMX_U32                                      i;
00142 
00143   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00144 
00145   /* frees port/s */
00146   if (omx_video_scheduler_component_Private->ports) {
00147   for(i=0; i < (omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts +
00148                    omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts); i++) {
00149     if(omx_video_scheduler_component_Private->ports[i])
00150        omx_video_scheduler_component_Private->ports[i]->PortDestructor(omx_video_scheduler_component_Private->ports[i]);
00151     }
00152     free(omx_video_scheduler_component_Private->ports);
00153     omx_video_scheduler_component_Private->ports=NULL;
00154   }
00155 
00156   omx_base_filter_Destructor(openmaxStandComp);
00157   DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s\n", __func__);
00158 
00159   return OMX_ErrorNone;
00160 }
00161 
00162 
00168 OMX_ERRORTYPE omx_video_scheduler_component_port_SendBufferFunction(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) {
00169 
00170   OMX_ERRORTYPE                   err;
00171   int                             errQue;
00172   OMX_U32                         portIndex;
00173   OMX_COMPONENTTYPE*              omxComponent = openmaxStandPort->standCompContainer;
00174   omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
00175   OMX_BOOL                        SendFrame;
00176   omx_base_clock_PortType*        pClockPort;
00177 #if NO_GST_OMX_PATCH
00178   unsigned int i;
00179 #endif
00180 
00181   portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex;
00182   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex);
00183 
00184   if (portIndex != openmaxStandPort->sPortParam.nPortIndex) {
00185     DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n",
00186            __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex);
00187     return OMX_ErrorBadPortIndex;
00188   }
00189 
00190   if(omx_base_component_Private->state == OMX_StateInvalid) {
00191     DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__);
00192     return OMX_ErrorInvalidState;
00193   }
00194 
00195   if(omx_base_component_Private->state != OMX_StateExecuting &&
00196     omx_base_component_Private->state != OMX_StatePause &&
00197     omx_base_component_Private->state != OMX_StateIdle) {
00198     DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state);
00199     return OMX_ErrorIncorrectStateOperation;
00200   }
00201   if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) ||
00202       (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle &&
00203       (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) {
00204     DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name);
00205     return OMX_ErrorIncorrectStateOperation;
00206   }
00207 
00208   /* Temporarily disable this check for gst-openmax */
00209 #if NO_GST_OMX_PATCH
00210   {
00211   OMX_BOOL foundBuffer = OMX_FALSE;
00212   if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) {
00213     for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
00214     if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) {
00215       foundBuffer = OMX_TRUE;
00216       break;
00217     }
00218     }
00219   }
00220   if (!foundBuffer) {
00221     return OMX_ErrorBadParameter;
00222   }
00223   }
00224 #endif
00225 
00226   if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) {
00227     DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__);
00228     return err;
00229   }
00230 
00231   pClockPort  = (omx_base_clock_PortType*)omx_base_component_Private->ports[CLOCKPORT_INDEX];
00232   if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(openmaxStandPort) &&
00233       (omx_base_component_Private->transientState != OMX_TransStateExecutingToIdle) &&
00234       ((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)){
00235     SendFrame = omx_video_scheduler_component_ClockPortHandleFunction((omx_video_scheduler_component_PrivateType*)omx_base_component_Private, pBuffer);
00236     if(!SendFrame) pBuffer->nFilledLen=0;
00237   }
00238 
00239   /* And notify the buffer management thread we have a fresh new buffer to manage */
00240   if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))
00241       && omx_base_component_Private->transientState != OMX_TransStateExecutingToIdle){
00242       errQue = queue(openmaxStandPort->pBufferQueue, pBuffer);
00243       if (errQue) {
00244           /* /TODO the queue is full. This can be handled in a fine way with
00245            * some retrials, or other checking. For the moment this is a critical error
00246            * and simply causes the failure of this call
00247            */
00248           return OMX_ErrorInsufficientResources;
00249       }
00250       tsem_up(openmaxStandPort->pBufferSem);
00251       DEBUG(DEB_LEV_FULL_SEQ, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex);
00252       tsem_up(omx_base_component_Private->bMgmtSem);
00253   }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){
00254       DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex);
00255       errQue = queue(openmaxStandPort->pBufferQueue, pBuffer);
00256       if (errQue) {
00257           /* /TODO the queue is full. This can be handled in a fine way with
00258            * some retrials, or other checking. For the moment this is a critical error
00259            * and simply causes the failure of this call
00260            */
00261           return OMX_ErrorInsufficientResources;
00262       }
00263       tsem_up(openmaxStandPort->pBufferSem);
00264   } else { // If port being flushed and not tunneled then return error
00265     DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__);
00266     return OMX_ErrorIncorrectStateOperation;
00267   }
00268   return OMX_ErrorNone;
00269 }
00270 
00271 
00272 OMX_BOOL omx_video_scheduler_component_ClockPortHandleFunction(
00273   omx_video_scheduler_component_PrivateType* omx_video_scheduler_component_Private,
00274   OMX_BUFFERHEADERTYPE* pInputBuffer){
00275   omx_base_clock_PortType               *pClockPort;
00276   OMX_HANDLETYPE                        hclkComponent;
00277   OMX_BUFFERHEADERTYPE*                 clockBuffer;
00278   OMX_TIME_MEDIATIMETYPE*               pMediaTime;
00279   OMX_TIME_CONFIG_TIMESTAMPTYPE         sClientTimeStamp;
00280   OMX_ERRORTYPE                         err;
00281   OMX_BOOL                              SendFrame;
00282   omx_base_video_PortType               *pInputPort;
00283 
00284   pClockPort    = (omx_base_clock_PortType*) omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX];
00285   pInputPort    = (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[0];
00286   hclkComponent = pClockPort->hTunneledComponent;
00287 
00288   SendFrame = OMX_TRUE;
00289 
00290   DEBUG(DEB_LEV_FULL_SEQ, "In %s Clock Port is Tunneled. Sending Request\n", __func__);
00291   /* if first time stamp is received then notify the clock component */
00292   if((pInputBuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) {
00293     DEBUG(DEB_LEV_FULL_SEQ," In %s  first time stamp = %llx \n", __func__,pInputBuffer->nTimeStamp);
00294     pInputBuffer->nFlags = 0;
00295     hclkComponent = pClockPort->hTunneledComponent;
00296     setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE));
00297     sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort;
00298     sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp;
00299     err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeClientStartTime, &sClientTimeStamp);
00300     if(err!=OMX_ErrorNone) {
00301      DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00302     }
00303     tsem_down(pClockPort->pBufferSem); /* wait for state change notification */
00304 
00305     /* update the clock state and clock scale info into the fbdev private data */
00306     if(pClockPort->pBufferQueue->nelem > 0) {
00307       clockBuffer=dequeue(pClockPort->pBufferQueue);
00308       pMediaTime  = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer;
00309       omx_video_scheduler_component_Private->eState      = pMediaTime->eState;
00310       omx_video_scheduler_component_Private->xScale      = pMediaTime->xScale;
00311       pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer);
00312     }
00313   }
00314 
00315   /* do not send the data to sink and return back, if the clock is not running*/
00316   if(!omx_video_scheduler_component_Private->eState==OMX_TIME_ClockStateRunning){
00317     pInputBuffer->nFilledLen=0;
00318     SendFrame = OMX_FALSE;
00319     return SendFrame;
00320   }
00321 
00322   /* check for any scale change information from the clock component */
00323   if(pClockPort->pBufferSem->semval>0) {
00324     tsem_down(pClockPort->pBufferSem);
00325     if(pClockPort->pBufferQueue->nelem > 0) {
00326       clockBuffer = dequeue(pClockPort->pBufferQueue);
00327       pMediaTime  = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer;
00328       if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) {
00329         /* On scale change update the media time base */
00330         sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort;
00331         sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp;
00332         err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp);
00333         if(err!=OMX_ErrorNone) {
00334           DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00335         }
00336         omx_video_scheduler_component_Private->frameDropFlag = OMX_TRUE;
00337         omx_video_scheduler_component_Private->dropFrameCount = 0;
00338         omx_video_scheduler_component_Private->xScale = pMediaTime->xScale;
00339       }
00340       pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer);
00341     }
00342   }
00343 
00344   /* drop next seven frames on scale change
00345      and rebase the clock time base */
00346   if(omx_video_scheduler_component_Private->frameDropFlag && omx_video_scheduler_component_Private->dropFrameCount<7) { //TODO - second check cond can be removed verify
00347      omx_video_scheduler_component_Private->dropFrameCount ++;
00348      if(omx_video_scheduler_component_Private->dropFrameCount==7) {
00349         /* rebase the clock time base */
00350         setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE));
00351         sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort;
00352         sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp;
00353         err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp);
00354         if(err!=OMX_ErrorNone) {
00355           DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00356         }
00357 
00358         omx_video_scheduler_component_Private->frameDropFlag  = OMX_FALSE;
00359         omx_video_scheduler_component_Private->dropFrameCount = 0;
00360         SendFrame = OMX_TRUE;
00361      }
00362      SendFrame = OMX_FALSE;
00363   }
00364 
00365   /* frame is not to be dropped so send the request for the timestamp for the data delivery */
00366   if(SendFrame){
00367     if(!PORT_IS_BEING_FLUSHED(pInputPort) && !PORT_IS_BEING_FLUSHED(pClockPort) &&
00368         omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) {
00369       setHeader(&pClockPort->sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE));
00370       pClockPort->sMediaTimeRequest.nMediaTimestamp = pInputBuffer->nTimeStamp;
00371       pClockPort->sMediaTimeRequest.nOffset         = 100; /*set the requested offset */
00372       pClockPort->sMediaTimeRequest.nPortIndex      = pClockPort->nTunneledPort;
00373       pClockPort->sMediaTimeRequest.pClientPrivate  = NULL; /* fill the appropriate value */
00374       err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeMediaTimeRequest, &pClockPort->sMediaTimeRequest);
00375       if(err!=OMX_ErrorNone) {
00376         DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00377       }
00378       if(!PORT_IS_BEING_FLUSHED(pInputPort) && !PORT_IS_BEING_FLUSHED(pClockPort) &&
00379           omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) {
00380         tsem_down(pClockPort->pBufferSem); /* wait for the request fullfillment */
00381         if(pClockPort->pBufferQueue->nelem > 0) {
00382           clockBuffer = dequeue(pClockPort->pBufferQueue);
00383           pMediaTime  = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer;
00384           if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) {
00385            /* update the media time base */
00386             setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); // do not need to setHeader again do once at the top
00387             sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort;
00388             sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp;
00389             err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp);
00390             if(err!=OMX_ErrorNone) {
00391               DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00392             }
00393             omx_video_scheduler_component_Private->frameDropFlag  = OMX_TRUE;
00394             omx_video_scheduler_component_Private->dropFrameCount = 0;
00395             omx_video_scheduler_component_Private->xScale = pMediaTime->xScale;
00396           }
00397           if(pMediaTime->eUpdateType==OMX_TIME_UpdateRequestFulfillment){
00398             if((pMediaTime->nOffset)>0) {
00399               SendFrame=OMX_TRUE;
00400             }else {
00401               SendFrame = OMX_FALSE;
00402             }
00403           }
00404           pClockPort->ReturnBufferFunction((omx_base_PortType *)pClockPort,clockBuffer);
00405         }
00406       }
00407     }
00408   }
00409   return(SendFrame);
00410 }
00411 
00412 
00417 OMX_ERRORTYPE  omx_video_scheduler_component_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort) {
00418   omx_base_component_PrivateType*              omx_base_component_Private;
00419   omx_video_scheduler_component_PrivateType*   omx_video_scheduler_component_Private;
00420   OMX_BUFFERHEADERTYPE*                        pBuffer;
00421   omx_base_clock_PortType                      *pClockPort;
00422   int errQue;
00423 
00424   DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00425   omx_base_component_Private             = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate;
00426   omx_video_scheduler_component_Private  = ( omx_video_scheduler_component_PrivateType*) omx_base_component_Private;
00427 
00428   pClockPort    = (omx_base_clock_PortType*) omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX];
00429 
00430   if(openmaxStandPort->sPortParam.eDomain!=OMX_PortDomainOther) { /* clock buffers not used in the clients buffer managment function */
00431     pthread_mutex_lock(&omx_base_component_Private->flush_mutex);
00432     openmaxStandPort->bIsPortFlushed=OMX_TRUE;
00433     /*Signal the buffer management thread of port flush,if it is waiting for buffers*/
00434     if(omx_base_component_Private->bMgmtSem->semval==0) {
00435       tsem_up(omx_base_component_Private->bMgmtSem);
00436     }
00437 
00438     if(omx_base_component_Private->state != OMX_StateExecuting ) {
00439       /*signal at non-executing state*/
00440       tsem_signal(omx_base_component_Private->bStateSem);
00441     }
00442     DEBUG(DEB_LEV_FULL_SEQ, "In %s waiting for flush all condition port index =%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex);
00443     /* Wait until flush is completed */
00444     pthread_mutex_unlock(&omx_base_component_Private->flush_mutex);
00445 
00446     /*Dummy signal to clock port*/
00447     if(pClockPort->pBufferSem->semval == 0) {
00448       tsem_up(pClockPort->pBufferSem);
00449       tsem_reset(pClockPort->pBufferSem);
00450     }
00451     tsem_down(omx_base_component_Private->flush_all_condition);
00452   }
00453 
00454   tsem_reset(omx_base_component_Private->bMgmtSem);
00455 
00456   /* Flush all the buffers not under processing */
00457   while (openmaxStandPort->pBufferSem->semval > 0) {
00458     DEBUG(DEB_LEV_FULL_SEQ, "In %s TFlag=%x Flusing Port=%d,Semval=%d Qelem=%d\n",
00459     __func__,(int)openmaxStandPort->nTunnelFlags,(int)openmaxStandPort->sPortParam.nPortIndex,
00460     (int)openmaxStandPort->pBufferSem->semval,(int)openmaxStandPort->pBufferQueue->nelem);
00461 
00462     tsem_down(openmaxStandPort->pBufferSem);
00463     pBuffer = dequeue(openmaxStandPort->pBufferQueue);
00464     if (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) {
00465       DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s is returning io:%d buffer\n",
00466         __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex);
00467       if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) {
00468         ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer);
00469       } else {
00470         ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer);
00471       }
00472     } else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) {
00473         errQue = queue(openmaxStandPort->pBufferQueue,pBuffer);
00474         if (errQue) {
00475           /* /TODO the queue is full. This can be handled in a fine way with
00476            * some retrials, or other checking. For the moment this is a critical error
00477            * and simply causes the failure of this call
00478            */
00479           return OMX_ErrorInsufficientResources;
00480         }
00481     } else {
00482       (*(openmaxStandPort->BufferProcessedCallback))(
00483         openmaxStandPort->standCompContainer,
00484         omx_base_component_Private->callbackData,
00485         pBuffer);
00486     }
00487   }
00488   /*Port is tunneled and supplier and didn't received all it's buffer then wait for the buffers*/
00489   if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) {
00490     while(openmaxStandPort->pBufferQueue->nelem!= openmaxStandPort->nNumAssignedBuffers){
00491       tsem_down(openmaxStandPort->pBufferSem);
00492       DEBUG(DEB_LEV_PARAMS, "In %s Got a buffer qelem=%d\n",__func__,openmaxStandPort->pBufferQueue->nelem);
00493     }
00494     tsem_reset(openmaxStandPort->pBufferSem);
00495   }
00496 
00497   pthread_mutex_lock(&omx_base_component_Private->flush_mutex);
00498   openmaxStandPort->bIsPortFlushed=OMX_FALSE;
00499   pthread_mutex_unlock(&omx_base_component_Private->flush_mutex);
00500 
00501   tsem_up(omx_base_component_Private->flush_condition);
00502 
00503   DEBUG(DEB_LEV_FULL_SEQ, "Out %s Port Index=%d bIsPortFlushed=%d Component %s\n", __func__,
00504     (int)openmaxStandPort->sPortParam.nPortIndex,(int)openmaxStandPort->bIsPortFlushed,omx_base_component_Private->name);
00505 
00506   DEBUG(DEB_LEV_PARAMS, "In %s TFlag=%x Qelem=%d BSem=%d bMgmtsem=%d component=%s\n", __func__,
00507     (int)openmaxStandPort->nTunnelFlags,
00508     (int)openmaxStandPort->pBufferQueue->nelem,
00509     (int)openmaxStandPort->pBufferSem->semval,
00510     (int)omx_base_component_Private->bMgmtSem->semval,
00511     omx_base_component_Private->name);
00512 
00513   DEBUG(DEB_LEV_FUNCTION_NAME, "Out %s Port Index=%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex);
00514 
00515   return OMX_ErrorNone;
00516 }
00517 
00520 void omx_video_scheduler_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* pInputBuffer, OMX_BUFFERHEADERTYPE* pOutputBuffer) {
00521 
00522   omx_video_scheduler_component_PrivateType*   omx_video_scheduler_component_Private = openmaxStandComp->pComponentPrivate;
00523   omx_base_video_PortType       *inPort = (omx_base_video_PortType *)omx_video_scheduler_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
00524   omx_base_clock_PortType*        pClockPort;
00525   OMX_BOOL                        SendFrame;
00526 
00527   pClockPort  = (omx_base_clock_PortType*)omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX];
00528   if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(inPort) &&
00529       (omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) &&
00530       ((pInputBuffer->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)){
00531     SendFrame = omx_video_scheduler_component_ClockPortHandleFunction(omx_video_scheduler_component_Private, pInputBuffer);
00532     if(!SendFrame) pInputBuffer->nFilledLen = 0;
00533   }
00534 
00535   if((pInputBuffer->pBuffer != pOutputBuffer->pBuffer) && (pInputBuffer->nFilledLen > 0)){
00536     memcpy(pOutputBuffer->pBuffer,pInputBuffer->pBuffer,pInputBuffer->nFilledLen);
00537     pOutputBuffer->nOffset = pInputBuffer->nOffset;
00538   }
00539   pOutputBuffer->nFilledLen = pInputBuffer->nFilledLen;
00540   pInputBuffer->nFilledLen=0;
00541 }
00542 
00543 
00544 
00545 OMX_ERRORTYPE omx_video_scheduler_component_SetParameter(
00546   OMX_HANDLETYPE hComponent,
00547   OMX_INDEXTYPE nParamIndex,
00548   OMX_PTR ComponentParameterStructure) {
00549 
00550   OMX_ERRORTYPE                     err = OMX_ErrorNone;
00551   OMX_PARAM_PORTDEFINITIONTYPE      *pPortDef;
00552   OMX_VIDEO_PARAM_PORTFORMATTYPE    *pVideoPortFormat;
00553   OMX_OTHER_PARAM_PORTFORMATTYPE    *pOtherPortFormat;
00554   OMX_U32                           portIndex;
00555   OMX_PARAM_COMPONENTROLETYPE       *pComponentRole;
00556 
00557   /* Check which structure we are being fed and make control its header */
00558   OMX_COMPONENTTYPE                           *openmaxStandComp = (OMX_COMPONENTTYPE *)hComponent;
00559   omx_video_scheduler_component_PrivateType*  omx_video_scheduler_component_Private = openmaxStandComp->pComponentPrivate;
00560   omx_base_video_PortType                     *pPort;
00561   omx_base_clock_PortType                     *pClockPort;
00562 
00563   if (ComponentParameterStructure == NULL) {
00564     return OMX_ErrorBadParameter;
00565   }
00566 
00567   DEBUG(DEB_LEV_SIMPLE_SEQ, "   Setting parameter %i\n", nParamIndex);
00568   switch(nParamIndex) {
00569      case OMX_IndexParamPortDefinition:
00570       pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE*) ComponentParameterStructure;
00571       portIndex = pPortDef->nPortIndex;
00572       err = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
00573       if(err!=OMX_ErrorNone) {
00574         DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n",__func__,err);
00575         break;
00576       }
00577 
00578       if(portIndex > (omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts +
00579                       omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) {
00580         return OMX_ErrorBadPortIndex;
00581       }
00582 
00583       if(portIndex < CLOCKPORT_INDEX) {
00584         pPort = (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[portIndex];
00585         pPort->sPortParam.nBufferCountActual = pPortDef->nBufferCountActual;
00586         //  Copy stuff from OMX_VIDEO_PORTDEFINITIONTYPE structure
00587         if(pPortDef->format.video.cMIMEType != NULL) {
00588           strcpy(pPort->sPortParam.format.video.cMIMEType , pPortDef->format.video.cMIMEType);
00589         }
00590         pPort->sPortParam.format.video.nFrameWidth  = pPortDef->format.video.nFrameWidth;
00591         pPort->sPortParam.format.video.nFrameHeight = pPortDef->format.video.nFrameHeight;
00592         pPort->sPortParam.format.video.nBitrate     = pPortDef->format.video.nBitrate;
00593         pPort->sPortParam.format.video.xFramerate   = pPortDef->format.video.xFramerate;
00594         pPort->sPortParam.format.video.bFlagErrorConcealment = pPortDef->format.video.bFlagErrorConcealment;
00595 
00596         //  Figure out stride, slice height, min buffer size
00597         pPort->sPortParam.format.video.nStride      = pPortDef->format.video.nStride;
00598         pPort->sPortParam.format.video.nSliceHeight = pPort->sPortParam.format.video.nFrameHeight;  //  No support for slices yet
00599         // Read-only field by spec
00600 
00601         pPort->sPortParam.nBufferSize = (OMX_U32) abs(pPort->sPortParam.format.video.nStride) * pPort->sPortParam.format.video.nSliceHeight;
00602       } else {
00603         pClockPort = (omx_base_clock_PortType *) omx_video_scheduler_component_Private->ports[portIndex];
00604 
00605         pClockPort->sPortParam.nBufferCountActual   = pPortDef->nBufferCountActual;
00606         pClockPort->sPortParam.format.other.eFormat = pPortDef->format.other.eFormat;
00607       }
00608       break;
00609 
00610     case OMX_IndexParamVideoPortFormat:
00611       //  FIXME: How do we handle the nIndex member?
00612       pVideoPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00613       portIndex = pVideoPortFormat->nPortIndex;
00614       err = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pVideoPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
00615       if(err!=OMX_ErrorNone) {
00616         DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n",__func__,err);
00617         break;
00618       }
00619       pPort = (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[portIndex];
00620       if(portIndex > 1) {
00621         return OMX_ErrorBadPortIndex;
00622       }
00623       if (pVideoPortFormat->eCompressionFormat != OMX_VIDEO_CodingUnused)  {
00624         //  No compression allowed
00625         return OMX_ErrorUnsupportedSetting;
00626       }
00627 
00628       pPort->sVideoParam.xFramerate         = pVideoPortFormat->xFramerate;
00629       pPort->sVideoParam.eCompressionFormat = pVideoPortFormat->eCompressionFormat;
00630       pPort->sVideoParam.eColorFormat       = pVideoPortFormat->eColorFormat;
00631       break;
00632     case  OMX_IndexParamOtherPortFormat:
00633       pOtherPortFormat = (OMX_OTHER_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00634       portIndex        = pOtherPortFormat->nPortIndex;
00635       err = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pOtherPortFormat, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE));
00636       if(err!=OMX_ErrorNone) {
00637         DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n",__func__,err);
00638         break;
00639       }
00640       if(portIndex != CLOCKPORT_INDEX) {
00641         return OMX_ErrorBadPortIndex;
00642       }
00643       pClockPort = (omx_base_clock_PortType *) omx_video_scheduler_component_Private->ports[portIndex];
00644 
00645       pClockPort->sOtherParam.eFormat = pOtherPortFormat->eFormat;
00646       break;
00647 
00648     case OMX_IndexParamStandardComponentRole:
00649       pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)ComponentParameterStructure;
00650 
00651       if (omx_video_scheduler_component_Private->state != OMX_StateLoaded && omx_video_scheduler_component_Private->state != OMX_StateWaitForResources) {
00652         DEBUG(DEB_LEV_ERR, "In %s Incorrect State=%x lineno=%d\n",__func__,omx_video_scheduler_component_Private->state,__LINE__);
00653         return OMX_ErrorIncorrectStateOperation;
00654       }
00655 
00656       if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PARAM_COMPONENTROLETYPE))) != OMX_ErrorNone) {
00657         break;
00658       }
00659 
00660       if (strcmp( (char*) pComponentRole->cRole, VIDEO_SCHEDULER_COMP_ROLE)) {
00661         return OMX_ErrorBadParameter;
00662       }
00663       break;
00664 
00665     default: /*Call the base component function*/
00666       return omx_base_component_SetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00667   }
00668   return err;
00669 }
00670 
00671 OMX_ERRORTYPE omx_video_scheduler_component_GetParameter(
00672   OMX_HANDLETYPE hComponent,
00673   OMX_INDEXTYPE nParamIndex,
00674   OMX_PTR ComponentParameterStructure) {
00675 
00676   OMX_VIDEO_PARAM_PORTFORMATTYPE             *pVideoPortFormat;
00677   OMX_OTHER_PARAM_PORTFORMATTYPE             *pOtherPortFormat;
00678   OMX_ERRORTYPE                              err = OMX_ErrorNone;
00679   OMX_COMPONENTTYPE                          *openmaxStandComp = (OMX_COMPONENTTYPE *)hComponent;
00680   omx_video_scheduler_component_PrivateType* omx_video_scheduler_component_Private = openmaxStandComp->pComponentPrivate;
00681   omx_base_video_PortType                    *pPort;
00682   omx_base_clock_PortType                    *pClockPort = (omx_base_clock_PortType *) omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX];
00683   OMX_PARAM_COMPONENTROLETYPE                *pComponentRole;
00684 
00685   if (ComponentParameterStructure == NULL) {
00686     return OMX_ErrorBadParameter;
00687   }
00688   DEBUG(DEB_LEV_SIMPLE_SEQ, "   Getting parameter %i\n", nParamIndex);
00689   /* Check which structure we are being fed and fill its header */
00690   switch(nParamIndex) {
00691     case OMX_IndexParamVideoInit:
00692       if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) {
00693         break;
00694       }
00695       memcpy(ComponentParameterStructure, &omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE));
00696       break;
00697     case OMX_IndexParamOtherInit:
00698       if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) {
00699         break;
00700       }
00701       memcpy(ComponentParameterStructure, &omx_video_scheduler_component_Private->sPortTypesParam[OMX_PortDomainOther], sizeof(OMX_PORT_PARAM_TYPE));
00702       break;
00703     case OMX_IndexParamVideoPortFormat:
00704       pVideoPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00705       pPort = (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[pVideoPortFormat->nPortIndex];
00706       if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone) {
00707         break;
00708       }
00709       if (pVideoPortFormat->nPortIndex < CLOCKPORT_INDEX) {
00710         memcpy(pVideoPortFormat, &pPort->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
00711       } else {
00712         return OMX_ErrorBadPortIndex;
00713       }
00714       break;
00715     case  OMX_IndexParamOtherPortFormat:
00716       pOtherPortFormat = (OMX_OTHER_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00717       if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone) {
00718         break;
00719       }
00720       if (pOtherPortFormat->nPortIndex == CLOCKPORT_INDEX) {
00721         memcpy(pOtherPortFormat, &pClockPort->sOtherParam, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE));
00722       } else {
00723         return OMX_ErrorBadPortIndex;
00724       }
00725       break;
00726 
00727     case OMX_IndexParamStandardComponentRole:
00728       pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)ComponentParameterStructure;
00729       if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PARAM_COMPONENTROLETYPE))) != OMX_ErrorNone) {
00730         break;
00731       }
00732       strcpy( (char*) pComponentRole->cRole, VIDEO_SCHEDULER_COMP_ROLE);
00733       break;
00734 
00735     default: /*Call the base component function*/
00736       return omx_base_component_GetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00737   }
00738   return err;
00739 }
00740