|
OpenMAXBellagio 0.9.3
|
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