OMX_ERRORTYPE volumeEmptyBufferDone( OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) { OMX_ERRORTYPE err; static int iBufferDropped = 0; if(pBuffer != NULL) { if(!bEOS) { if(pOutBuffer[0]->pBuffer == pBuffer->pBuffer) { pOutBuffer[0]->nFilledLen = pBuffer->nFilledLen; err = OMX_FillThisBuffer(appPriv->audiosrchandle, pOutBuffer[0]); } else { pOutBuffer[1]->nFilledLen = pBuffer->nFilledLen; err = OMX_FillThisBuffer(appPriv->audiosrchandle, pOutBuffer[1]); } if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s Error %08x Calling FillThisBuffer\n", __func__,err); } } else { DEBUG(DEB_LEV_ERR, "In %s: eos=%x Dropping Fill This Buffer\n", __func__,(int)pBuffer->nFlags); iBufferDropped++; if(iBufferDropped == 2) { tsem_up(appPriv->eofSem); } } } else { if(!bEOS) { tsem_up(appPriv->eofSem); } DEBUG(DEB_LEV_ERR, "Ouch! In %s: had NULL buffer to output...\n", __func__); } return OMX_ErrorNone; }
OMX_ERRORTYPE omx_clocksrc_component_SendCommand( OMX_HANDLETYPE hComponent, OMX_COMMANDTYPE Cmd, OMX_U32 nParam, OMX_PTR pCmdData) { OMX_COMPONENTTYPE* omxComponent = (OMX_COMPONENTTYPE*)hComponent; omx_clocksrc_component_PrivateType* omx_clocksrc_component_Private = (omx_clocksrc_component_PrivateType*)omxComponent->pComponentPrivate; OMX_U32 nMask; switch (Cmd) { case OMX_CommandPortDisable: if (nParam >= omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts && nParam != OMX_ALL) { return OMX_ErrorBadPortIndex; } if(nParam == OMX_ALL) { nMask = 0xFF; } else { nMask = 0x1 << nParam; } omx_clocksrc_component_Private->sClockState.nWaitMask &= (~nMask); DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s nWaitMask =%08x Musk=%x\n",__func__, (int)omx_clocksrc_component_Private->sClockState.nWaitMask,(int)(~nMask)); break; case OMX_CommandPortEnable: if (nParam >= omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts && nParam != OMX_ALL) { return OMX_ErrorBadPortIndex; } if(nParam == OMX_ALL) { nMask = 0xFF; } else { nMask = 0x1 << nParam; } omx_clocksrc_component_Private->sClockState.nWaitMask &= nMask; DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s nWaitMask =%08x Musk=%x\n",__func__, (int)omx_clocksrc_component_Private->sClockState.nWaitMask,(int)nMask); break; case OMX_CommandStateSet: if ((nParam == OMX_StateLoaded) && (omx_clocksrc_component_Private->state == OMX_StateIdle)) { omx_clocksrc_component_Private->transientState = OMX_TransStateIdleToLoaded; /*Signal buffer management thread to exit*/ tsem_up(omx_clocksrc_component_Private->clockEventSem); } else if ((nParam == OMX_StateExecuting) && (omx_clocksrc_component_Private->state == OMX_StatePause)) { /*Dummy signal to the clock buffer management function*/ omx_clocksrc_component_Private->transientState = OMX_TransStatePauseToExecuting; tsem_up(omx_clocksrc_component_Private->clockEventSem); } else if (nParam == OMX_StateInvalid) { omx_clocksrc_component_Private->transientState = OMX_TransStateInvalid; /*Signal buffer management thread to exit*/ tsem_up(omx_clocksrc_component_Private->clockEventSem); } break; default: break; } DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s calling omx_base_component_SendCommand\n",__func__); return omx_base_component_SendCommand(hComponent,Cmd,nParam,pCmdData); }
OMX_ERRORTYPE filereaderEventHandler( OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_EVENTTYPE eEvent, OMX_OUT OMX_U32 Data1, OMX_OUT OMX_U32 Data2, OMX_OUT OMX_PTR pEventData) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Hi there, I am in the %s callback\n", __func__); if(eEvent == OMX_EventCmdComplete) { if (Data1 == OMX_CommandStateSet) { DEBUG(DEB_LEV_SIMPLE_SEQ, "File Reader State changed in "); switch ((int)Data2) { case OMX_StateInvalid: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateInvalid\n"); break; case OMX_StateLoaded: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateLoaded\n"); break; case OMX_StateIdle: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateIdle\n"); break; case OMX_StateExecuting: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateExecuting\n"); break; case OMX_StatePause: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StatePause\n"); break; case OMX_StateWaitForResources: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateWaitForResources\n"); break; } tsem_up(appPriv->filereaderEventSem); } else if (Data1 == OMX_CommandPortEnable){ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Received Port Enable Event\n",__func__); tsem_up(appPriv->filereaderEventSem); } else if (Data1 == OMX_CommandPortDisable){ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Received Port Disable Event\n",__func__); tsem_up(appPriv->filereaderEventSem); } else { DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s Received Event Event=%d Data1=%d,Data2=%d\n",__func__,eEvent,(int)Data1,(int)Data2); } }else if(eEvent == OMX_EventPortSettingsChanged) { DEBUG(DEB_LEV_SIMPLE_SEQ,"File reader Port Setting Changed event\n"); }else if(eEvent == OMX_EventPortFormatDetected) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Port Format Detected %x\n", __func__,(int)Data1); } else if(eEvent == OMX_EventBufferFlag) { DEBUG(DEFAULT_MESSAGES, "In %s OMX_BUFFERFLAG_EOS\n", __func__); if((int)Data2 == OMX_BUFFERFLAG_EOS) { bEOS=OMX_TRUE; tsem_up(appPriv->eofSem); } } else { DEBUG(DEB_LEV_SIMPLE_SEQ, "Param1 is %i\n", (int)Data1); DEBUG(DEB_LEV_SIMPLE_SEQ, "Param2 is %i\n", (int)Data2); } return OMX_ErrorNone; }
/** callbacks implementation of camera component */ static OMX_ERRORTYPE camera_sourceEventHandler( OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_EVENTTYPE eEvent, OMX_OUT OMX_U32 Data1, OMX_OUT OMX_U32 Data2, OMX_OUT OMX_PTR pEventData) { DEBUG(DEB_LEV_FUNCTION_NAME, "In %s for camera component\n",__func__); DEBUG(DEB_LEV_SIMPLE_SEQ, "Hi there, I am in the %s callback\n", __func__); DEBUG(DEB_LEV_SIMPLE_SEQ, "%s: event type code (eEvent)=%d\n", __func__, eEvent); if(eEvent == OMX_EventCmdComplete) { if (Data1 == OMX_CommandStateSet) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Set state to "); switch ((int)Data2) { case OMX_StateLoaded: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateLoaded\n"); break; case OMX_StateIdle: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateIdle\n"); break; case OMX_StateExecuting: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateExecuting\n"); break; case OMX_StatePause: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StatePause\n"); break; case OMX_StateWaitForResources: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateWaitForResources\n"); break; default: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateInvalid\n"); break; } tsem_up(appPriv->cameraSourceEventSem); } else { if(Data1 == OMX_CommandPortEnable) { tsem_up(appPriv->cameraSourceEventSem); } } } DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s for camera component, return code: 0x%X\n",__func__, OMX_ErrorNone); return OMX_ErrorNone; }
/** Callbacks implementation of the audio source component*/ OMX_ERRORTYPE audiosrcEventHandler( OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_EVENTTYPE eEvent, OMX_OUT OMX_U32 Data1, OMX_OUT OMX_U32 Data2, OMX_OUT OMX_PTR pEventData) { OMX_ERRORTYPE err = OMX_ErrorNone; DEBUG(DEB_LEV_SIMPLE_SEQ, "Hi there, I am in the %s callback\n", __func__); if(eEvent == OMX_EventCmdComplete) { if (Data1 == OMX_CommandStateSet) { DEBUG(DEB_LEV_SIMPLE_SEQ, "State changed in "); switch ((int)Data2) { case OMX_StateInvalid: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateInvalid\n"); break; case OMX_StateLoaded: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateLoaded\n"); break; case OMX_StateIdle: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateIdle\n"); break; case OMX_StateExecuting: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateExecuting\n"); break; case OMX_StatePause: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StatePause\n"); break; case OMX_StateWaitForResources: DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateWaitForResources\n"); break; } tsem_up(appPriv->sourceEventSem); } else if (OMX_CommandPortEnable || OMX_CommandPortDisable) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Received Port Enable/Disable Event\n",__func__); tsem_up(appPriv->sourceEventSem); } } else if(eEvent == OMX_EventPortSettingsChanged) { DEBUG(DEB_LEV_SIMPLE_SEQ, "\n port settings change event handler in %s \n", __func__); } else if(eEvent == OMX_EventBufferFlag) { DEBUG(DEB_LEV_ERR, "In %s OMX_BUFFERFLAG_EOS\n", __func__); if((int)Data2 == OMX_BUFFERFLAG_EOS) { tsem_up(appPriv->eofSem); } } else { DEBUG(DEB_LEV_SIMPLE_SEQ, "Param1 is %i\n", (int)Data1); DEBUG(DEB_LEV_SIMPLE_SEQ, "Param2 is %i\n", (int)Data2); } return err; }
OMX_ERRORTYPE volcEmptyBufferDone( OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) { int data_read; static int iBufferDropped=0; DEBUG(DEB_LEV_FULL_SEQ, "Hi there, I am in the %s callback.\n", __func__); data_read = read(fd, pBuffer->pBuffer, BUFFER_IN_SIZE); pBuffer->nFilledLen = data_read; pBuffer->nOffset = 0; filesize -= data_read; if (data_read <= 0) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In the %s no more input data available\n", __func__); iBufferDropped++; if(iBufferDropped>=2) { tsem_up(appPriv->eofSem); return OMX_ErrorNone; } pBuffer->nFilledLen=0; pBuffer->nFlags = OMX_BUFFERFLAG_EOS; bEOS=OMX_TRUE; err = OMX_EmptyThisBuffer(hComponent, pBuffer); return OMX_ErrorNone; } if(!bEOS) { DEBUG(DEB_LEV_FULL_SEQ, "Empty buffer %x\n", (int)pBuffer); err = OMX_EmptyThisBuffer(hComponent, pBuffer); }else { DEBUG(DEB_LEV_FULL_SEQ, "In %s Dropping Empty This buffer to Audio Dec\n", __func__); } return OMX_ErrorNone; }
/** Initialize libshcodecs, and open a decoder for the format specified by IL client */ OMX_ERRORTYPE omx_shvpudec_component_ffmpegLibInit(omx_shvpudec_component_PrivateType* omx_shvpudec_component_Private) { //OMX_U32 target_codecID; SHCodecs_Format format; omx_base_video_PortType *inPort; inPort = (omx_base_video_PortType *)omx_shvpudec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; switch(omx_shvpudec_component_Private->video_coding_type) { case OMX_VIDEO_CodingMPEG4 : //target_codecID = CODEC_ID_MPEG4; format = SHCodecs_Format_MPEG4; break; case OMX_VIDEO_CodingAVC : //target_codecID = CODEC_ID_H264; format = SHCodecs_Format_H264; break; default : DEBUG(DEB_LEV_ERR, "\n codecs other than H.264 / MPEG-4 AVC are not supported -- codec not found\n"); return OMX_ErrorComponentNotFound; } DEBUG(DEB_LEV_SIMPLE_SEQ, "Initializing VPU decoder, format %d, width %d, height %d\n", format, inPort->sPortParam.format.video.nFrameWidth, inPort->sPortParam.format.video.nFrameHeight); /** Initialize the VPU4 decoder */ omx_shvpudec_component_Private->decoder = #if 0 shcodecs_decoder_init (inPort->sPortParam.format.video.nFrameWidth, inPort->sPortParam.format.video.nFrameHeight, format); #else /* XXX */ shcodecs_decoder_init (DEFAULT_WIDTH, DEFAULT_HEIGHT, format); #endif if (omx_shvpudec_component_Private->decoder == NULL) { DEBUG(DEB_LEV_ERR, "Unable to initialize VPU4 decoder\n"); return OMX_ErrorInsufficientResources; } //omx_shvpudec_component_Private->avCodecContext = avcodec_alloc_context(); tsem_up(omx_shvpudec_component_Private->avCodecSyncSem); //shcodecs_decoder_set_frame_by_frame (omx_shvpudec_component_Private->decoder, 1); DEBUG(DEB_LEV_SIMPLE_SEQ, "done\n"); return OMX_ErrorNone; }
/** @brief The OMX_Init standard function * * This function calls the init function of each component loader added. If there * is no component loaders present, the ST default component loader (static libraries) * is loaded as default component loader. * * @return OMX_ErrorNone */ OMX_ERRORTYPE OMX_Init() { int i = 0; OMX_ERRORTYPE err = OMX_ErrorNone, errLoader = OMX_ErrorInsufficientResources; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); /* Get a lock in case multiple thread are calling OMX_Init at the same time */ tsem_down(&initSem); if(initialized == 0) { if (createComponentLoaders()) { tsem_up(&initSem); return OMX_ErrorInsufficientResources; } for (i = 0; i < bosa_loaders; i++) { err = loadersList[i]->BOSA_InitComponentLoader((struct BOSA_COMPONENTLOADER *) loadersList[i]); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Component loader %d constructor fails. Error= 0x%08x \n",i, err); /* The loader failed to initialize itself -> discarding it for the session */ free((void *) loadersList[i]); loadersList[i] = 0; } // Returning OMX_ErrorNone if at least one loader has been able to initialize itself if (err == OMX_ErrorNone) { errLoader = OMX_ErrorNone; } } } else { /* In case core already initialized things are fine */ errLoader = OMX_ErrorNone; } initialized ++; tsem_up(&initSem); DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s\n", __func__); return errLoader; }
/** It initializates the FFmpeg framework, and opens an FFmpeg videoencoder of type specified by IL client */ OMX_ERRORTYPE omx_videoenc_component_ffmpegLibInit(omx_videoenc_component_PrivateType* omx_videoenc_component_Private) { omx_base_video_PortType *inPort = (omx_base_video_PortType *)omx_videoenc_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; OMX_U32 target_coencID; avcodec_init(); av_register_all(); DEBUG(DEB_LEV_SIMPLE_SEQ, "FFmpeg library/encoder initialized\n"); switch(omx_videoenc_component_Private->video_encoding_type) { case OMX_VIDEO_CodingMPEG4 : target_coencID = CODEC_ID_MPEG4; break; default : DEBUG(DEB_LEV_ERR, "\n encoders other than MPEG-4 are not supported -- encoder not found\n"); return OMX_ErrorComponentNotFound; } /** Find the encoder corresponding to the video type specified by IL client*/ omx_videoenc_component_Private->avCodec = avcodec_find_encoder(target_coencID); if (omx_videoenc_component_Private->avCodec == NULL) { DEBUG(DEB_LEV_ERR, "Encoder Not found\n"); return OMX_ErrorInsufficientResources; } omx_videoenc_component_Private->avCodecContext = avcodec_alloc_context(); omx_videoenc_component_Private->picture = avcodec_alloc_frame (); /* put sample parameters */ omx_videoenc_component_Private->avCodecContext->bit_rate = 400000; /* bit per second */ omx_videoenc_component_Private->avCodecContext->width = inPort->sPortParam.format.video.nFrameWidth; omx_videoenc_component_Private->avCodecContext->height = inPort->sPortParam.format.video.nFrameHeight; /* frames per second */ DEBUG(DEB_LEV_SIMPLE_SEQ, "Frame Rate=%d\n",(int)inPort->sPortParam.format.video.xFramerate); omx_videoenc_component_Private->avCodecContext->time_base= (AVRational){1,inPort->sPortParam.format.video.xFramerate}; omx_videoenc_component_Private->avCodecContext->gop_size = 5; /* emit one intra frame every ten frames */ omx_videoenc_component_Private->avCodecContext->max_b_frames=1; omx_videoenc_component_Private->avCodecContext->pix_fmt = PIX_FMT_YUV420P; if (avcodec_open(omx_videoenc_component_Private->avCodecContext, omx_videoenc_component_Private->avCodec) < 0) { DEBUG(DEB_LEV_ERR, "Could not open encoder\n"); return OMX_ErrorInsufficientResources; } tsem_up(omx_videoenc_component_Private->avCodecSyncSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "done\n"); return OMX_ErrorNone; }
/** @brief The OMX_Deinit standard function * * In this function the Deinit function for each component loader is performed */ OMX_ERRORTYPE OMX_Deinit() { int i = 0; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); tsem_down(&initSem); initialized --; if(initialized == 0) { for (i = 0; i < bosa_loaders; i++) { if(loadersList[i]) { loadersList[i]->BOSA_DeInitComponentLoader((struct BOSA_COMPONENTLOADER *) loadersList[i]); free((void *) loadersList[i]); loadersList[i] = 0; } } free(loadersList); loadersList = 0; bosa_loaders = 0; } tsem_up(&initSem); DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s\n", __func__); return OMX_ErrorNone; }
/** The Initialization function */ OMX_ERRORTYPE omx_videosrc_component_Init(OMX_COMPONENTTYPE *openmaxStandComp) { omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate; omx_base_video_PortType *pPort = (omx_base_video_PortType *)omx_videosrc_component_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX]; OMX_ERRORTYPE err = OMX_ErrorNone; DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__); /* Presently V4L2_PIX_FMT_YUV420 format is supported by the camera */ switch(pPort->sPortParam.format.video.eColorFormat) { case OMX_COLOR_FormatYUV420Planar: case OMX_COLOR_FormatYUV420PackedPlanar: omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV420; break; case OMX_COLOR_Format16bitRGB565: omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_RGB565 ; // 565 16 bit RGB // omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth* pPort->sPortParam.format.video.nFrameHeight*2; omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth* pPort->sPortParam.format.video.nFrameHeight*2; break; case OMX_COLOR_Format24bitRGB888: omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_RGB24 ; // 24bit RGB // omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth* pPort->sPortParam.format.video.nFrameHeight*3; break; case OMX_COLOR_Format32bitARGB8888: omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_RGB32 ; // 32bit RGB // omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth* pPort->sPortParam.format.video.nFrameHeight*4; break; case OMX_COLOR_FormatYUV422Planar: omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV422P ; // YUV 4:2:2 Planar // omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth* pPort->sPortParam.format.video.nFrameHeight*2; break; case OMX_COLOR_FormatYUV411Planar: omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV411P ; // YUV 4:1:1 Planar // break; default: omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV420; break; } /** Initialize video capture pixel format */ omx_videosrc_component_Private->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; omx_videosrc_component_Private->fmt.fmt.pix.width = pPort->sPortParam.format.video.nFrameWidth; omx_videosrc_component_Private->fmt.fmt.pix.height = pPort->sPortParam.format.video.nFrameHeight; omx_videosrc_component_Private->fmt.fmt.pix.pixelformat = omx_videosrc_component_Private->pixel_format; omx_videosrc_component_Private->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_S_FMT, &omx_videosrc_component_Private->fmt)) return errno_return("VIDIOC_S_FMT"); // Note VIDIOC_S_FMT may change width and height. // pPort->sPortParam.format.video.nFrameWidth = omx_videosrc_component_Private->fmt.fmt.pix.width; pPort->sPortParam.format.video.nFrameHeight = omx_videosrc_component_Private->fmt.fmt.pix.height; /*output frame size*/ omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth* pPort->sPortParam.format.video.nFrameHeight*3/2; DEBUG(DEB_ALL_MESS,"Frame Width=%d, Height=%d, Frame Size=%d n_buffers=%d\n", (int)pPort->sPortParam.format.video.nFrameWidth, (int)pPort->sPortParam.format.video.nFrameHeight, (int)omx_videosrc_component_Private->iFrameSize,n_buffers); /** initialization for buff mgmt callback function */ omx_videosrc_component_Private->bIsEOSSent = OMX_FALSE; err = start_capturing(omx_videosrc_component_Private); omx_videosrc_component_Private->videoReady = OMX_TRUE; /*Indicate that video is ready*/ tsem_up(omx_videosrc_component_Private->videoSyncSem); return err; }
/** The initialization function * This function opens the frame buffer device and allocates memory for display * also it finds the frame buffer supported display formats */ OMX_ERRORTYPE omx_xvideo_sink_component_Init(OMX_COMPONENTTYPE *openmaxStandComp) { omx_xvideo_sink_component_PrivateType* omx_xvideo_sink_component_Private = openmaxStandComp->pComponentPrivate; omx_xvideo_sink_component_PortType* pPort = (omx_xvideo_sink_component_PortType *) omx_xvideo_sink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; int yuv_width = pPort->sPortParam.format.video.nFrameWidth; int yuv_height = pPort->sPortParam.format.video.nFrameHeight; unsigned int err,i; omx_xvideo_sink_component_Private->dpy = XOpenDisplay(NULL); omx_xvideo_sink_component_Private->screen = DefaultScreen(omx_xvideo_sink_component_Private->dpy); XGetWindowAttributes(omx_xvideo_sink_component_Private->dpy, DefaultRootWindow(omx_xvideo_sink_component_Private->dpy), &omx_xvideo_sink_component_Private->attribs); XMatchVisualInfo(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->screen, omx_xvideo_sink_component_Private->attribs.depth, TrueColor, & omx_xvideo_sink_component_Private->vinfo); omx_xvideo_sink_component_Private->wmDeleteWindow = XInternAtom(omx_xvideo_sink_component_Private->dpy, "WM_DELETE_WINDOW", False); omx_xvideo_sink_component_Private->hint.x = 1; omx_xvideo_sink_component_Private->hint.y = 1; omx_xvideo_sink_component_Private->hint.width = yuv_width; omx_xvideo_sink_component_Private->hint.height = yuv_height; omx_xvideo_sink_component_Private->hint.flags = PPosition | PSize; omx_xvideo_sink_component_Private->xswa.colormap = XCreateColormap(omx_xvideo_sink_component_Private->dpy, DefaultRootWindow(omx_xvideo_sink_component_Private->dpy), omx_xvideo_sink_component_Private->vinfo.visual, AllocNone); omx_xvideo_sink_component_Private->xswa.event_mask = StructureNotifyMask | ExposureMask; omx_xvideo_sink_component_Private->xswa.background_pixel = 0; omx_xvideo_sink_component_Private->xswa.border_pixel = 0; omx_xvideo_sink_component_Private->window = XCreateWindow(omx_xvideo_sink_component_Private->dpy, DefaultRootWindow(omx_xvideo_sink_component_Private->dpy), 0, 0, yuv_width, yuv_height, 0, omx_xvideo_sink_component_Private->vinfo.depth, InputOutput, omx_xvideo_sink_component_Private->vinfo.visual, CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &omx_xvideo_sink_component_Private->xswa); XSelectInput(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window, StructureNotifyMask); XSetStandardProperties(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window, "xvcam", "xvcam", None, NULL, 0, &omx_xvideo_sink_component_Private->hint); XSetWMProtocols(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window, &omx_xvideo_sink_component_Private->wmDeleteWindow, 1); XMapWindow(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window); if (XShmQueryExtension(omx_xvideo_sink_component_Private->dpy)) omx_xvideo_sink_component_Private->CompletionType = XShmGetEventBase(omx_xvideo_sink_component_Private->dpy) + ShmCompletion; else return OMX_ErrorUndefined; if (Success != XvQueryExtension(omx_xvideo_sink_component_Private->dpy, &omx_xvideo_sink_component_Private->ver, &omx_xvideo_sink_component_Private->rel, &omx_xvideo_sink_component_Private->req, &omx_xvideo_sink_component_Private->ev, &err)) fprintf(stderr, "Couldn't do Xv stuff\n"); if (Success != XvQueryAdaptors(omx_xvideo_sink_component_Private->dpy, DefaultRootWindow(omx_xvideo_sink_component_Private->dpy), &omx_xvideo_sink_component_Private->adapt, &omx_xvideo_sink_component_Private->ai)) fprintf(stderr, "Couldn't do Xv stuff\n"); for (i = 0; i < (int) omx_xvideo_sink_component_Private->adapt; i++) { omx_xvideo_sink_component_Private->xv_port = omx_xvideo_sink_component_Private->ai[i].base_id; } if (omx_xvideo_sink_component_Private->adapt > 0) XvFreeAdaptorInfo(omx_xvideo_sink_component_Private->ai); omx_xvideo_sink_component_Private->gc = XCreateGC(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->window, 0, 0); omx_xvideo_sink_component_Private->yuv_image = XvShmCreateImage(omx_xvideo_sink_component_Private->dpy, omx_xvideo_sink_component_Private->xv_port, GUID_I420_PLANAR, 0, yuv_width, yuv_height, &omx_xvideo_sink_component_Private->yuv_shminfo); omx_xvideo_sink_component_Private->yuv_shminfo.shmid = shmget(IPC_PRIVATE, omx_xvideo_sink_component_Private->yuv_image->data_size, IPC_CREAT | 0777); omx_xvideo_sink_component_Private->yuv_shminfo.shmaddr = (char *) shmat(omx_xvideo_sink_component_Private->yuv_shminfo.shmid, 0, 0); omx_xvideo_sink_component_Private->yuv_image->data = omx_xvideo_sink_component_Private->yuv_shminfo.shmaddr; omx_xvideo_sink_component_Private->yuv_shminfo.readOnly = False; if (!XShmAttach(omx_xvideo_sink_component_Private->dpy, &omx_xvideo_sink_component_Private->yuv_shminfo)) { printf("XShmAttach go boom boom!\n"); return OMX_ErrorUndefined; } omx_xvideo_sink_component_Private->old_time = 0; omx_xvideo_sink_component_Private->new_time = 0; omx_xvideo_sink_component_Private->bIsXVideoInit = OMX_TRUE; /*Signal XVideo Initialized*/ tsem_up(omx_xvideo_sink_component_Private->xvideoSyncSem); return OMX_ErrorNone; }
/** @brief Called by the standard allocate buffer, it implements a base functionality. * * This function can be overriden if the allocation of the buffer is not a simply alloc call. * The parameters are the same as the standard function, except for the handle of the port * instead of the handler of the component * When the buffers needed by this port are all assigned or allocated, the variable * bIsFullOfBuffers becomes equal to OMX_TRUE */ OMX_ERRORTYPE camera_video_port_AllocateBuffer( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE **pBuffer, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, OMX_U32 nSizeBytes) { unsigned int i; OMX_COMPONENTTYPE *omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType *omx_base_component_Private = (omx_base_component_PrivateType *)omxComponent->pComponentPrivate; omx_base_camera_video_PortType *omx_base_video_Port = (omx_base_camera_video_PortType *)openmaxStandPort; OMXDBUG(OMXDBUG_VERB, "In %s for port %p\n", __func__, openmaxStandPort); if(nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { return OMX_ErrorBadPortIndex; } if(PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) { if(!openmaxStandPort->bIsTransientToEnabled) { OMXDBUG(OMXDBUG_ERR, "In %s: The port is not allowed to receive buffers\n", __func__); return OMX_ErrorIncorrectStateTransition; } } if(nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) { OMXDBUG(OMXDBUG_ERR, "In %s: Requested Buffer Size %lu is less than Minimum Buffer Size %lu\n", __func__, nSizeBytes, openmaxStandPort->sPortParam.nBufferSize); return OMX_ErrorIncorrectStateTransition; } if(omx_base_video_Port->pBufferHeadAct == NULL) { omx_base_video_Port->pBufferHeadAct = calloc(openmaxStandPort->sPortParam.nBufferCountActual, sizeof(OMX_BUFFERHEADERTYPE_ACTEXT)); if(omx_base_video_Port->pBufferHeadAct == NULL) { return OMX_ErrorInsufficientResources; } } for(i = 0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++) { if(openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { openmaxStandPort->pInternalBufferStorage[i] = calloc(1, sizeof(OMX_BUFFERHEADERTYPE)); if(!openmaxStandPort->pInternalBufferStorage[i]) { return OMX_ErrorInsufficientResources; } setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)); /* allocate the buffer */ #if 0 openmaxStandPort->pInternalBufferStorage[i]->pBuffHead.pBuffer = calloc(1, nSizeBytes); #else { unsigned long pVirAddr = 0; openmaxStandPort->pInternalBufferStorage[i]->pBuffer = (OMX_U8 *)ext_phycalloc_mem(1, nSizeBytes, (void *)&pVirAddr); omx_base_video_Port->pBufferHeadAct[i].pConfigParam.VirAddr = (OMX_U8 *)pVirAddr; omx_base_video_Port->pBufferHeadAct[i].pConfigParam.phyAddr = openmaxStandPort->pInternalBufferStorage[i]->pBuffer; openmaxStandPort->pInternalBufferStorage[i]->pBuffer = omx_base_video_Port->pBufferHeadAct[i].pConfigParam.VirAddr; omx_base_video_Port->pBufferHeadAct[i].pConfigParam.bAllocByComp = OMX_TRUE; } #endif if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer == NULL) { return OMX_ErrorInsufficientResources; } omx_base_video_Port->pBufferHeadAct[i].pBuffHead = openmaxStandPort->pInternalBufferStorage[i]; openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = nSizeBytes; openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort; openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate; *pBuffer = (OMX_BUFFERHEADERTYPE *)openmaxStandPort->pInternalBufferStorage[i]; openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED; openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED; if(openmaxStandPort->sPortParam.eDir == OMX_DirInput) { openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; } else { openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; } openmaxStandPort->nNumAssignedBuffers++; OMXDBUG(OMXDBUG_VERB, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); if(openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; OMXDBUG(OMXDBUG_VERB, "In %s nPortIndex=%d\n", __func__, (int)nPortIndex); tsem_up(openmaxStandPort->pAllocSem); } OMXDBUG(OMXDBUG_VERB, "Out of %s for port %p\n", __func__, openmaxStandPort); return OMX_ErrorNone; } } OMXDBUG(OMXDBUG_ERR, "Out of %s for port %p. Error: no available buffers\n", __func__, openmaxStandPort); return OMX_ErrorInsufficientResources; }
/** @brief Releases buffers under processing. * This function must be implemented in the derived classes, for the * specific processing */ OMX_ERRORTYPE clocksrc_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort) { omx_clocksrc_component_PrivateType* omx_clocksrc_component_Private; OMX_BUFFERHEADERTYPE* pBuffer; int errQue; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); omx_clocksrc_component_Private = (omx_clocksrc_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); openmaxStandPort->bIsPortFlushed=OMX_TRUE; /*Signal the buffer management thread of port flush,if it is waiting for buffers*/ if(omx_clocksrc_component_Private->bMgmtSem->semval==0) { tsem_up(omx_clocksrc_component_Private->bMgmtSem); } tsem_up(omx_clocksrc_component_Private->clockEventSem); tsem_up(omx_clocksrc_component_Private->clockEventCompleteSem); if(omx_clocksrc_component_Private->state==OMX_StatePause ) { /*Waiting at paused state*/ tsem_signal(omx_clocksrc_component_Private->bStateSem); } DEBUG(DEB_LEV_FULL_SEQ, "In %s waiting for flush all condition port index =%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); /* Wait until flush is completed */ pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); tsem_down(omx_clocksrc_component_Private->flush_all_condition); tsem_reset(omx_clocksrc_component_Private->bMgmtSem); tsem_reset(omx_clocksrc_component_Private->clockEventSem); /* Flush all the buffers not under processing */ while (openmaxStandPort->pBufferSem->semval > 0) { DEBUG(DEB_LEV_FULL_SEQ, "In %s TFlag=%x Flusing Port=%d,Semval=%d Qelem=%d\n", __func__,(int)openmaxStandPort->nTunnelFlags,(int)openmaxStandPort->sPortParam.nPortIndex, (int)openmaxStandPort->pBufferSem->semval,(int)openmaxStandPort->pBufferQueue->nelem); tsem_down(openmaxStandPort->pBufferSem); pBuffer = dequeue(openmaxStandPort->pBufferQueue); if (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s is returning io:%d buffer\n", __func__,omx_clocksrc_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); } else { ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); } } else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { errQue = queue(openmaxStandPort->pBufferQueue,pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } } else { (*(openmaxStandPort->BufferProcessedCallback))( openmaxStandPort->standCompContainer, omx_clocksrc_component_Private->callbackData, pBuffer); } } /*Port is tunneled and supplier and didn't received all it's buffer then wait for the buffers*/ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { while(openmaxStandPort->pBufferQueue->nelem!= openmaxStandPort->nNumAssignedBuffers){ tsem_down(openmaxStandPort->pBufferSem); DEBUG(DEB_LEV_PARAMS, "In %s Got a buffer qelem=%d\n",__func__,openmaxStandPort->pBufferQueue->nelem); } tsem_reset(openmaxStandPort->pBufferSem); } pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); openmaxStandPort->bIsPortFlushed=OMX_FALSE; pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); tsem_up(omx_clocksrc_component_Private->flush_condition); DEBUG(DEB_LEV_FULL_SEQ, "Out %s Port Index=%d bIsPortFlushed=%d Component %s\n", __func__, (int)openmaxStandPort->sPortParam.nPortIndex,(int)openmaxStandPort->bIsPortFlushed,omx_clocksrc_component_Private->name); DEBUG(DEB_LEV_PARAMS, "In %s TFlag=%x Qelem=%d BSem=%d bMgmtsem=%d component=%s\n", __func__, (int)openmaxStandPort->nTunnelFlags, (int)openmaxStandPort->pBufferQueue->nelem, (int)openmaxStandPort->pBufferSem->semval, (int)omx_clocksrc_component_Private->bMgmtSem->semval, omx_clocksrc_component_Private->name); DEBUG(DEB_LEV_FUNCTION_NAME, "Out %s Port Index=%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); return OMX_ErrorNone; }
OMX_ERRORTYPE omx_clocksrc_component_SetConfig( OMX_HANDLETYPE hComponent, OMX_INDEXTYPE nIndex, OMX_PTR pComponentConfigStructure) { OMX_COMPONENTTYPE* omxComponent = (OMX_COMPONENTTYPE*)hComponent; omx_clocksrc_component_PrivateType* omx_clocksrc_component_Private = (omx_clocksrc_component_PrivateType*)omxComponent->pComponentPrivate; OMX_TIME_CONFIG_CLOCKSTATETYPE* clockstate; OMX_TIME_CONFIG_TIMESTAMPTYPE* sRefTimeStamp; OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE* pRefClock; OMX_U32 portIndex; omx_base_clock_PortType *pPort; OMX_TIME_CONFIG_SCALETYPE *pConfigScale; OMX_U32 nMask; OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE* sMediaTimeRequest; int i; struct timeval tv; struct timezone zv; OMX_TICKS walltime, mediatime, mediaTimediff, wallTimediff; OMX_S32 Scale; unsigned int sleeptime; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); switch (nIndex) { case OMX_IndexConfigTimeClockState : { clockstate = (OMX_TIME_CONFIG_CLOCKSTATETYPE*) pComponentConfigStructure; switch (clockstate->eState) { case OMX_TIME_ClockStateRunning: if(omx_clocksrc_component_Private->sClockState.eState == OMX_TIME_ClockStateRunning) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Received OMX_TIME_ClockStateRunning again\n",__func__); } DEBUG(DEB_LEV_SIMPLE_SEQ,"in %s ...set to OMX_TIME_ClockStateRunning\n",__func__); memcpy(&omx_clocksrc_component_Private->sClockState, clockstate, sizeof(OMX_TIME_CONFIG_CLOCKSTATETYPE)); omx_clocksrc_component_Private->eUpdateType = OMX_TIME_UpdateClockStateChanged; /* update the state change in all port */ for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[i]; pPort->sMediaTime.eUpdateType = OMX_TIME_UpdateClockStateChanged; pPort->sMediaTime.eState = OMX_TIME_ClockStateRunning; pPort->sMediaTime.xScale = omx_clocksrc_component_Private->sConfigScale.xScale; } /*Signal Buffer Management Thread*/ tsem_up(omx_clocksrc_component_Private->clockEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for Clock Running Event for all ports\n"); tsem_down(omx_clocksrc_component_Private->clockEventCompleteSem); break; case OMX_TIME_ClockStateWaitingForStartTime: if(omx_clocksrc_component_Private->sClockState.eState == OMX_TIME_ClockStateRunning) { return OMX_ErrorIncorrectStateTransition; } else if(omx_clocksrc_component_Private->sClockState.eState == OMX_TIME_ClockStateWaitingForStartTime) { return OMX_ErrorSameState; } DEBUG(DEB_LEV_SIMPLE_SEQ," in %s ...set to OMX_TIME_ClockStateWaitingForStartTime mask sent=%d\n",__func__,(int)clockstate->nWaitMask); memcpy(&omx_clocksrc_component_Private->sClockState, clockstate, sizeof(OMX_TIME_CONFIG_CLOCKSTATETYPE)); break; case OMX_TIME_ClockStateStopped: DEBUG(DEB_LEV_SIMPLE_SEQ," in %s ...set to OMX_TIME_ClockStateStopped\n",__func__); memcpy(&omx_clocksrc_component_Private->sClockState, clockstate, sizeof(OMX_TIME_CONFIG_CLOCKSTATETYPE)); omx_clocksrc_component_Private->eUpdateType = OMX_TIME_UpdateClockStateChanged; /* update the state change in all port */ for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[i]; pPort->sMediaTime.eUpdateType = OMX_TIME_UpdateClockStateChanged; pPort->sMediaTime.eState = OMX_TIME_ClockStateStopped; pPort->sMediaTime.xScale = omx_clocksrc_component_Private->sConfigScale.xScale; } /*Signal Buffer Management Thread*/ tsem_up(omx_clocksrc_component_Private->clockEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for Clock Stop Event for all ports\n"); tsem_down(omx_clocksrc_component_Private->clockEventCompleteSem); break; default: break; } } break; case OMX_IndexConfigTimeClientStartTime: sRefTimeStamp = (OMX_TIME_CONFIG_TIMESTAMPTYPE*) pComponentConfigStructure; portIndex = sRefTimeStamp->nPortIndex; if(portIndex > omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) { return OMX_ErrorBadPortIndex; } pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[portIndex]; if(!PORT_IS_ENABLED(pPort)) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Port is disabled \n",__func__); return OMX_ErrorBadParameter; } memcpy(&pPort->sTimeStamp, sRefTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); /* update the nWaitMask to clear the flag for the client which has sent its start time */ if(omx_clocksrc_component_Private->sClockState.nWaitMask) { DEBUG(DEB_LEV_SIMPLE_SEQ,"refTime set is =%x \n",(int)pPort->sTimeStamp.nTimestamp); nMask = ~(0x1 << portIndex); omx_clocksrc_component_Private->sClockState.nWaitMask = omx_clocksrc_component_Private->sClockState.nWaitMask & nMask; if(omx_clocksrc_component_Private->sMinStartTime.nTimestamp >= pPort->sTimeStamp.nTimestamp){ omx_clocksrc_component_Private->sMinStartTime.nTimestamp = pPort->sTimeStamp.nTimestamp; omx_clocksrc_component_Private->sMinStartTime.nPortIndex = pPort->sTimeStamp.nPortIndex; } } if(!omx_clocksrc_component_Private->sClockState.nWaitMask && omx_clocksrc_component_Private->sClockState.eState == OMX_TIME_ClockStateWaitingForStartTime) { omx_clocksrc_component_Private->sClockState.eState = OMX_TIME_ClockStateRunning; omx_clocksrc_component_Private->sClockState.nStartTime = omx_clocksrc_component_Private->sMinStartTime.nTimestamp; omx_clocksrc_component_Private->MediaTimeBase = omx_clocksrc_component_Private->sMinStartTime.nTimestamp; gettimeofday(&tv,&zv); walltime = ((OMX_TICKS)tv.tv_sec)*1000000 + ((OMX_TICKS)tv.tv_usec); omx_clocksrc_component_Private->WallTimeBase = walltime; DEBUG(DEB_LEV_SIMPLE_SEQ,"Mediatimebase=%llx walltimebase=%llx \n",omx_clocksrc_component_Private->MediaTimeBase,omx_clocksrc_component_Private->WallTimeBase); omx_clocksrc_component_Private->eUpdateType = OMX_TIME_UpdateClockStateChanged; /* update the state change in all port */ for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[i]; pPort->sMediaTime.eUpdateType = OMX_TIME_UpdateClockStateChanged; pPort->sMediaTime.eState = OMX_TIME_ClockStateRunning; pPort->sMediaTime.xScale = omx_clocksrc_component_Private->sConfigScale.xScale; } /*Signal Buffer Management Thread*/ tsem_up(omx_clocksrc_component_Private->clockEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ,"setting the state to running from %s \n",__func__); DEBUG(DEB_LEV_SIMPLE_SEQ,"Waiting for Clock Running Event for all ports in case OMX_IndexConfigTimeClientStartTime\n"); tsem_down(omx_clocksrc_component_Private->clockEventCompleteSem); } break; case OMX_IndexConfigTimeActiveRefClock : pRefClock = (OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE*) pComponentConfigStructure; memcpy(&omx_clocksrc_component_Private->sRefClock, pRefClock, sizeof(OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE)); break; case OMX_IndexConfigTimeCurrentAudioReference: sRefTimeStamp = (OMX_TIME_CONFIG_TIMESTAMPTYPE*) pComponentConfigStructure; portIndex = sRefTimeStamp->nPortIndex; if(portIndex > omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) { return OMX_ErrorBadPortIndex; } pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[portIndex]; memcpy(&pPort->sTimeStamp, sRefTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); gettimeofday(&tv,&zv); walltime = ((OMX_TICKS)tv.tv_sec)*1000000 + ((OMX_TICKS)tv.tv_usec); omx_clocksrc_component_Private->WallTimeBase = walltime; omx_clocksrc_component_Private->MediaTimeBase = sRefTimeStamp->nTimestamp; /* set the mediatime base of the received time stamp*/ break; case OMX_IndexConfigTimeCurrentVideoReference: sRefTimeStamp = (OMX_TIME_CONFIG_TIMESTAMPTYPE*) pComponentConfigStructure; portIndex = sRefTimeStamp->nPortIndex; if(portIndex > omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) { return OMX_ErrorBadPortIndex; } pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[portIndex]; memcpy(&pPort->sTimeStamp, sRefTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); gettimeofday(&tv,&zv); walltime = ((OMX_TICKS)tv.tv_sec)*1000000 + ((OMX_TICKS)tv.tv_usec); omx_clocksrc_component_Private->WallTimeBase = walltime; omx_clocksrc_component_Private->MediaTimeBase = sRefTimeStamp->nTimestamp; /* set the mediatime base of the received time stamp*/ break; case OMX_IndexConfigTimeScale: /* update the mediatime base and walltime base using the current scale value*/ Scale = omx_clocksrc_component_Private->sConfigScale.xScale >> 16; //* the scale currently in use, right shifted as Q16 format is used for the scale gettimeofday(&tv,&zv); walltime = ((OMX_TICKS)tv.tv_sec)*1000000 + ((OMX_TICKS)tv.tv_usec); mediatime = omx_clocksrc_component_Private->MediaTimeBase + Scale*(walltime - omx_clocksrc_component_Private->WallTimeBase); omx_clocksrc_component_Private->WallTimeBase = walltime; // suitable start time to be used here omx_clocksrc_component_Private->MediaTimeBase = mediatime; // TODO - needs to be checked /* update the new scale value */ pConfigScale = (OMX_TIME_CONFIG_SCALETYPE*) pComponentConfigStructure; memcpy( &omx_clocksrc_component_Private->sConfigScale,pConfigScale, sizeof(OMX_TIME_CONFIG_SCALETYPE)); omx_clocksrc_component_Private->eUpdateType = OMX_TIME_UpdateScaleChanged; /* update the scale change in all ports */ for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[i]; pPort->sMediaTime.eUpdateType = OMX_TIME_UpdateScaleChanged; pPort->sMediaTime.eState = OMX_TIME_ClockStateRunning; pPort->sMediaTime.xScale = omx_clocksrc_component_Private->sConfigScale.xScale; pPort->sMediaTime.nMediaTimestamp = omx_clocksrc_component_Private->MediaTimeBase; pPort->sMediaTime.nWallTimeAtMediaTime = omx_clocksrc_component_Private->WallTimeBase; } /*Signal Buffer Management Thread*/ tsem_up(omx_clocksrc_component_Private->clockEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for Scale Change Event for all ports\n"); tsem_down(omx_clocksrc_component_Private->clockEventCompleteSem); break; case OMX_IndexConfigTimeMediaTimeRequest: Scale = omx_clocksrc_component_Private->sConfigScale.xScale >> 16; if(omx_clocksrc_component_Private->sClockState.eState != OMX_TIME_ClockStateStopped && Scale != 0) {//TODO- what happens if request comes in pause mode sMediaTimeRequest = (OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE*) pComponentConfigStructure; portIndex = sMediaTimeRequest->nPortIndex; pPort = (omx_base_clock_PortType*)omx_clocksrc_component_Private->ports[portIndex]; memcpy(&pPort->sMediaTimeRequest, sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE)); gettimeofday(&tv,&zv); walltime = ((OMX_TICKS)tv.tv_sec)*1000000 + ((OMX_TICKS)tv.tv_usec); mediatime = omx_clocksrc_component_Private->MediaTimeBase + Scale*(walltime - omx_clocksrc_component_Private->WallTimeBase); int thresh=2000; // TODO - what is a good threshold to use mediaTimediff = (sMediaTimeRequest->nMediaTimestamp - (sMediaTimeRequest->nOffset*Scale)) - mediatime; DEBUG(DEB_LEV_SIMPLE_SEQ," pI=%d MTD=%lld MT=%lld RT=%lld offset=%lld, Scale=%d\n", (int)portIndex,mediaTimediff,mediatime,sMediaTimeRequest->nMediaTimestamp,sMediaTimeRequest->nOffset,(int)Scale); if((mediaTimediff<0 && Scale>0) || (mediaTimediff>0 && Scale<0)) { /* if mediatime has already elapsed then request can not be fullfilled */ DEBUG(DEB_LEV_SIMPLE_SEQ," pI=%d RNF MTD<0 MB=%lld WB=%lld MT=%lld RT=%lld WT=%lld offset=%lld, Scale=%d\n", (int)portIndex,omx_clocksrc_component_Private->MediaTimeBase,omx_clocksrc_component_Private->WallTimeBase, mediatime,sMediaTimeRequest->nMediaTimestamp,walltime,sMediaTimeRequest->nOffset,(int)Scale); pPort->sMediaTime.eUpdateType = OMX_TIME_UpdateRequestFulfillment; // TODO : to be checked pPort->sMediaTime.nMediaTimestamp = sMediaTimeRequest->nMediaTimestamp; pPort->sMediaTime.nOffset = 0xFFFFFFFF; }else{ wallTimediff = mediaTimediff/Scale; if(mediaTimediff){ if(wallTimediff>thresh) { sleeptime = (unsigned int) (wallTimediff-thresh); usleep(sleeptime); wallTimediff = thresh; // ask : can I use this as the new walltimediff gettimeofday(&tv,&zv); walltime = ((OMX_TICKS)tv.tv_sec)*1000000 + ((OMX_TICKS)tv.tv_usec); mediatime = omx_clocksrc_component_Private->MediaTimeBase + Scale*(walltime - omx_clocksrc_component_Private->WallTimeBase); } //pPort->sMediaTime.nMediaTimestamp = mediatime; pPort->sMediaTime.nMediaTimestamp = sMediaTimeRequest->nMediaTimestamp; ///???? pPort->sMediaTime.nWallTimeAtMediaTime = walltime + wallTimediff; //?????? pPort->sMediaTime.nOffset = wallTimediff; //???? pPort->sMediaTime.xScale = Scale; pPort->sMediaTime.eUpdateType = OMX_TIME_UpdateRequestFulfillment; DEBUG(DEB_LEV_SIMPLE_SEQ,"pI=%d MB=%lld WB=%lld MT=%lld RT=%lld WT=%lld \n",(int)portIndex, omx_clocksrc_component_Private->MediaTimeBase,omx_clocksrc_component_Private->WallTimeBase, mediatime,sMediaTimeRequest->nMediaTimestamp,walltime); } } /*Signal Buffer Management Thread*/ tsem_up(omx_clocksrc_component_Private->clockEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for Scale Change Event for all ports\n"); tsem_down(omx_clocksrc_component_Private->clockEventCompleteSem); } else { DEBUG(DEB_LEV_ERR,"In %s Clock State=%x Scale=%x Line=%d \n", __func__,(int)omx_clocksrc_component_Private->sClockState.eState,(int)Scale,__LINE__); } break; default: return OMX_ErrorBadParameter; break; } return OMX_ErrorNone; }
/** This is the central function for component processing. It * is executed in a separate thread, is synchronized with * semaphores at each port, those are released each time a new buffer * is available on the given port. */ void* omx_base_source_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_source_PrivateType* omx_base_source_Private = (omx_base_source_PrivateType*)omx_base_component_Private; omx_base_PortType *pOutPort = (omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX]; tsem_t* pOutputSem = pOutPort->pBufferSem; queue_t* pOutputQueue = pOutPort->pBufferQueue; OMX_BUFFERHEADERTYPE* pOutputBuffer = NULL; OMX_COMPONENTTYPE* target_component; OMX_BOOL isOutputBufferNeeded = OMX_TRUE; int outBufExchanged = 0; omx_base_source_Private->bellagioThreads->nThreadBufferMngtID = (long int)syscall(__NR_gettid); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s the thread ID is %i\n", __func__, (int)omx_base_source_Private->bellagioThreads->nThreadBufferMngtID); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n", __func__); while(omx_base_component_Private->state == OMX_StateIdle || omx_base_component_Private->state == OMX_StateExecuting || omx_base_component_Private->state == OMX_StatePause || omx_base_component_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_source_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pOutPort)) { pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); if(isOutputBufferNeeded == OMX_FALSE) { pOutPort->ReturnBufferFunction(pOutPort, pOutputBuffer); outBufExchanged--; pOutputBuffer = NULL; isOutputBufferNeeded = OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s signalling flush all condition \n", __func__); tsem_up(omx_base_source_Private->flush_all_condition); tsem_down(omx_base_source_Private->flush_condition); pthread_mutex_lock(&omx_base_source_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); /*No buffer to process. So wait here*/ if((isOutputBufferNeeded==OMX_TRUE && pOutputSem->semval==0) && (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid)) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer \n"); tsem_down(omx_base_source_Private->bMgmtSem); } if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_FULL_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer semval=%d \n",pOutputSem->semval); if(pOutputSem->semval > 0 && isOutputBufferNeeded == OMX_TRUE ) { tsem_down(pOutputSem); if(pOutputQueue->nelem>0){ outBufExchanged++; isOutputBufferNeeded = OMX_FALSE; pOutputBuffer = dequeue(pOutputQueue); if(pOutputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "In %s Had NULL output buffer!!\n",__func__); break; } } } if(isOutputBufferNeeded == OMX_FALSE) { if((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { pOutputBuffer->nFlags = 0; } if(omx_base_source_Private->pMark.hMarkTargetComponent != NULL){ pOutputBuffer->hMarkTargetComponent = omx_base_source_Private->pMark.hMarkTargetComponent; pOutputBuffer->pMarkData = omx_base_source_Private->pMark.pMarkData; omx_base_source_Private->pMark.hMarkTargetComponent = NULL; omx_base_source_Private->pMark.pMarkData = NULL; } target_component = (OMX_COMPONENTTYPE*)pOutputBuffer->hMarkTargetComponent; if(target_component == (OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ 0, /* The state has been changed in message->messageParam2 */ pOutputBuffer->pMarkData); } else if(pOutputBuffer->hMarkTargetComponent != NULL) { /*If this is not the target component then pass the mark*/ DEBUG(DEB_LEV_FULL_SEQ, "Pass Mark. This is a Source!!\n"); } if(omx_base_source_Private->state == OMX_StateExecuting) { if (omx_base_source_Private->BufferMgmtCallback && pOutputBuffer->nFilledLen == 0) { (*(omx_base_source_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer); } else { /*It no buffer management call back then don't produce any output buffer*/ pOutputBuffer->nFilledLen = 0; } } else { DEBUG(DEB_LEV_ERR, "In %s Received Buffer in non-Executing State(%x)\n", __func__, (int)omx_base_source_Private->state); } if(omx_base_source_Private->state == OMX_StatePause && !PORT_IS_BEING_FLUSHED(pOutPort)) { /*Waiting at paused state*/ tsem_wait(omx_base_source_Private->bStateSem); } if((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Detected EOS flags in output buffer\n"); (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ 0, /* The commands was a OMX_CommandStateSet */ pOutputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ NULL); //pOutputBuffer->nFlags = 0; omx_base_source_Private->bIsEOSReached = OMX_TRUE; } /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if((pOutputBuffer->nFilledLen != 0) || ((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) ==OMX_BUFFERFLAG_EOS) || (omx_base_source_Private->bIsEOSReached == OMX_TRUE)) { if((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nFlags=%x Name=%s \n", __func__, (int)pOutputBuffer->nFlags, omx_base_source_Private->name); pOutPort->ReturnBufferFunction(pOutPort, pOutputBuffer); outBufExchanged--; pOutputBuffer = NULL; isOutputBufferNeeded = OMX_TRUE; } } } DEBUG(DEB_LEV_SIMPLE_SEQ, "Exiting Buffer Management Thread\n"); return NULL; }
/** @brief the entry point for sending buffers to the alsa sink port * * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on * the nature of the port, that can be an input or output port. */ OMX_ERRORTYPE omx_alsasink_component_port_SendBufferFunction(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) { OMX_ERRORTYPE err; OMX_U32 portIndex; OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; OMX_BOOL SendFrame; omx_base_clock_PortType* pClockPort; int errQue; #if NO_GST_OMX_PATCH unsigned int i; #endif portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex); if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); return OMX_ErrorInvalidState; } if(omx_base_component_Private->state != OMX_StateExecuting && omx_base_component_Private->state != OMX_StatePause && omx_base_component_Private->state != OMX_StateIdle) { DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); return OMX_ErrorIncorrectStateOperation; } if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); return OMX_ErrorIncorrectStateOperation; } /* Temporarily disable this check for gst-openmax */ #if NO_GST_OMX_PATCH { OMX_BOOL foundBuffer = OMX_FALSE; if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { foundBuffer = OMX_TRUE; break; } } } if (!foundBuffer) { return OMX_ErrorBadParameter; } } #endif if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); return err; } pClockPort = (omx_base_clock_PortType*)omx_base_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX]; if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(openmaxStandPort) && (omx_base_component_Private->transientState != OMX_TransStateExecutingToIdle) && ((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)){ SendFrame = omx_alsasink_component_ClockPortHandleFunction((omx_alsasink_component_PrivateType*)omx_base_component_Private, pBuffer); /* drop the frame */ if(!SendFrame) pBuffer->nFilledLen=0; } /* And notify the buffer management thread we have a fresh new buffer to manage */ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ errQue = queue(openmaxStandPort->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(openmaxStandPort->pBufferSem); DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); tsem_up(omx_base_component_Private->bMgmtSem); }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); errQue = queue(openmaxStandPort->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(openmaxStandPort->pBufferSem); } else { // If port being flushed and not tunneled then return error DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); return OMX_ErrorIncorrectStateOperation; } return OMX_ErrorNone; }
/** @brief the entry point for sending buffers to the port * * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on * the nature of the port, that can be an input or output port. */ OMX_ERRORTYPE base_clock_port_SendBufferFunction( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) { OMX_ERRORTYPE err; OMX_U32 portIndex; OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; #if NO_GST_OMX_PATCH unsigned int i; #endif portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex); if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); return OMX_ErrorInvalidState; } if(omx_base_component_Private->state != OMX_StateExecuting && omx_base_component_Private->state != OMX_StatePause && omx_base_component_Private->state != OMX_StateIdle) { DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); return OMX_ErrorIncorrectStateOperation; } if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); return OMX_ErrorIncorrectStateOperation; } /* Temporarily disable this check for gst-openmax */ #if NO_GST_OMX_PATCH { OMX_BOOL foundBuffer = OMX_FALSE; if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { foundBuffer = OMX_TRUE; break; } } } if (!foundBuffer) { return OMX_ErrorBadParameter; } } #endif if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); return err; } /*If port is not tunneled then simply return the buffer except paused state*/ if (!PORT_IS_TUNNELED(openmaxStandPort) && (omx_base_component_Private->state != OMX_StatePause)) { openmaxStandPort->ReturnBufferFunction(openmaxStandPort,pBuffer); return OMX_ErrorNone; } /* And notify the buffer management thread we have a fresh new buffer to manage */ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ queue(openmaxStandPort->pBufferQueue, pBuffer); tsem_up(openmaxStandPort->pBufferSem); DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); tsem_up(omx_base_component_Private->bMgmtSem); }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); queue(openmaxStandPort->pBufferQueue, pBuffer); tsem_up(openmaxStandPort->pBufferSem); } else { // If port being flushed and not tunneled then return error DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); return OMX_ErrorIncorrectStateOperation; } return OMX_ErrorNone; }
/** This is the central function for component processing. It * is executed in a separate thread, is synchronized with * semaphores at each port, those are released each time a new buffer * is available on the given port. */ void* omx_base_filter_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_filter_PrivateType* omx_base_filter_Private = (omx_base_filter_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_PortType *pInPort=(omx_base_PortType *)omx_base_filter_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; omx_base_PortType *pOutPort=(omx_base_PortType *)omx_base_filter_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; tsem_t* pInputSem = pInPort->pBufferSem; tsem_t* pOutputSem = pOutPort->pBufferSem; queue_t* pInputQueue = pInPort->pBufferQueue; queue_t* pOutputQueue = pOutPort->pBufferQueue; OMX_BUFFERHEADERTYPE* pOutputBuffer=NULL; OMX_BUFFERHEADERTYPE* pInputBuffer=NULL; OMX_BOOL isInputBufferNeeded=OMX_TRUE,isOutputBufferNeeded=OMX_TRUE; int inBufExchanged=0,outBufExchanged=0; omx_base_filter_Private->bellagioThreads->nThreadBufferMngtID = (long int)syscall(__NR_gettid); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s of component %p\n", __func__, openmaxStandComp); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s the thread ID is %i\n", __func__, (int)omx_base_filter_Private->bellagioThreads->nThreadBufferMngtID); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); /* checks if the component is in a state able to receive buffers */ while(omx_base_filter_Private->state == OMX_StateIdle || omx_base_filter_Private->state == OMX_StateExecuting || omx_base_filter_Private->state == OMX_StatePause || omx_base_filter_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_filter_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort)) { pthread_mutex_unlock(&omx_base_filter_Private->flush_mutex); DEBUG(DEB_LEV_FULL_SEQ, "In %s 1 signaling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,inBufExchanged,isInputBufferNeeded,outBufExchanged,isOutputBufferNeeded,pInputSem->semval,pOutputSem->semval); if(isOutputBufferNeeded==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort)) { pOutPort->ReturnBufferFunction(pOutPort,pOutputBuffer); outBufExchanged--; pOutputBuffer=NULL; isOutputBufferNeeded=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer\n"); } if(isInputBufferNeeded==OMX_FALSE && PORT_IS_BEING_FLUSHED(pInPort)) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning input buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s 2 signaling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,inBufExchanged,isInputBufferNeeded,outBufExchanged,isOutputBufferNeeded,pInputSem->semval,pOutputSem->semval); tsem_up(omx_base_filter_Private->flush_all_condition); tsem_down(omx_base_filter_Private->flush_condition); pthread_mutex_lock(&omx_base_filter_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_filter_Private->flush_mutex); /*No buffer to process. So wait here*/ if((isInputBufferNeeded==OMX_TRUE && pInputSem->semval==0) && (omx_base_filter_Private->state != OMX_StateLoaded && omx_base_filter_Private->state != OMX_StateInvalid)) { //Signaled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next input/output buffer\n"); tsem_down(omx_base_filter_Private->bMgmtSem); } if(omx_base_filter_Private->state == OMX_StateLoaded || omx_base_filter_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } if((isOutputBufferNeeded==OMX_TRUE && pOutputSem->semval==0) && (omx_base_filter_Private->state != OMX_StateLoaded && omx_base_filter_Private->state != OMX_StateInvalid) && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { //Signaled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next input/output buffer\n"); tsem_down(omx_base_filter_Private->bMgmtSem); } if(omx_base_filter_Private->state == OMX_StateLoaded || omx_base_filter_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_FULL_SEQ, "Waiting for input buffer semval=%d in %s\n",pInputSem->semval, __func__); if(pInputSem->semval>0 && isInputBufferNeeded==OMX_TRUE ) { tsem_down(pInputSem); if(pInputQueue->nelem>0){ inBufExchanged++; isInputBufferNeeded=OMX_FALSE; pInputBuffer = dequeue(pInputQueue); if(pInputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL input buffer!!\n"); break; } } } /*When we have input buffer to process then get one output buffer*/ if(pOutputSem->semval>0 && isOutputBufferNeeded==OMX_TRUE) { tsem_down(pOutputSem); if(pOutputQueue->nelem>0){ outBufExchanged++; isOutputBufferNeeded=OMX_FALSE; pOutputBuffer = dequeue(pOutputQueue); if(pOutputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!! op is=%d,iq=%d\n",pOutputSem->semval,pOutputQueue->nelem); break; } } } if(isInputBufferNeeded==OMX_FALSE) { if(pInputBuffer->hMarkTargetComponent != NULL){ if((OMX_COMPONENTTYPE*)pInputBuffer->hMarkTargetComponent ==(OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_filter_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_filter_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ 0, /* The state has been changed in message->messageParam2 */ pInputBuffer->pMarkData); } else { /*If this is not the target component then pass the mark*/ omx_base_filter_Private->pMark.hMarkTargetComponent = pInputBuffer->hMarkTargetComponent; omx_base_filter_Private->pMark.pMarkData = pInputBuffer->pMarkData; } pInputBuffer->hMarkTargetComponent = NULL; } } if(isInputBufferNeeded==OMX_FALSE && isOutputBufferNeeded==OMX_FALSE) { if(omx_base_filter_Private->pMark.hMarkTargetComponent != NULL){ pOutputBuffer->hMarkTargetComponent = omx_base_filter_Private->pMark.hMarkTargetComponent; pOutputBuffer->pMarkData = omx_base_filter_Private->pMark.pMarkData; omx_base_filter_Private->pMark.hMarkTargetComponent = NULL; omx_base_filter_Private->pMark.pMarkData = NULL; } pOutputBuffer->nTimeStamp = pInputBuffer->nTimeStamp; if((pInputBuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) { DEBUG(DEB_LEV_FULL_SEQ, "Detected START TIME flag in the input buffer filled len=%d\n", (int)pInputBuffer->nFilledLen); pOutputBuffer->nFlags = pInputBuffer->nFlags; pInputBuffer->nFlags = 0; } if(omx_base_filter_Private->state == OMX_StateExecuting) { if (omx_base_filter_Private->BufferMgmtCallback && pInputBuffer->nFilledLen > 0) { (*(omx_base_filter_Private->BufferMgmtCallback))(openmaxStandComp, pInputBuffer, pOutputBuffer); } else { /*It no buffer management call back the explicitly consume input buffer*/ pInputBuffer->nFilledLen = 0; } } else if(!(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { DEBUG(DEB_LEV_ERR, "In %s Received Buffer in non-Executing State(%x)\n", __func__, (int)omx_base_filter_Private->state); } else { pInputBuffer->nFilledLen = 0; } if((pInputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS && pInputBuffer->nFilledLen==0) { DEBUG(DEB_LEV_FULL_SEQ, "Detected EOS flags in input buffer filled len=%d\n", (int)pInputBuffer->nFilledLen); pOutputBuffer->nFlags=pInputBuffer->nFlags; pInputBuffer->nFlags=0; (*(omx_base_filter_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_filter_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ pOutputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ NULL); omx_base_filter_Private->bIsEOSReached = OMX_TRUE; } if(omx_base_filter_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { /*Waiting at paused state*/ tsem_wait(omx_base_filter_Private->bStateSem); } /*If EOS and Input buffer Filled Len Zero then Return output buffer immediately*/ if((pOutputBuffer->nFilledLen != 0) || ((pOutputBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) || (omx_base_filter_Private->bIsEOSReached == OMX_TRUE)) { pOutPort->ReturnBufferFunction(pOutPort,pOutputBuffer); outBufExchanged--; pOutputBuffer=NULL; isOutputBufferNeeded=OMX_TRUE; } } if(omx_base_filter_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pInPort) || PORT_IS_BEING_FLUSHED(pOutPort))) { /*Waiting at paused state*/ tsem_wait(omx_base_filter_Private->bStateSem); } /*Input Buffer has been completely consumed. So, return input buffer*/ if((isInputBufferNeeded == OMX_FALSE) && (pInputBuffer->nFilledLen==0)) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded=OMX_TRUE; } } DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s of component %p\n", __func__, openmaxStandComp); return NULL; }
OMX_ERRORTYPE videosrc_port_AllocateBuffer( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE** pBuffer, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, OMX_U32 nSizeBytes) { int i; OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; omx_videosrc_component_PrivateType* omx_videosrc_component_Private = (omx_videosrc_component_PrivateType*)omx_base_component_Private; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { return OMX_ErrorBadPortIndex; } if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { return OMX_ErrorBadPortIndex; } if (omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) { if (!openmaxStandPort->bIsTransientToEnabled) { DEBUG(DEB_LEV_ERR, "In %s: The port is not allowed to receive buffers\n", __func__); return OMX_ErrorIncorrectStateTransition; } } if(nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) { DEBUG(DEB_LEV_ERR, "In %s: Requested Buffer Size %lu is less than Minimum Buffer Size %lu\n", __func__, nSizeBytes, openmaxStandPort->sPortParam.nBufferSize); return OMX_ErrorIncorrectStateTransition; } for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { openmaxStandPort->pInternalBufferStorage[i] = calloc(1,sizeof(OMX_BUFFERHEADERTYPE)); if (!openmaxStandPort->pInternalBufferStorage[i]) { return OMX_ErrorInsufficientResources; } setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)); /* Map the buffer with the device's memory area*/ if(i > n_buffers) { DEBUG(DEB_LEV_ERR, "In %s returning error i=%d, nframe=%d\n", __func__,i,n_buffers); return OMX_ErrorInsufficientResources; } omx_videosrc_component_Private->bOutBufferMemoryMapped = OMX_TRUE; openmaxStandPort->pInternalBufferStorage[i]->pBuffer = omx_videosrc_component_Private->buffers[i].start; openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = (int)nSizeBytes; openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort; openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate; *pBuffer = openmaxStandPort->pInternalBufferStorage[i]; openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED; openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED; if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; } else { openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; } openmaxStandPort->nNumAssignedBuffers++; DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nPortIndex=%d\n",__func__,(int)nPortIndex); tsem_up(openmaxStandPort->pAllocSem); } return OMX_ErrorNone; } } DEBUG(DEB_LEV_ERR, "In %s Error: no available buffers\n",__func__); return OMX_ErrorInsufficientResources; }
OMX_ERRORTYPE videosrc_port_FreeBuffer( omx_base_PortType *openmaxStandPort, OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE* pBuffer) { int i; OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; omx_videosrc_component_PrivateType* omx_videosrc_component_Private = (omx_videosrc_component_PrivateType*)omx_base_component_Private; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { return OMX_ErrorBadPortIndex; } if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { return OMX_ErrorBadPortIndex; } if (omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) { if (!openmaxStandPort->bIsTransientToDisabled) { DEBUG(DEB_LEV_FULL_SEQ, "In %s: The port is not allowed to free the buffers\n", __func__); (*(omx_base_component_Private->callbacks->EventHandler)) (omxComponent, omx_base_component_Private->callbackData, OMX_EventError, /* The command was completed */ OMX_ErrorPortUnpopulated, /* The commands was a OMX_CommandStateSet */ nPortIndex, /* The state has been changed in message->messageParam2 */ NULL); } } for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ if (openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) { openmaxStandPort->bIsFullOfBuffers = OMX_FALSE; if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) { if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer){ DEBUG(DEB_LEV_PARAMS, "In %s freeing %i pBuffer=%x\n",__func__, (int)i, (int)openmaxStandPort->pInternalBufferStorage[i]->pBuffer); openmaxStandPort->pInternalBufferStorage[i]->pBuffer=NULL; omx_videosrc_component_Private->bOutBufferMemoryMapped = OMX_FALSE; } } else if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ASSIGNED) { free(pBuffer); pBuffer=NULL; } if(openmaxStandPort->bBufferStateAllocated[i] & HEADER_ALLOCATED) { free(openmaxStandPort->pInternalBufferStorage[i]); openmaxStandPort->pInternalBufferStorage[i]=NULL; } openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE; openmaxStandPort->nNumAssignedBuffers--; DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); if (openmaxStandPort->nNumAssignedBuffers == 0) { openmaxStandPort->sPortParam.bPopulated = OMX_FALSE; openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE; tsem_up(openmaxStandPort->pAllocSem); } return OMX_ErrorNone; } } return OMX_ErrorInsufficientResources; }
/** @brief Called by the standard use buffer, it implements a base functionality. * * This function can be overriden if the use buffer implicate more complicated operations. * The parameters are the same as the standard function, except for the handle of the port * instead of the handler of the component. * When the buffers needed by this port are all assigned or allocated, the variable * bIsFullOfBuffers becomes equal to OMX_TRUE */ OMX_ERRORTYPE camera_video_port_UseBuffer( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE **ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, OMX_U32 nSizeBytes, OMX_U8 *pBuffer) { unsigned int i; OMX_BUFFERHEADERTYPE *returnBufferHeader; omx_base_camera_video_PortType *pBasePort = (omx_base_camera_video_PortType *)openmaxStandPort; OMX_COMPONENTTYPE *omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType *omx_base_component_Private = (omx_base_component_PrivateType *)omxComponent->pComponentPrivate; omx_base_camera_video_PortType *omx_base_video_Port = (omx_base_camera_video_PortType *)openmaxStandPort; OMXDBUG(OMXDBUG_VERB, "In %s for port %p\n", __func__, openmaxStandPort); if(nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { return OMX_ErrorBadPortIndex; } if(PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) { if(!openmaxStandPort->bIsTransientToEnabled) { OMXDBUG(OMXDBUG_ERR, "In %s: The port of Comp %s is not allowed to receive buffers\n", __func__, omx_base_component_Private->name); return OMX_ErrorIncorrectStateTransition; } } if(pBasePort->bStoreMediadata == OMX_FALSE && nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) { OMXDBUG(OMXDBUG_ERR, "In %s: Port %d Given Buffer Size %u is less than Minimum Buffer Size %u\n", __func__, (int)nPortIndex, (int)nSizeBytes, (int)openmaxStandPort->sPortParam.nBufferSize); return OMX_ErrorIncorrectStateTransition; } if(omx_base_video_Port->pBufferHeadAct == NULL) { omx_base_video_Port->pBufferHeadAct = calloc(openmaxStandPort->sPortParam.nBufferCountActual, sizeof(OMX_BUFFERHEADERTYPE_ACTEXT)); if(omx_base_video_Port->pBufferHeadAct == NULL) { return OMX_ErrorInsufficientResources; } } for(i = 0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++) { if(openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { openmaxStandPort->pInternalBufferStorage[i] = calloc(1, sizeof(OMX_BUFFERHEADERTYPE)); if(!openmaxStandPort->pInternalBufferStorage[i]) { return OMX_ErrorInsufficientResources; } openmaxStandPort->bIsEmptyOfBuffers = OMX_FALSE; setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)); openmaxStandPort->pInternalBufferStorage[i]->pBuffer = pBuffer; openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = nSizeBytes; openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort; openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate; openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ASSIGNED; openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED; returnBufferHeader = calloc(1, sizeof(OMX_BUFFERHEADERTYPE)); if(!returnBufferHeader) { return OMX_ErrorInsufficientResources; } omx_base_video_Port->pBufferHeadAct[i].pBuffHead = returnBufferHeader; setHeader(returnBufferHeader, sizeof(OMX_BUFFERHEADERTYPE)); returnBufferHeader->pBuffer = pBuffer; returnBufferHeader->nAllocLen = nSizeBytes; returnBufferHeader->pPlatformPrivate = openmaxStandPort; returnBufferHeader->pAppPrivate = pAppPrivate; if(openmaxStandPort->sPortParam.eDir == OMX_DirInput) { openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; returnBufferHeader->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; } else { openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; returnBufferHeader->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; } *ppBufferHdr = (OMX_BUFFERHEADERTYPE *)returnBufferHeader; openmaxStandPort->nNumAssignedBuffers++; OMXDBUG(OMXDBUG_VERB, "openmaxStandPort->nNumAssignedBuffers %d,%d\n", (unsigned int)openmaxStandPort->sPortParam.nBufferCountActual, (unsigned int)openmaxStandPort->nNumAssignedBuffers); if(openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; tsem_up(openmaxStandPort->pAllocSem); } OMXDBUG(OMXDBUG_VERB, "Out of %s for port %p\n", __func__, openmaxStandPort); return OMX_ErrorNone; } } OMXDBUG(OMXDBUG_ERR, "In %s Error: no available buffers CompName=%s\n", __func__, omx_base_component_Private->name); return OMX_ErrorInsufficientResources; }
void* omx_base_source_twoport_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_source_PrivateType* omx_base_source_Private = (omx_base_source_PrivateType*)omx_base_component_Private; omx_base_PortType *pOutPort[2]; tsem_t* pOutputSem[2]; queue_t* pOutputQueue[2]; OMX_BUFFERHEADERTYPE* pOutputBuffer[2]; OMX_COMPONENTTYPE* target_component; OMX_BOOL isOutputBufferNeeded[2]; int i,outBufExchanged[2]; pOutPort[0]=(omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX]; pOutPort[1]=(omx_base_PortType *)omx_base_source_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX_1]; pOutputSem[0] = pOutPort[0]->pBufferSem; pOutputSem[1] = pOutPort[1]->pBufferSem; pOutputQueue[0] = pOutPort[0]->pBufferQueue; pOutputQueue[1] = pOutPort[1]->pBufferQueue; pOutputBuffer[1]= pOutputBuffer[0]=NULL; isOutputBufferNeeded[0]=isOutputBufferNeeded[1]=OMX_TRUE; outBufExchanged[0]=outBufExchanged[1]=0; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); while(omx_base_source_Private->state == OMX_StateIdle || omx_base_source_Private->state == OMX_StateExecuting || omx_base_source_Private->state == OMX_StatePause || omx_base_source_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_source_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1])) { pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); DEBUG(DEB_LEV_FULL_SEQ, "In %s 1 signalling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,outBufExchanged[0],isOutputBufferNeeded[0],outBufExchanged[1],isOutputBufferNeeded[1],pOutputSem[0]->semval,pOutputSem[1]->semval); if(isOutputBufferNeeded[1]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[1])) { pOutPort[1]->ReturnBufferFunction(pOutPort[1],pOutputBuffer[1]); outBufExchanged[1]--; pOutputBuffer[1]=NULL; isOutputBufferNeeded[1]=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output 1 buffer\n"); } if(isOutputBufferNeeded[0]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[0])) { pOutPort[0]->ReturnBufferFunction(pOutPort[0],pOutputBuffer[0]); outBufExchanged[0]--; pOutputBuffer[0]=NULL; isOutputBufferNeeded[0]=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output 0 buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s 2 signalling flush all cond iE=%d,iF=%d,oE=%d,oF=%d iSemVal=%d,oSemval=%d\n", __func__,outBufExchanged[0],isOutputBufferNeeded[0],outBufExchanged[1],isOutputBufferNeeded[1],pOutputSem[0]->semval,pOutputSem[1]->semval); tsem_up(omx_base_source_Private->flush_all_condition); tsem_down(omx_base_source_Private->flush_condition); pthread_mutex_lock(&omx_base_source_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_source_Private->flush_mutex); /*No buffer to process. So wait here*/ if((isOutputBufferNeeded[0]==OMX_TRUE && pOutputSem[0]->semval==0) && (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid)) { //Signalled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer 0\n"); tsem_down(omx_base_source_Private->bMgmtSem); } if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } if((isOutputBufferNeeded[1]==OMX_TRUE && pOutputSem[1]->semval==0) && (omx_base_source_Private->state != OMX_StateLoaded && omx_base_source_Private->state != OMX_StateInvalid) && !(PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1]))) { //Signalled from EmptyThisBuffer or FillThisBuffer or some thing else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer 1\n"); tsem_down(omx_base_source_Private->bMgmtSem); } if(omx_base_source_Private->state == OMX_StateLoaded || omx_base_source_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for output buffer 0 semval=%d \n",pOutputSem[0]->semval); if(pOutputSem[0]->semval>0 && isOutputBufferNeeded[0]==OMX_TRUE ) { tsem_down(pOutputSem[0]); if(pOutputQueue[0]->nelem>0){ outBufExchanged[0]++; isOutputBufferNeeded[0]=OMX_FALSE; pOutputBuffer[0] = dequeue(pOutputQueue[0]); if(pOutputBuffer[0] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!!\n"); break; } } } /*When we have input buffer to process then get one output buffer*/ if(pOutputSem[1]->semval>0 && isOutputBufferNeeded[1]==OMX_TRUE) { tsem_down(pOutputSem[1]); if(pOutputQueue[1]->nelem>0){ outBufExchanged[1]++; isOutputBufferNeeded[1]=OMX_FALSE; pOutputBuffer[1] = dequeue(pOutputQueue[1]); if(pOutputBuffer[1] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!! op is=%d,iq=%d\n",pOutputSem[1]->semval,pOutputQueue[1]->nelem); break; } } } for(i=0;i < (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts -1);i++) { if(omx_base_source_Private->ports[i]->sPortParam.eDomain!=OMX_PortDomainOther){ /* clock ports are not to be processed */ /*Process Output buffer of Port i */ if(isOutputBufferNeeded[i]==OMX_FALSE) { /*Pass the Mark to all outgoing buffers*/ if(omx_base_source_Private->pMark.hMarkTargetComponent != NULL){ pOutputBuffer[i]->hMarkTargetComponent = omx_base_source_Private->pMark.hMarkTargetComponent; pOutputBuffer[i]->pMarkData = omx_base_source_Private->pMark.pMarkData; } target_component=(OMX_COMPONENTTYPE*)pOutputBuffer[i]->hMarkTargetComponent; if(target_component==(OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_source_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_source_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ i, /* The state has been changed in message->messageParam2 */ pOutputBuffer[i]->pMarkData); } else if(pOutputBuffer[i]->hMarkTargetComponent!=NULL){ /*If this is not the target component then pass the mark*/ DEBUG(DEB_LEV_FULL_SEQ, "Pass Mark. This is a Source!!\n"); } if(omx_base_source_Private->state == OMX_StateExecuting) { if (omx_base_source_Private->BufferMgmtCallback && pOutputBuffer[i]->nFilledLen == 0) { (*(omx_base_source_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer[i]); } else { /*If no buffer management call back then don't produce any output buffer*/ pOutputBuffer[i]->nFilledLen = 0; } } else { DEBUG(DEB_LEV_ERR, "In %s Received Buffer in non-Executing State(%x)\n", __func__, (int)omx_base_source_Private->state); } if((pOutputBuffer[i]->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS && pOutputBuffer[i]->nFilledLen==0) { DEBUG(DEB_LEV_FULL_SEQ, "Detected EOS flags in input buffer filled len=%d\n", (int)pOutputBuffer[i]->nFilledLen); (*(omx_base_source_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_source_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ i, /* The commands was a OMX_CommandStateSet */ pOutputBuffer[i]->nFlags, /* The state has been changed in message->messageParam2 */ NULL); } if(omx_base_source_Private->state==OMX_StatePause && !(PORT_IS_BEING_FLUSHED(pOutPort[0]) || PORT_IS_BEING_FLUSHED(pOutPort[1]))) { /*Waiting at paused state*/ tsem_wait(omx_base_component_Private->bStateSem); } /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if(pOutputBuffer[i]->nFilledLen!=0 || (pOutputBuffer[i]->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS){ pOutPort[i]->ReturnBufferFunction(pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[i]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; } } } } /*Clear the Mark*/ if(omx_base_source_Private->pMark.hMarkTargetComponent != NULL){ omx_base_source_Private->pMark.hMarkTargetComponent = NULL; omx_base_source_Private->pMark.pMarkData = NULL; } } DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); return NULL; }
/** It initializates the FFmpeg framework, and opens an FFmpeg videoencoder of type specified by IL client */ OMX_ERRORTYPE omx_videoenc_component_ffmpegLibInit(omx_videoenc_component_PrivateType* omx_videoenc_component_Private) { omx_base_video_PortType *inPort = (omx_base_video_PortType *)omx_videoenc_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; OMX_U32 target_coencID; avcodec_init(); av_register_all(); DEBUG(DEB_LEV_SIMPLE_SEQ, "FFmpeg library/encoder initialized\n"); switch(omx_videoenc_component_Private->video_encoding_type) { case OMX_VIDEO_CodingMPEG4 : target_coencID = CODEC_ID_MPEG4; break; default : DEBUG(DEB_LEV_ERR, "\n encoders other than MPEG-4 are not supported -- encoder not found\n"); return OMX_ErrorComponentNotFound; } /** Find the encoder corresponding to the video type specified by IL client*/ omx_videoenc_component_Private->avCodec = avcodec_find_encoder(target_coencID); if (omx_videoenc_component_Private->avCodec == NULL) { DEBUG(DEB_LEV_ERR, "Encoder Not found\n"); return OMX_ErrorInsufficientResources; } omx_videoenc_component_Private->avCodecContext = avcodec_alloc_context(); omx_videoenc_component_Private->picture = avcodec_alloc_frame (); /* put sample parameters */ omx_videoenc_component_Private->avCodecContext->bit_rate = 200000; /* bit per second */ omx_videoenc_component_Private->avCodecContext->bit_rate_tolerance = 4000000; /* bit per second */ omx_videoenc_component_Private->avCodecContext->width = inPort->sPortParam.format.video.nFrameWidth; omx_videoenc_component_Private->avCodecContext->height = inPort->sPortParam.format.video.nFrameHeight; /* frames per second */ DEBUG(DEB_LEV_SIMPLE_SEQ, "Frame Rate=%d\n",(int)inPort->sPortParam.format.video.xFramerate); omx_videoenc_component_Private->avCodecContext->time_base= (AVRational){1,inPort->sPortParam.format.video.xFramerate}; omx_videoenc_component_Private->avCodecContext->gop_size = omx_videoenc_component_Private->pVideoMpeg4.nPFrames + 1; /* emit one intra frame every twelve frames */ omx_videoenc_component_Private->avCodecContext->pix_fmt = PIX_FMT_YUV420P; omx_videoenc_component_Private->avCodecContext->strict_std_compliance = FF_COMPLIANCE_NORMAL; omx_videoenc_component_Private->avCodecContext->sample_fmt = SAMPLE_FMT_S16; omx_videoenc_component_Private->avCodecContext->qmin = 2; omx_videoenc_component_Private->avCodecContext->qmax = 31; omx_videoenc_component_Private->avCodecContext->workaround_bugs |= FF_BUG_AUTODETECT; if(omx_videoenc_component_Private->pVideoMpeg4.eProfile == OMX_VIDEO_MPEG4ProfileAdvancedScalable) { omx_videoenc_component_Private->avCodecContext->max_b_frames = omx_videoenc_component_Private->pVideoMpeg4.nBFrames; } if(omx_videoenc_component_Private->pVideoMpeg4.bACPred == OMX_TRUE) { omx_videoenc_component_Private->avCodecContext->flags != CODEC_FLAG_AC_PRED; } #if 0 /*Add checking with bit rate and M4V levels*/ switch(omx_videoenc_component_Private->pVideoMpeg4.eLevel) { case OMX_VIDEO_MPEG4Level0: /**< Level 0 */ case OMX_VIDEO_MPEG4Level0b: /**< Level 0b */ case OMX_VIDEO_MPEG4Level1: /**< Level 1 */ case OMX_VIDEO_MPEG4Level2: /**< Level 2 */ case OMX_VIDEO_MPEG4Level3: /**< Level 3 */ case OMX_VIDEO_MPEG4Level4: /**< Level 4 */ case OMX_VIDEO_MPEG4Level4a: /**< Level 4a */ case OMX_VIDEO_MPEG4Level5: /**< Level 5 */ case default: break; } #endif if (avcodec_open(omx_videoenc_component_Private->avCodecContext, omx_videoenc_component_Private->avCodec) < 0) { DEBUG(DEB_LEV_ERR, "Could not open encoder\n"); return OMX_ErrorInsufficientResources; } tsem_up(omx_videoenc_component_Private->avCodecSyncSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "done\n"); return OMX_ErrorNone; }
/** * Returns Input/Output Buffer to the IL client or Tunneled Component */ OMX_ERRORTYPE videoenc_port_ReturnBufferFunction( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE *pBuffer) { int errQue; OMX_ERRORTYPE eError = OMX_ErrorNone; omx_base_component_PrivateType *omx_base_component_Private = openmaxStandPort->standCompContainer->pComponentPrivate; omx_videoenc_PortType *omx_videoenc_Port = (omx_videoenc_PortType *)openmaxStandPort; queue_t *pQueue = omx_videoenc_Port->pBufferQueue; tsem_t *pSem = omx_videoenc_Port->pBufferSem; OMX_VCE_Buffers_List *pBuffersMng_List= &(omx_videoenc_Port->BuffersMng_List); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s for port %p\n", __func__, omx_videoenc_Port); OMX_BUFFERHEADERTYPE *pBuffer_ACTEXT = (OMX_BUFFERHEADERTYPE *)pBuffer; if( omx_videoenc_Port->sPortParam.eDir == OMX_DirOutput ) { eError = ReturnBuffer_BuffersMng(pBuffersMng_List, pBuffer_ACTEXT, omx_videoenc_Port->bIsStoreMediaData); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!ReturnBuffer_BuffersMng fail!%s,%d\n",__FILE__,__LINE__); return eError; } } #ifdef enable_gralloc if(pBuffer->nFilledLen == 0 && ((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) ) { DEBUG(DEB_LEV_ERR, "ReturnBufferFunction,input buffer is eos now!"); } else { eError = UnLock_VirAddr_BuffersMng(pBuffersMng_List, pBuffer_ACTEXT, omx_videoenc_Port->bIsStoreMediaData); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!UnLock_VirAddr_BuffersMng fail!%s,%d\n", __FILE__, __LINE__); return eError; } } #endif if (PORT_IS_TUNNELED(omx_videoenc_Port) && ! PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port)) { if (omx_videoenc_Port->sPortParam.eDir == OMX_DirInput) { pBuffer->nOutputPortIndex = omx_videoenc_Port->nTunneledPort; pBuffer->nInputPortIndex = omx_videoenc_Port->sPortParam.nPortIndex; eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->FillThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s eError %08x in FillThis Buffer from Component %s Non-Supplier\n", __func__, eError,omx_base_component_Private->name); } } else { pBuffer->nInputPortIndex = omx_videoenc_Port->nTunneledPort; pBuffer->nOutputPortIndex = omx_videoenc_Port->sPortParam.nPortIndex; eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->EmptyThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s eError %08x in EmptyThis Buffer from Component %s Non-Supplier\n", __func__, eError, omx_base_component_Private->name); } } } else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port) && !PORT_IS_BEING_FLUSHED(omx_videoenc_Port)) { if (omx_videoenc_Port->sPortParam.eDir == OMX_DirInput) { eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->FillThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in FillThis Buffer from Component %s Supplier\n", __func__, eError,omx_base_component_Private->name); /*If Error Occured then queue the buffer*/ errQue = queue(pQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(pSem); } } else { eError = ((OMX_COMPONENTTYPE *)(omx_videoenc_Port->hTunneledComponent))->EmptyThisBuffer(omx_videoenc_Port->hTunneledComponent, pBuffer); if(eError != OMX_ErrorNone) { DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in EmptyThis Buffer from Component %s Supplier\n", __func__, eError,omx_base_component_Private->name); /*If Error Occured then queue the buffer*/ errQue = queue(pQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(pSem); } } } else if (!PORT_IS_TUNNELED(omx_videoenc_Port)) { //here (*(omx_videoenc_Port->BufferProcessedCallback))( omx_videoenc_Port->standCompContainer, omx_base_component_Private->callbackData, pBuffer); } else { errQue = queue(pQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } omx_videoenc_Port->nNumBufferFlushed++; } DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s for port %p\n", __func__, omx_videoenc_Port); return OMX_ErrorNone; }
/** @brief the entry point for sending buffers to the port * * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on * the nature of the port, that can be an input or output port. */ OMX_ERRORTYPE videoenc_port_SendBufferFunction( omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE *pBuffer) { int errQue; OMX_U32 portIndex; OMX_ERRORTYPE err = OMX_ErrorNone; OMX_COMPONENTTYPE *omxComponent = openmaxStandPort->standCompContainer; omx_videoenc_PortType *omx_videoenc_Port = (omx_videoenc_PortType *)openmaxStandPort; omx_base_component_PrivateType *omx_base_component_Private = (omx_base_component_PrivateType *)omxComponent->pComponentPrivate; OMX_VCE_Buffers_List *pBuffersMng_List= &(omx_videoenc_Port->BuffersMng_List); DEBUG(DEB_LEV_FUNCTION_NAME, "In %s for port %p\n", __func__, omx_videoenc_Port); #if NO_GST_OMX_PATCH unsigned int i; #endif portIndex = (omx_videoenc_Port->sPortParam.eDir == OMX_DirInput) ? pBuffer->nInputPortIndex : pBuffer->nOutputPortIndex; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %d\n", __func__, portIndex); if (portIndex != omx_videoenc_Port->sPortParam.nPortIndex) { DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)omx_videoenc_Port->sPortParam.nPortIndex); return OMX_ErrorBadPortIndex; } if(omx_base_component_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); return OMX_ErrorInvalidState; } if(omx_base_component_Private->state != OMX_StateExecuting && omx_base_component_Private->state != OMX_StatePause && omx_base_component_Private->state != OMX_StateIdle) { DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); return OMX_ErrorIncorrectStateOperation; } if (!PORT_IS_ENABLED(omx_videoenc_Port) || (PORT_IS_BEING_DISABLED(omx_videoenc_Port) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port)) || ((omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle || omx_base_component_Private->transientState == OMX_TransStatePauseToIdle) && (PORT_IS_TUNNELED(omx_videoenc_Port) && !PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port)))) { DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex, omx_base_component_Private->name); return OMX_ErrorIncorrectStateOperation; } /* Temporarily disable this check for gst-openmax */ #if NO_GST_OMX_PATCH { OMX_BOOL foundBuffer = OMX_FALSE; if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { for(i=0; i < omx_videoenc_Port->sPortParam.nBufferCountActual; i++) { if (pBuffer->pBuffer == omx_videoenc_Port->pInternalBufferStorage[i]->pBuffer) { foundBuffer = OMX_TRUE; break; } } } if (!foundBuffer) { return OMX_ErrorBadParameter; } } #endif if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); return err; } /* And notify the buffer management thread we have a fresh new buffer to manage */ if(!PORT_IS_BEING_FLUSHED(omx_videoenc_Port) && \ !(PORT_IS_BEING_DISABLED(omx_videoenc_Port) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port))) { //here if(omx_videoenc_Port->bIsStoreMediaData == OMX_TRUE) { if((*(OMX_U32 *)pBuffer->pBuffer != kMetadataBufferTypeCameraSource_act) && \ (*(OMX_U32 *)pBuffer->pBuffer != kMetadataBufferTypeGrallocSource_act)) { DEBUG(DEB_LEV_ERR, "Warning!in StoreMediaData mode,but the buffer (%x) is not kMetadataBufferTypeCameraSource_act!\n", (int)*(OMX_U32 *)pBuffer->pBuffer); } } if(omx_videoenc_Port->ringbuffer == OMX_TRUE && omx_videoenc_Port->sPortParam.nPortIndex == OMX_BASE_FILTER_OUTPUTPORT_INDEX) { err = Free_UseRingBuffer_BuffersMng(&omx_videoenc_Port->BuffersMng_List,omx_videoenc_Port->bufferpool,pBuffer, omx_videoenc_Port->sPortParam.nBufferSize); if( err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!In %s: SendBuffer_BuffersMng\n", __func__); return err; } } else { err = SendBuffer_BuffersMng(pBuffersMng_List,pBuffer,omx_videoenc_Port->bIsStoreMediaData,omx_videoenc_Port->sPortParam.eDir); if( err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "err!In %s: SendBuffer_BuffersMng\n", __func__); return err; } } errQue = queue(omx_videoenc_Port->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(omx_videoenc_Port->pBufferSem); DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n", __func__, (int)portIndex); tsem_up(omx_base_component_Private->bMgmtSem); } else if(PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port)) { DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", __func__, omx_base_component_Private->name, (int)omx_videoenc_Port->sPortParam.nPortIndex); errQue = queue(omx_videoenc_Port->pBufferQueue, pBuffer); if (errQue) { /* /TODO the queue is full. This can be handled in a fine way with * some retrials, or other checking. For the moment this is a critical error * and simply causes the failure of this call */ return OMX_ErrorInsufficientResources; } tsem_up(omx_videoenc_Port->pBufferSem); } else { // If port being flushed and not tunneled then return error DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); return OMX_ErrorIncorrectStateOperation; } DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s for port %p\n", __func__, omx_videoenc_Port); return OMX_ErrorNone; }
void* omx_clocksrc_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_clocksrc_component_PrivateType* omx_clocksrc_component_Private = (omx_clocksrc_component_PrivateType*)omx_base_component_Private; omx_base_clock_PortType *pOutPort[MAX_CLOCK_PORTS]; tsem_t* pOutputSem[MAX_CLOCK_PORTS]; queue_t* pOutputQueue[MAX_CLOCK_PORTS]; OMX_BUFFERHEADERTYPE* pOutputBuffer[MAX_CLOCK_PORTS]; OMX_BOOL isOutputBufferNeeded[MAX_CLOCK_PORTS],bPortsBeingFlushed = OMX_FALSE; int i,j,outBufExchanged[MAX_CLOCK_PORTS]; for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { pOutPort[i] = (omx_base_clock_PortType *)omx_clocksrc_component_Private->ports[i]; pOutputSem[i] = pOutPort[i]->pBufferSem; pOutputQueue[i] = pOutPort[i]->pBufferQueue; pOutputBuffer[i] = NULL; isOutputBufferNeeded[i] = OMX_TRUE; outBufExchanged[i] = 0; } DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); while(omx_clocksrc_component_Private->state == OMX_StateIdle || omx_clocksrc_component_Private->state == OMX_StateExecuting || omx_clocksrc_component_Private->state == OMX_StatePause || omx_clocksrc_component_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { bPortsBeingFlushed |= PORT_IS_BEING_FLUSHED(pOutPort[i]); } while(bPortsBeingFlushed) { pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { if(isOutputBufferNeeded[i]==OMX_FALSE && PORT_IS_BEING_FLUSHED(pOutPort[i])) { pOutPort[i]->ReturnBufferFunction((omx_base_PortType*)pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[1]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning output buffer for port %i\n",i); } } tsem_up(omx_clocksrc_component_Private->flush_all_condition); tsem_down(omx_clocksrc_component_Private->flush_condition); pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); bPortsBeingFlushed = OMX_FALSE; for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { bPortsBeingFlushed |= PORT_IS_BEING_FLUSHED(pOutPort[i]); } } pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); /*Wait for clock state event*/ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Waiting for clock event\n",__func__); tsem_down(omx_clocksrc_component_Private->clockEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s clock event occured semval=%d \n",__func__,omx_clocksrc_component_Private->clockEventSem->semval); /*If port is not tunneled then simply return the buffer except paused state*/ if(omx_clocksrc_component_Private->transientState == OMX_TransStatePauseToExecuting) { for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { if(!PORT_IS_TUNNELED(pOutPort[i])) { if(pOutputSem[i]->semval>0 && isOutputBufferNeeded[i]==OMX_TRUE ) { tsem_down(pOutputSem[i]); if(pOutputQueue[i]->nelem>0){ outBufExchanged[i]++; isOutputBufferNeeded[i]=OMX_FALSE; pOutputBuffer[i] = dequeue(pOutputQueue[i]); if(pOutputBuffer[i] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!!\n"); break; } } } if(isOutputBufferNeeded[i]==OMX_FALSE) { /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if(pOutputBuffer[i]->nFilledLen!=0) { DEBUG(DEB_LEV_ERR, "In %s Returning Output nFilledLen=%d (line=%d)\n", __func__,(int)pOutputBuffer[i]->nFilledLen,__LINE__); pOutPort[i]->ReturnBufferFunction((omx_base_PortType*)pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[i]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; } } } } omx_clocksrc_component_Private->transientState = OMX_TransStateMax; } if(omx_clocksrc_component_Private->state == OMX_StateLoaded || omx_clocksrc_component_Private->state == OMX_StateInvalid || omx_clocksrc_component_Private->transientState == OMX_TransStateIdleToLoaded || omx_clocksrc_component_Private->transientState == OMX_TransStateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting (line %d)\n",__func__,__LINE__); break; } for(i=0;i<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;i++) { if(pOutPort[i]->sMediaTime.eUpdateType == OMX_TIME_UpdateClockStateChanged || pOutPort[i]->sMediaTime.eUpdateType == OMX_TIME_UpdateScaleChanged || pOutPort[i]->sMediaTime.eUpdateType == OMX_TIME_UpdateRequestFulfillment) { if((isOutputBufferNeeded[i]==OMX_TRUE && pOutputSem[i]->semval==0) && (omx_clocksrc_component_Private->state != OMX_StateLoaded && omx_clocksrc_component_Private->state != OMX_StateInvalid) && PORT_IS_ENABLED(pOutPort[i])) { //Signalled from EmptyThisBuffer or FillThisBuffer or some where else DEBUG(DEB_LEV_FULL_SEQ, "Waiting for next output buffer %i\n",i); tsem_down(omx_clocksrc_component_Private->bMgmtSem); } if(omx_clocksrc_component_Private->state == OMX_StateLoaded || omx_clocksrc_component_Private->state == OMX_StateInvalid || omx_clocksrc_component_Private->transientState == OMX_TransStateIdleToLoaded || omx_clocksrc_component_Private->transientState == OMX_TransStateInvalid) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Buffer Management Thread is exiting (line %d)\n",__func__,__LINE__); break; } if(pOutputSem[i]->semval>0 && isOutputBufferNeeded[i]==OMX_TRUE ) { tsem_down(pOutputSem[i]); if(pOutputQueue[i]->nelem>0){ outBufExchanged[i]++; isOutputBufferNeeded[i]=OMX_FALSE; pOutputBuffer[i] = dequeue(pOutputQueue[i]); if(pOutputBuffer[i] == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL output buffer!!\n"); break; } } } else { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Output buffer not available Port %d (line=%d)\n",__func__,(int)i,__LINE__); /*Check if any dummy bMgmtSem signal and ports are flushing*/ pthread_mutex_lock(&omx_clocksrc_component_Private->flush_mutex); bPortsBeingFlushed = OMX_FALSE; for(j=0;j<omx_clocksrc_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts;j++) { bPortsBeingFlushed |= PORT_IS_BEING_FLUSHED(pOutPort[j]); } pthread_mutex_unlock(&omx_clocksrc_component_Private->flush_mutex); if(bPortsBeingFlushed) { DEBUG(DEB_LEV_ERR, "In %s Ports are being flushed - breaking (line %d)\n",__func__,__LINE__); break; } } /*Process Output buffer of Port i */ if(isOutputBufferNeeded[i]==OMX_FALSE) { if (omx_clocksrc_component_Private->BufferMgmtCallback) { (*(omx_clocksrc_component_Private->BufferMgmtCallback))(openmaxStandComp, pOutputBuffer[i]); } else { /*If no buffer management call back then don't produce any output buffer*/ pOutputBuffer[i]->nFilledLen = 0; } /*Output Buffer has been produced or EOS. So, return output buffer and get new buffer*/ if(pOutputBuffer[i]->nFilledLen!=0) { pOutPort[i]->ReturnBufferFunction((omx_base_PortType*)pOutPort[i],pOutputBuffer[i]); outBufExchanged[i]--; pOutputBuffer[i]=NULL; isOutputBufferNeeded[i]=OMX_TRUE; } } } } DEBUG(DEB_LEV_SIMPLE_SEQ, "Sent Clock Event for all ports\n"); tsem_up(omx_clocksrc_component_Private->clockEventCompleteSem); } DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); return NULL; }
/** The Initialization function */ OMX_ERRORTYPE omx_parser3gp_component_Init(OMX_COMPONENTTYPE *openmaxStandComp) { omx_parser3gp_component_PrivateType* omx_parser3gp_component_Private = openmaxStandComp->pComponentPrivate; omx_base_video_PortType *pPortV; omx_base_audio_PortType *pPortA; int error; DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__); /* set the first time stamp flags to false */ FirstTimeStampFlag[0] = OMX_FALSE; FirstTimeStampFlag[1] = OMX_FALSE; /** initialization of parser3gp component private data structures */ /** opening the input file whose name is already set via setParameter */ error = av_open_input_file(&omx_parser3gp_component_Private->avformatcontext, (char*)omx_parser3gp_component_Private->sInputFileName, omx_parser3gp_component_Private->avinputformat, 0, omx_parser3gp_component_Private->avformatparameters); if(error != 0) { DEBUG(DEB_LEV_ERR,"Couldn't Open Input Stream error=%d File Name=%s\n", error,(char*)omx_parser3gp_component_Private->sInputFileName); return OMX_ErrorBadParameter; } av_find_stream_info(omx_parser3gp_component_Private->avformatcontext); /* Setting the audio and video coding types of the audio and video ports based on the information obtained from the stream */ /* for the video port */ pPortV = (omx_base_video_PortType *) omx_parser3gp_component_Private->ports[VIDEO_PORT_INDEX]; switch(omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_PORT_INDEX]->codec->codec_id){ case CODEC_ID_H264: pPortV->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; pPortV->sPortParam.format.video.nFrameWidth =omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->width; pPortV->sPortParam.format.video.nFrameHeight =omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->height; omx_parser3gp_component_Private->video_coding_type = OMX_VIDEO_CodingAVC; DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s Video Coding Type h.264\n",__func__); break; case CODEC_ID_MPEG4: pPortV->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; pPortV->sPortParam.format.video.nFrameWidth =omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->width; pPortV->sPortParam.format.video.nFrameHeight =omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->height; omx_parser3gp_component_Private->video_coding_type = OMX_VIDEO_CodingMPEG4; DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s Video Coding Type Mpeg4\n",__func__); break; default : (*(omx_parser3gp_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_parser3gp_component_Private->callbackData, OMX_EventError, /* The command was completed */ OMX_ErrorFormatNotDetected, /* Format Not Detected */ VIDEO_PORT_INDEX, /* This is the output port index*/ NULL); DEBUG(DEB_LEV_ERR,"Trouble in %s No Video Coding Type Selected (only H264 and MPEG4 codecs supported)\n",__func__); return OMX_ErrorBadParameter; } /* for the audio port*/ pPortA = (omx_base_audio_PortType *) omx_parser3gp_component_Private->ports[AUDIO_PORT_INDEX]; switch(omx_parser3gp_component_Private->avformatcontext->streams[AUDIO_STREAM]->codec->codec_id){ case CODEC_ID_MP3: pPortA->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingMP3; pPortA->sAudioParam.eEncoding = OMX_AUDIO_CodingMP3; omx_parser3gp_component_Private->audio_coding_type = OMX_AUDIO_CodingMP3; break; case CODEC_ID_AAC: pPortA->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingAAC; pPortA->sAudioParam.eEncoding = OMX_AUDIO_CodingAAC; omx_parser3gp_component_Private->audio_coding_type = OMX_AUDIO_CodingAAC; break; default: (*(omx_parser3gp_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_parser3gp_component_Private->callbackData, OMX_EventError, /* The command was completed */ OMX_ErrorFormatNotDetected, /* Format Not Detected */ AUDIO_PORT_INDEX, /* This is the output port index */ NULL); DEBUG(DEB_LEV_ERR,"Trouble in %s No Audio Coding Type Selected (only MP3 and AAC codecs supported)\n",__func__); return OMX_ErrorBadParameter; } DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s Video Extra data size=%d\n",__func__,omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->extradata_size); DEBUG(DEB_LEV_SIMPLE_SEQ,"In %s Audio Extra data size=%d\n",__func__,omx_parser3gp_component_Private->avformatcontext->streams[AUDIO_STREAM]->codec->extradata_size); /** initialization for buff mgmt callback function */ /** send callback regarding codec context extradata which will be required to * open the codec in the audio and video decoder component */ (*(omx_parser3gp_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_parser3gp_component_Private->callbackData, OMX_EventPortFormatDetected, /* The command was completed */ OMX_IndexParamVideoPortFormat, /* port Format Detected */ VIDEO_PORT_INDEX, /* This is the output port index */ NULL); (*(omx_parser3gp_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_parser3gp_component_Private->callbackData, OMX_EventPortSettingsChanged, /* The command was completed */ OMX_IndexParamCommonExtraQuantData, /* port settings changed */ VIDEO_PORT_INDEX, /* This is the output port index */ NULL); (*(omx_parser3gp_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_parser3gp_component_Private->callbackData, OMX_EventPortFormatDetected, /* The command was completed */ OMX_IndexParamVideoPortFormat, /* port Format Detected */ AUDIO_PORT_INDEX, /* This is the output port index */ NULL); (*(omx_parser3gp_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_parser3gp_component_Private->callbackData, OMX_EventPortSettingsChanged, /* The command was completed */ OMX_IndexParamCommonExtraQuantData, /* port settings changed */ AUDIO_PORT_INDEX, /* This is the output port index */ NULL); omx_parser3gp_component_Private->avformatReady = OMX_TRUE; omx_parser3gp_component_Private->isFirstBufferAudio = OMX_TRUE; omx_parser3gp_component_Private->isFirstBufferVideo = OMX_TRUE; /*Indicate that avformat is ready*/ tsem_up(omx_parser3gp_component_Private->avformatSyncSem); return OMX_ErrorNone; }
/** This is the central function for component processing. It * is executed in a separate thread, is synchronized with * semaphores at each port, those are released each time a new buffer * is available on the given port. */ void* omx_base_sink_BufferMgmtFunction (void* param) { OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; omx_base_sink_PrivateType* omx_base_sink_Private = (omx_base_sink_PrivateType*)omx_base_component_Private; omx_base_PortType *pInPort = (omx_base_PortType *)omx_base_sink_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; tsem_t* pInputSem = pInPort->pBufferSem; queue_t* pInputQueue = pInPort->pBufferQueue; OMX_BUFFERHEADERTYPE* pInputBuffer = NULL; OMX_COMPONENTTYPE* target_component; OMX_BOOL isInputBufferNeeded = OMX_TRUE; int inBufExchanged = 0; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n", __func__); while(omx_base_component_Private->state == OMX_StateIdle || omx_base_component_Private->state == OMX_StateExecuting || omx_base_component_Private->state == OMX_StatePause || omx_base_component_Private->transientState == OMX_TransStateLoadedToIdle){ /*Wait till the ports are being flushed*/ pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); while( PORT_IS_BEING_FLUSHED(pInPort)) { pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); if(isInputBufferNeeded==OMX_FALSE) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded=OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning input buffer\n"); } DEBUG(DEB_LEV_FULL_SEQ, "In %s signalling flush all condition \n", __func__); tsem_up(omx_base_sink_Private->flush_all_condition); tsem_down(omx_base_sink_Private->flush_condition); pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); } pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); /*No buffer to process. So wait here*/ if((pInputSem->semval==0 && isInputBufferNeeded==OMX_TRUE ) && (omx_base_sink_Private->state != OMX_StateLoaded && omx_base_sink_Private->state != OMX_StateInvalid)) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer \n"); tsem_down(omx_base_sink_Private->bMgmtSem); } if(omx_base_sink_Private->state == OMX_StateLoaded || omx_base_sink_Private->state == OMX_StateInvalid) { DEBUG(DEB_LEV_FULL_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); break; } DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer semval=%d \n",pInputSem->semval); if(pInputSem->semval>0 && isInputBufferNeeded==OMX_TRUE ) { tsem_down(pInputSem); if(pInputQueue->nelem>0){ inBufExchanged++; isInputBufferNeeded=OMX_FALSE; pInputBuffer = dequeue(pInputQueue); if(pInputBuffer == NULL){ DEBUG(DEB_LEV_ERR, "Had NULL input buffer!!\n"); break; } } } if(isInputBufferNeeded==OMX_FALSE) { if(pInputBuffer->nFlags==OMX_BUFFERFLAG_EOS) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Detected EOS flags in input buffer\n"); (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventBufferFlag, /* The command was completed */ 0, /* The commands was a OMX_CommandStateSet */ pInputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ NULL); pInputBuffer->nFlags=0; } target_component=(OMX_COMPONENTTYPE*)pInputBuffer->hMarkTargetComponent; if(target_component==(OMX_COMPONENTTYPE *)openmaxStandComp) { /*Clear the mark and generate an event*/ (*(omx_base_component_Private->callbacks->EventHandler)) (openmaxStandComp, omx_base_component_Private->callbackData, OMX_EventMark, /* The command was completed */ 1, /* The commands was a OMX_CommandStateSet */ 0, /* The state has been changed in message->messageParam2 */ pInputBuffer->pMarkData); } else if(pInputBuffer->hMarkTargetComponent!=NULL){ /*If this is not the target component then pass the mark*/ DEBUG(DEB_LEV_FULL_SEQ, "Can't Pass Mark. This is a Sink!!\n"); } if (omx_base_sink_Private->BufferMgmtCallback && pInputBuffer->nFilledLen > 0) { (*(omx_base_sink_Private->BufferMgmtCallback))(openmaxStandComp, pInputBuffer); } else { /*If no buffer management call back the explicitly consume input buffer*/ pInputBuffer->nFilledLen = 0; } /*Input Buffer has been completely consumed. So, get new input buffer*/ if(omx_base_sink_Private->state==OMX_StatePause && !PORT_IS_BEING_FLUSHED(pInPort)) { /*Waiting at paused state*/ tsem_wait(omx_base_sink_Private->bStateSem); } /*Input Buffer has been completely consumed. So, return input buffer*/ if(pInputBuffer->nFilledLen==0) { pInPort->ReturnBufferFunction(pInPort,pInputBuffer); inBufExchanged--; pInputBuffer=NULL; isInputBufferNeeded = OMX_TRUE; } } } DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); return NULL; }
/** @brief Called by the standard function. * * It frees the buffer header and in case also the buffer itself, if needed. * When all the buffers are done, the variable bIsEmptyOfBuffers is set to OMX_TRUE */ OMX_ERRORTYPE camera_video_port_FreeBuffer( omx_base_PortType *openmaxStandPort, OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE *pBuffer) { unsigned int i; OMX_COMPONENTTYPE *omxComponent = openmaxStandPort->standCompContainer; omx_base_component_PrivateType *omx_base_component_Private = (omx_base_component_PrivateType *)omxComponent->pComponentPrivate; omx_base_camera_video_PortType *omx_base_video_Port = (omx_base_camera_video_PortType *)openmaxStandPort; OMXDBUG(OMXDBUG_VERB, "In %s for port %p,%d\n", __func__, openmaxStandPort, (int)nPortIndex); if(nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { return OMX_ErrorBadPortIndex; } if(PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { return OMX_ErrorBadPortIndex; } //printf("b,,,,1\n"); if(omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) { if(!openmaxStandPort->bIsTransientToDisabled) { OMXDBUG(OMXDBUG_VERB, "In %s: The port is not allowed to free the buffers\n", __func__); (*(omx_base_component_Private->callbacks->EventHandler)) (omxComponent, omx_base_component_Private->callbackData, OMX_EventError, /* The command was completed */ OMX_ErrorPortUnpopulated, /* The commands was a OMX_CommandStateSet */ nPortIndex, /* The state has been changed in message->messageParam2 */ NULL); } } for(i = 0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++) { if(openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) { openmaxStandPort->bIsFullOfBuffers = OMX_FALSE; if(openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) { if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { OMXDBUG(OMXDBUG_VERB, "In %s freeing %i pBuffer=%p\n", __func__, (int)i, openmaxStandPort->pInternalBufferStorage[i]->pBuffer); if(omx_base_video_Port->pBufferHeadAct[i].pConfigParam.bAllocByComp == OMX_TRUE) { ext_phyfree_mem((void *)openmaxStandPort->pInternalBufferStorage[i]->pBuffer, \ (void *)omx_base_video_Port->pBufferHeadAct[i].pConfigParam.VirAddr); omx_base_video_Port->pBufferHeadAct[i].pConfigParam.bAllocByComp = OMX_FALSE; omx_base_video_Port->pBufferHeadAct[i].pBuffHead = NULL; } else { free(openmaxStandPort->pInternalBufferStorage[i]->pBuffer); } openmaxStandPort->pInternalBufferStorage[i]->pBuffer = NULL; omx_base_video_Port->pBufferHeadAct[i].pConfigParam.bUseBufFlag = OMX_FALSE; } } else if(openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ASSIGNED) { // printf("buffer free....????%x\n",pBuffer); if(omx_base_video_Port->pBufferHeadAct[i].pConfigParam.bAllocByComp == OMX_TRUE) { ext_phyfree_mem((void *)omx_base_video_Port->pBufferHeadAct[i].pConfigParam.phyAddr, \ (void *)omx_base_video_Port->pBufferHeadAct[i].pConfigParam.VirAddr); omx_base_video_Port->pBufferHeadAct[i].pConfigParam.bAllocByComp = OMX_FALSE; omx_base_video_Port->pBufferHeadAct[i].pConfigParam.phyAddr = NULL; omx_base_video_Port->pBufferHeadAct[i].pConfigParam.VirAddr = NULL; omx_base_video_Port->pBufferHeadAct[i].pBuffHead = NULL; } omx_base_video_Port->pBufferHeadAct[i].pConfigParam.bUseBufFlag = OMX_FALSE; free(pBuffer); } //printf("b,,,,2\n"); if(openmaxStandPort->bBufferStateAllocated[i] & HEADER_ALLOCATED) { free(openmaxStandPort->pInternalBufferStorage[i]); openmaxStandPort->pInternalBufferStorage[i] = NULL; } openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE; openmaxStandPort->nNumAssignedBuffers--; OMXDBUG(OMXDBUG_VERB, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); if(openmaxStandPort->nNumAssignedBuffers == 0) { if(omx_base_video_Port->pBufferHeadAct) { free(omx_base_video_Port->pBufferHeadAct); omx_base_video_Port->pBufferHeadAct = NULL; printf("Free pBufferHeadAct now\n"); } openmaxStandPort->sPortParam.bPopulated = OMX_FALSE; openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE; tsem_up(openmaxStandPort->pAllocSem); } OMXDBUG(OMXDBUG_VERB, "Out of %s for port %p\n", __func__, openmaxStandPort); return OMX_ErrorNone; } } OMXDBUG(OMXDBUG_ERR, "Out of %s for port %p with OMX_ErrorInsufficientResources\n", __func__, openmaxStandPort); return OMX_ErrorInsufficientResources; }