/** This function is used to process the input buffer and provide one output buffer */ void omx_videoenc_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* pInputBuffer, OMX_BUFFERHEADERTYPE* pOutputBuffer) { omx_videoenc_component_PrivateType* omx_videoenc_component_Private = openmaxStandComp->pComponentPrivate; omx_base_video_PortType *inPort = (omx_base_video_PortType *)omx_videoenc_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; OMX_S32 nOutputFilled = 0; OMX_U8* outputCurrBuffer; OMX_S32 nLen = 0; int size; size= inPort->sPortParam.format.video.nFrameWidth*inPort->sPortParam.format.video.nFrameHeight; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); /** Fill up the current input buffer when a new buffer has arrived */ if(omx_videoenc_component_Private->isNewBuffer) { omx_videoenc_component_Private->isNewBuffer = 0; DEBUG(DEB_LEV_FULL_SEQ, "New Buffer FilledLen = %d\n", (int)pInputBuffer->nFilledLen); omx_videoenc_component_Private->picture->data[0] = pInputBuffer->pBuffer; omx_videoenc_component_Private->picture->data[1] = omx_videoenc_component_Private->picture->data[0] + size; omx_videoenc_component_Private->picture->data[2] = omx_videoenc_component_Private->picture->data[1] + size / 4; omx_videoenc_component_Private->picture->linesize[0] = inPort->sPortParam.format.video.nFrameWidth; omx_videoenc_component_Private->picture->linesize[1] = inPort->sPortParam.format.video.nFrameWidth / 2; omx_videoenc_component_Private->picture->linesize[2] = inPort->sPortParam.format.video.nFrameWidth / 2; } outputCurrBuffer = pOutputBuffer->pBuffer; pOutputBuffer->nFilledLen = 0; pOutputBuffer->nOffset = 0; while (!nOutputFilled) { if (omx_videoenc_component_Private->isFirstBuffer) { tsem_down(omx_videoenc_component_Private->avCodecSyncSem); omx_videoenc_component_Private->isFirstBuffer = 0; } omx_videoenc_component_Private->avCodecContext->frame_number++; nLen = avcodec_encode_video(omx_videoenc_component_Private->avCodecContext, outputCurrBuffer, pOutputBuffer->nAllocLen, omx_videoenc_component_Private->picture); if (nLen < 0) { DEBUG(DEB_LEV_ERR, "----> A general error or simply frame not encoded?\n"); } pInputBuffer->nFilledLen = 0; omx_videoenc_component_Private->isNewBuffer = 1; if ( nLen >= 0) { pOutputBuffer->nFilledLen = nLen; } nOutputFilled = 1; } DEBUG(DEB_LEV_FULL_SEQ, "One output buffer %x nLen=%d is full returning in video encoder\n", (int)pOutputBuffer->pBuffer, (int)pOutputBuffer->nFilledLen); }
/** * This function processes the input file and returns packet by packet as an output data * this packet is used in video decoder component for decoding */ void omx_videosrc_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* pOutputBuffer) { omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate; struct v4l2_buffer buf; CLEAR(buf); DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__); if (omx_videosrc_component_Private->videoReady == OMX_FALSE) { if(omx_videosrc_component_Private->state == OMX_StateExecuting) { /*wait for video to be ready*/ tsem_down(omx_videosrc_component_Private->videoSyncSem); } else { return; } } pOutputBuffer->nOffset = 0; pOutputBuffer->nFilledLen = 0; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_DQBUF, &buf)) { switch (errno) { case EAGAIN: return; case EIO: /* Could ignore EIO, see spec. */ /* fall through */ default: DEBUG(DEB_LEV_ERR,"In %s error VIDIOC_DQBUF\n",__func__); return; } } assert(buf.index < n_buffers); if(omx_videosrc_component_Private->bOutBufferMemoryMapped == OMX_FALSE) { /* In case OMX_UseBuffer copy frame to buffer metadata */ memcpy(pOutputBuffer->pBuffer,omx_videosrc_component_Private->buffers[buf.index].start,omx_videosrc_component_Private->iFrameSize); } pOutputBuffer->nFilledLen = omx_videosrc_component_Private->iFrameSize; DEBUG(DEB_LEV_FULL_SEQ,"Camera output buffer nFilledLen=%d buf.length=%d\n",(int)pOutputBuffer->nFilledLen,buf.length); if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_QBUF, &buf)) { DEBUG(DEB_LEV_ERR,"In %s error VIDIOC_DQBUF\n",__func__); } /** return the current output buffer */ return; }
/** @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; }
/** @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; }
OMX_BOOL omx_alsasink_component_ClockPortHandleFunction(omx_alsasink_component_PrivateType* omx_alsasink_component_Private, OMX_BUFFERHEADERTYPE* inputbuffer){ omx_base_clock_PortType* pClockPort; OMX_BUFFERHEADERTYPE* clockBuffer; OMX_TIME_MEDIATIMETYPE* pMediaTime; OMX_HANDLETYPE hclkComponent; OMX_TIME_CONFIG_TIMESTAMPTYPE sClientTimeStamp; OMX_ERRORTYPE err; OMX_BOOL SendFrame=OMX_TRUE; omx_base_audio_PortType *pAudioPort; int static count=0; //frame counter pClockPort = (omx_base_clock_PortType*)omx_alsasink_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX]; pAudioPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; hclkComponent = pClockPort->hTunneledComponent; setHeader(&pClockPort->sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE)); /* if first time stamp is received then notify the clock component */ if((inputbuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) { DEBUG(DEB_LEV_FULL_SEQ,"In %s first time stamp = %llx \n", __func__,inputbuffer->nTimeStamp); inputbuffer->nFlags = 0; hclkComponent = pClockPort->hTunneledComponent; setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeClientStartTime, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } if(!PORT_IS_BEING_FLUSHED(pAudioPort) && !PORT_IS_BEING_FLUSHED(pClockPort)) { tsem_down(pClockPort->pBufferSem); /* wait for state change notification from clock src*/ /* update the clock state and clock scale info into the alsa sink private data */ if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; omx_alsasink_component_Private->eState = pMediaTime->eState; omx_alsasink_component_Private->xScale = pMediaTime->xScale; pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); } } } /* do not send the data to alsa and return back, if the clock is not running or the scale is anything but 1*/ if(!(omx_alsasink_component_Private->eState==OMX_TIME_ClockStateRunning && (omx_alsasink_component_Private->xScale>>16)==1)){ inputbuffer->nFilledLen=0; //return; SendFrame = OMX_FALSE; return SendFrame; } /* check for any scale change information from the clock component */ if(pClockPort->pBufferSem->semval>0){ tsem_down(pClockPort->pBufferSem); if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { if(/*(omx_alsasink_component_Private->xScale>>16)==2 &&*/ (pMediaTime->xScale>>16)==1){ /* check with Q16 format only */ /* rebase the clock time base when turning to normal play mode*/ hclkComponent = pClockPort->hTunneledComponent; setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentAudioReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } } omx_alsasink_component_Private->xScale = pMediaTime->xScale; } pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); }
/** This function is used to process the input buffer and provide one output buffer */ void omx_shvpudec_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* pInputBuffer, OMX_BUFFERHEADERTYPE* pOutputBuffer) { omx_shvpudec_component_PrivateType* vpudec = openmaxStandComp->pComponentPrivate; int ret = 0; OMX_U32 input_len=0, input_used=0; DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); #if 0 /* For comparing input to output */ memcpy (pOutputBuffer->pBuffer, pInputBuffer->pBuffer, pInputBuffer->nFilledLen); pOutputBuffer->nFilledLen = pInputBuffer->nFilledLen; pInputBuffer->nFilledLen = 0; goto buffer_mgmt_done; #endif vpudec->pOutputBuffer = pOutputBuffer; pOutputBuffer->nFilledLen = 0; pOutputBuffer->nOffset = 0; DEBUG(DEB_LEV_FULL_SEQ, "Output buffer size %d\n", pOutputBuffer->nAllocLen); /* If there is some already cached output, copy it out */ if (vpudec->outputCacheFilled > vpudec->outputCacheCopied) { OMX_U32 copy_len = MIN (vpudec->outputCacheFilled - vpudec->outputCacheCopied, pOutputBuffer->nAllocLen); DEBUG(DEB_LEV_FULL_SEQ, "Copying %d bytes from cache, %d remaining\n", copy_len, vpudec->outputCacheFilled - (vpudec->outputCacheCopied + copy_len)); memcpy (pOutputBuffer->pBuffer, &vpudec->outputCache[vpudec->outputCacheCopied], copy_len); vpudec->outputCacheCopied += copy_len; pOutputBuffer->nFilledLen = copy_len; /* If we have exhausted the output cache, reset it */ if (vpudec->outputCacheFilled == vpudec->outputCacheCopied) { DEBUG(DEB_LEV_FULL_SEQ, "Exhausted output cache, resetting\n"); vpudec->outputCacheFilled = 0; vpudec->outputCacheCopied = 0; } /* If we have filled the output buffer, we are done */ if (pOutputBuffer->nFilledLen == pOutputBuffer->nAllocLen) { DEBUG(DEB_LEV_FULL_SEQ, "Filled output buffer\n"); goto buffer_mgmt_done; } } input_len = vpudec->inputCurrLength; input_used = MIN (pInputBuffer->nFilledLen, INPUT_BUF_LEN - input_len); /** Fill up the current input buffer when a new buffer has arrived */ if(vpudec->isNewBuffer) { memcpy (&vpudec->inputCurrBuffer[input_len], pInputBuffer->pBuffer, input_used); input_len = input_used; vpudec->inputCurrLength += input_len; pInputBuffer->nFilledLen -= input_len; vpudec->isNewBuffer = 0; } if (vpudec->isFirstBuffer) { DEBUG(DEB_LEV_SIMPLE_SEQ, " isFirstBuffer {\n"); tsem_down(vpudec->avCodecSyncSem); vpudec->isFirstBuffer = 0; } DEBUG(DEB_LEV_SIMPLE_SEQ, " Setting decode callback ...\n"); shcodecs_decoder_set_decoded_callback (vpudec->decoder, vpu_decoded, vpudec); DEBUG(DEB_LEV_SIMPLE_SEQ, " Calling decode...\n"); ret = shcodecs_decode (vpudec->decoder, vpudec->inputCurrBuffer, vpudec->inputCurrLength); DEBUG(DEB_LEV_SIMPLE_SEQ, " Returned from decode (returned %d) ...\n", ret); if (ret < 0) { DEBUG(DEB_LEV_ERR, "----> A general error or simply frame not decoded?\n"); } else if (ret > 0) { vpudec->inputCurrLength -= ret; memmove (vpudec->inputCurrBuffer, &vpudec->inputCurrBuffer[ret], vpudec->inputCurrLength); } vpudec->isNewBuffer = 1; buffer_mgmt_done: DEBUG(DEB_LEV_FULL_SEQ, "One output buffer %x nLen=%d is full returning in video decoder\n", (int)pOutputBuffer->pBuffer, (int)pOutputBuffer->nFilledLen); }
/** * This function processes the input file and returns packet by packet as an output data * this packet is used in audio/video decoder component for decoding */ void omx_parser3gp_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* pOutputBuffer) { omx_parser3gp_component_PrivateType* omx_parser3gp_component_Private = openmaxStandComp->pComponentPrivate; OMX_BUFFERHEADERTYPE* temp_buffer; int error; int stream_index; AVRational bq = { 1, 1000000 }; omx_base_clock_PortType *pClockPort; OMX_TIME_MEDIATIMETYPE* pMediaTime; OMX_BUFFERHEADERTYPE* clockBuffer; OMX_S32 Scale; temp_buffer = omx_parser3gp_component_Private->pTmpOutputBuffer; DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__); if (omx_parser3gp_component_Private->avformatReady == OMX_FALSE) { if(omx_parser3gp_component_Private->state == OMX_StateExecuting) { /*wait for avformat to be ready*/ tsem_down(omx_parser3gp_component_Private->avformatSyncSem); } else { return; } } if(omx_parser3gp_component_Private->isFirstBufferAudio == OMX_TRUE && pOutputBuffer->nOutputPortIndex==AUDIO_PORT_INDEX ) { omx_parser3gp_component_Private->isFirstBufferAudio = OMX_FALSE; if(omx_parser3gp_component_Private->avformatcontext->streams[AUDIO_STREAM]->codec->extradata_size > 0) { memcpy(pOutputBuffer->pBuffer, omx_parser3gp_component_Private->avformatcontext->streams[AUDIO_STREAM]->codec->extradata, omx_parser3gp_component_Private->avformatcontext->streams[AUDIO_STREAM]->codec->extradata_size); pOutputBuffer->nFilledLen = omx_parser3gp_component_Private->avformatcontext->streams[AUDIO_STREAM]->codec->extradata_size; pOutputBuffer->nFlags = pOutputBuffer->nFlags | OMX_BUFFERFLAG_CODECCONFIG; DEBUG(DEB_ALL_MESS, "In %s Sending Audio First Buffer Extra Data Size=%d\n",__func__,(int)pOutputBuffer->nFilledLen); return; } } if(omx_parser3gp_component_Private->isFirstBufferVideo == OMX_TRUE && pOutputBuffer->nOutputPortIndex==VIDEO_PORT_INDEX ) { omx_parser3gp_component_Private->isFirstBufferVideo = OMX_FALSE; if(omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->extradata_size > 0) { memcpy(pOutputBuffer->pBuffer, omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->extradata, omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->extradata_size); pOutputBuffer->nFilledLen = omx_parser3gp_component_Private->avformatcontext->streams[VIDEO_STREAM]->codec->extradata_size; pOutputBuffer->nFlags = pOutputBuffer->nFlags | OMX_BUFFERFLAG_CODECCONFIG; DEBUG(DEB_ALL_MESS, "In %s Sending Video First Buffer Extra Data Size=%d\n",__func__,(int)pOutputBuffer->nFilledLen); return; } } pOutputBuffer->nFilledLen = 0; pOutputBuffer->nOffset = 0; /* check for any information from the clock component */ pClockPort = (omx_base_clock_PortType*)omx_parser3gp_component_Private->ports[CLOCK_PORT_INDEX]; if(pClockPort->pBufferSem->semval>0){ tsem_down(pClockPort->pBufferSem); clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; omx_parser3gp_component_Private->xScale = pMediaTime->xScale; pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); } /* read the stream */ if(temp_buffer->nFilledLen==0) { /* no data available in temporary buffer*/ error = av_read_frame(omx_parser3gp_component_Private->avformatcontext, &omx_parser3gp_component_Private->pkt); if(error < 0) { DEBUG(DEB_LEV_FULL_SEQ,"In %s EOS - no more packet,state=%x\n",__func__, omx_parser3gp_component_Private->state); pOutputBuffer->nFlags = pOutputBuffer->nFlags | OMX_BUFFERFLAG_EOS; } else { stream_index = omx_parser3gp_component_Private->pkt.stream_index; Scale = omx_parser3gp_component_Private->xScale >> 16; if(Scale!=1 && Scale!=0 && stream_index==VIDEO_STREAM){ /* TODO - change to a switch statement to handle all cases */ /* fast forward the stream if Scale>1 */ if(Scale>1){ error = av_seek_frame(omx_parser3gp_component_Private->avformatcontext, stream_index, omx_parser3gp_component_Private->pkt.pts+Scale ,0); if(error < 0) { DEBUG(DEB_LEV_ERR,"Error in seeking stream=%d\n",stream_index); }else DEBUG(DEB_LEV_SIMPLE_SEQ,"Success in seeking stream=%d\n",stream_index); } if(Scale<0){ error = av_seek_frame(omx_parser3gp_component_Private->avformatcontext, stream_index, omx_parser3gp_component_Private->pkt.pts+Scale ,AVSEEK_FLAG_BACKWARD); if(error < 0) { DEBUG(DEB_LEV_ERR,"Error in seeking stream=%d\n",stream_index); }else DEBUG(DEB_LEV_SIMPLE_SEQ,"Success in seeking stream=%d\n",stream_index); } } if((stream_index==VIDEO_STREAM && pOutputBuffer->nOutputPortIndex==VIDEO_PORT_INDEX) || (stream_index==AUDIO_STREAM && pOutputBuffer->nOutputPortIndex==AUDIO_PORT_INDEX)){ /** copying the packetized data in the output buffer that will be decoded in the decoder component */ if(pOutputBuffer->nAllocLen >= omx_parser3gp_component_Private->pkt.size) { memcpy(pOutputBuffer->pBuffer, omx_parser3gp_component_Private->pkt.data, omx_parser3gp_component_Private->pkt.size); pOutputBuffer->nFilledLen = omx_parser3gp_component_Private->pkt.size; pOutputBuffer->nTimeStamp = av_rescale_q(omx_parser3gp_component_Private->pkt.pts, omx_parser3gp_component_Private->avformatcontext->streams[stream_index]->time_base, bq); if(FirstTimeStampFlag[stream_index]==OMX_FALSE){ pOutputBuffer->nFlags = pOutputBuffer->nFlags | OMX_BUFFERFLAG_STARTTIME; FirstTimeStampFlag[stream_index] = OMX_TRUE; } } else { DEBUG(DEB_LEV_ERR,"In %s Buffer Size=%d less than Pkt size=%d buffer=%x port_index=%d \n",__func__, (int)pOutputBuffer->nAllocLen,(int)omx_parser3gp_component_Private->pkt.size, (unsigned int)pOutputBuffer,(int)pOutputBuffer->nOutputPortIndex); } }else { /* the port type and the stream data do not match so keep the data in temporary buffer*/ if(temp_buffer->nAllocLen >= omx_parser3gp_component_Private->pkt.size) { memcpy(temp_buffer->pBuffer, omx_parser3gp_component_Private->pkt.data, omx_parser3gp_component_Private->pkt.size); temp_buffer->nFilledLen = omx_parser3gp_component_Private->pkt.size; temp_buffer->nTimeStamp = av_rescale_q (omx_parser3gp_component_Private->pkt.pts, omx_parser3gp_component_Private->avformatcontext->streams[stream_index]->time_base, bq); temp_buffer->nOutputPortIndex = omx_parser3gp_component_Private->pkt.stream_index; /* keep the stream_index in OutputPortIndex for identification */ if(FirstTimeStampFlag[temp_buffer->nOutputPortIndex]==OMX_FALSE){ temp_buffer->nFlags = temp_buffer->nFlags | OMX_BUFFERFLAG_STARTTIME; FirstTimeStampFlag[temp_buffer->nOutputPortIndex] = OMX_TRUE; } } else { DEBUG(DEB_LEV_ERR,"In %s Buffer Size=%d less than Pkt size=%d\n",__func__, (int)temp_buffer->nAllocLen,(int)omx_parser3gp_component_Private->pkt.size); } } } } else { /* data available in temporary buffer */
OMX_ERRORTYPE audiodecEventHandler( 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_PARAM_PORTDEFINITIONTYPE param; OMX_AUDIO_PARAM_PCMMODETYPE pcmParam; 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, "Audio Decoder 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->decoderEventSem); } else if (Data1 == OMX_CommandPortEnable){ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Received Port Enable Event\n",__func__); tsem_up(appPriv->decoderEventSem); } else if (Data1 == OMX_CommandPortDisable){ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Received Port Disable Event\n",__func__); tsem_up(appPriv->decoderEventSem); } } else if(eEvent == OMX_EventPortSettingsChanged) { DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Received Port Settings Changed Event\n", __func__); if (Data2 == 1) { param.nPortIndex = 1; setHeader(¶m, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); err = OMX_GetParameter(appPriv->audiodechandle,OMX_IndexParamPortDefinition, ¶m); /*Get Port parameters*/ pcmParam.nPortIndex=1; setHeader(&pcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); err = OMX_GetParameter(appPriv->audiodechandle, OMX_IndexParamAudioPcm, &pcmParam); if (flagPlaybackOn && flagSetupTunnel) { /*Disable Volume Component and Audio Sink Port,Set Parameter in Tunneled Case*/ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Volume Component Port Disabling\n", __func__); err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandPortDisable, 1, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Volume Component port disable failed\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Audio Sink Port Disabling\n", __func__); err = OMX_SendCommand(appPriv->audiosinkhandle, OMX_CommandPortDisable, 0, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"alas sink port disable failed\n"); exit(1); } /*Wait for Ports Disable Events*/ tsem_down(appPriv->sinkEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Audio Sink Port Disabled\n", __func__); tsem_down(appPriv->volumeEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Volume Component Port Disabled\n", __func__); DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Audio Sink Setting Parameters\n", __func__); pcmParam.nPortIndex=0; err = OMX_SetParameter(appPriv->audiosinkhandle, OMX_IndexParamAudioPcm, &pcmParam); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetParameter 0 \n",err); } err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandPortEnable, 1, NULL); err = OMX_SendCommand(appPriv->audiosinkhandle, OMX_CommandPortEnable, 0, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"audio sink port enable failed\n"); exit(1); } /*Wait for Ports Enable Events*/ tsem_down(appPriv->volumeEventSem); tsem_down(appPriv->sinkEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ,"audio sink port enabled\n"); } } else if (Data2 == 0) { /*Get Port parameters*/ param.nPortIndex = 0; setHeader(¶m, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); err = OMX_GetParameter(appPriv->audiodechandle,OMX_IndexParamPortDefinition, ¶m); } } 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; }
/** @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; }
OMX_BOOL omx_video_scheduler_component_ClockPortHandleFunction( omx_video_scheduler_component_PrivateType* omx_video_scheduler_component_Private, OMX_BUFFERHEADERTYPE* pInputBuffer){ omx_base_clock_PortType *pClockPort; OMX_HANDLETYPE hclkComponent; OMX_BUFFERHEADERTYPE* clockBuffer; OMX_TIME_MEDIATIMETYPE* pMediaTime; OMX_TIME_CONFIG_TIMESTAMPTYPE sClientTimeStamp; OMX_ERRORTYPE err; OMX_BOOL SendFrame; omx_base_video_PortType *pInputPort; pClockPort = (omx_base_clock_PortType*) omx_video_scheduler_component_Private->ports[CLOCKPORT_INDEX]; pInputPort = (omx_base_video_PortType *) omx_video_scheduler_component_Private->ports[0]; hclkComponent = pClockPort->hTunneledComponent; SendFrame = OMX_TRUE; DEBUG(DEB_LEV_FULL_SEQ, "In %s Clock Port is Tunneled. Sending Request\n", __func__); /* if first time stamp is received then notify the clock component */ if((pInputBuffer->nFlags & OMX_BUFFERFLAG_STARTTIME) == OMX_BUFFERFLAG_STARTTIME) { DEBUG(DEB_LEV_FULL_SEQ," In %s first time stamp = %llx \n", __func__,pInputBuffer->nTimeStamp); pInputBuffer->nFlags = 0; hclkComponent = pClockPort->hTunneledComponent; setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeClientStartTime, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } tsem_down(pClockPort->pBufferSem); /* wait for state change notification */ /* update the clock state and clock scale info into the fbdev private data */ if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer=dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; omx_video_scheduler_component_Private->eState = pMediaTime->eState; omx_video_scheduler_component_Private->xScale = pMediaTime->xScale; pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); } } /* do not send the data to sink and return back, if the clock is not running*/ if(!omx_video_scheduler_component_Private->eState==OMX_TIME_ClockStateRunning){ pInputBuffer->nFilledLen=0; SendFrame = OMX_FALSE; return SendFrame; } /* check for any scale change information from the clock component */ if(pClockPort->pBufferSem->semval>0) { tsem_down(pClockPort->pBufferSem); if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { /* On scale change update the media time base */ sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } omx_video_scheduler_component_Private->frameDropFlag = OMX_TRUE; omx_video_scheduler_component_Private->dropFrameCount = 0; omx_video_scheduler_component_Private->xScale = pMediaTime->xScale; } pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); } } /* drop next seven frames on scale change and rebase the clock time base */ if(omx_video_scheduler_component_Private->frameDropFlag && omx_video_scheduler_component_Private->dropFrameCount<7) { //TODO - second check cond can be removed verify omx_video_scheduler_component_Private->dropFrameCount ++; if(omx_video_scheduler_component_Private->dropFrameCount==7) { /* rebase the clock time base */ setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } omx_video_scheduler_component_Private->frameDropFlag = OMX_FALSE; omx_video_scheduler_component_Private->dropFrameCount = 0; SendFrame = OMX_TRUE; } SendFrame = OMX_FALSE; } /* frame is not to be dropped so send the request for the timestamp for the data delivery */ if(SendFrame){ if(!PORT_IS_BEING_FLUSHED(pInputPort) && !PORT_IS_BEING_FLUSHED(pClockPort) && omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) { setHeader(&pClockPort->sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE)); pClockPort->sMediaTimeRequest.nMediaTimestamp = pInputBuffer->nTimeStamp; pClockPort->sMediaTimeRequest.nOffset = 100; /*set the requested offset */ pClockPort->sMediaTimeRequest.nPortIndex = pClockPort->nTunneledPort; pClockPort->sMediaTimeRequest.pClientPrivate = NULL; /* fill the appropriate value */ err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeMediaTimeRequest, &pClockPort->sMediaTimeRequest); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } if(!PORT_IS_BEING_FLUSHED(pInputPort) && !PORT_IS_BEING_FLUSHED(pClockPort) && omx_video_scheduler_component_Private->transientState != OMX_TransStateExecutingToIdle) { tsem_down(pClockPort->pBufferSem); /* wait for the request fullfillment */ if(pClockPort->pBufferQueue->nelem > 0) { clockBuffer = dequeue(pClockPort->pBufferQueue); pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { /* update the media time base */ setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); // do not need to setHeader again do once at the top sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; sClientTimeStamp.nTimestamp = pInputBuffer->nTimeStamp; err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentVideoReference, &sClientTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); } omx_video_scheduler_component_Private->frameDropFlag = OMX_TRUE; omx_video_scheduler_component_Private->dropFrameCount = 0; omx_video_scheduler_component_Private->xScale = pMediaTime->xScale; } if(pMediaTime->eUpdateType==OMX_TIME_UpdateRequestFulfillment){ if((pMediaTime->nOffset)>0) { SendFrame=OMX_TRUE; }else { SendFrame = OMX_FALSE; } } pClockPort->ReturnBufferFunction((omx_base_PortType *)pClockPort,clockBuffer); } } } } return(SendFrame); }
int main(int argc, char** argv) { OMX_PORT_PARAM_TYPE param; OMX_BUFFERHEADERTYPE *inBuffer1, *inBuffer2, *outBuffer1, *outBuffer2; int data_read1; int data_read2; OMX_PARAM_PORTDEFINITIONTYPE sPortDef; OMX_AUDIO_CONFIG_VOLUMETYPE sVolume; int gain=100; int argn_dec; /* Obtain file descriptor */ if(argc < 2){ display_help(); } else { flagIsOutputExpected = 0; flagOutputReceived = 0; flagInputReceived = 0; flagIsGain = 0; argn_dec = 1; while (argn_dec<argc) { if (*(argv[argn_dec]) =='-') { if (flagIsOutputExpected) { display_help(); } switch (*(argv[argn_dec]+1)) { case 'h': display_help(); break; case 'o': flagIsOutputExpected = 1; break; case 'g': flagIsGain = 1; break; default: display_help(); } } else { if (flagIsGain) { gain = (int)atoi(argv[argn_dec]); flagIsGain = 0; if(gain > 100) { DEBUG(DEFAULT_MESSAGES, "Gain should be between [0..100]\n"); gain = 100; } } else if (flagIsOutputExpected) { output_file = malloc(strlen(argv[argn_dec]) + 1); strcpy(output_file,argv[argn_dec]); flagIsOutputExpected = 0; flagOutputReceived = 1; } else { input_file = malloc(strlen(argv[argn_dec]) + 1); strcpy(input_file,argv[argn_dec]); flagInputReceived = 1; } } argn_dec++; } if (!flagInputReceived) { display_help(); } DEBUG(DEFAULT_MESSAGES, "Input file %s", input_file); DEBUG(DEFAULT_MESSAGES, " to "); if (flagOutputReceived) { DEBUG(DEFAULT_MESSAGES, " %s\n", output_file); } } fd = open(input_file, O_RDONLY); if(fd < 0){ perror("Error opening input file\n"); exit(1); } if (flagOutputReceived) { outfile = fopen(output_file,"wb"); if(outfile == NULL) { DEBUG(DEB_LEV_ERR, "Error at opening the output file"); exit(1); } } filesize = getFileSize(fd); /* Initialize application private data */ appPriv = malloc(sizeof(appPrivateType)); pthread_cond_init(&appPriv->condition, NULL); pthread_mutex_init(&appPriv->mutex, NULL); appPriv->eventSem = malloc(sizeof(tsem_t)); tsem_init(appPriv->eventSem, 0); appPriv->eofSem = malloc(sizeof(tsem_t)); tsem_init(appPriv->eofSem, 0); err = OMX_Init(); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "OMX_Init() failed\n"); exit(1); } /** Ask the core for a handle to the volume control component */ err = OMX_GetHandle(&handle, "OMX.st.volume.component", NULL /*appPriv */, &callbacks); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "OMX_GetHandle failed\n"); exit(1); } if((gain >= 0) && (gain <100)) { err = OMX_GetConfig(handle, OMX_IndexConfigAudioVolume, &sVolume); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_GetConfig 0 \n",err); } sVolume.sVolume.nValue = gain; DEBUG(DEFAULT_MESSAGES, "Setting Gain %d \n", gain); err = OMX_SetConfig(handle, OMX_IndexConfigAudioVolume, &sVolume); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig 0 \n",err); } } /** Set the number of ports for the parameter structure */ param.nPorts = 2; setHeader(¶m, sizeof(OMX_PORT_PARAM_TYPE)); err = OMX_GetParameter(handle, OMX_IndexParamAudioInit, ¶m); if(err != OMX_ErrorNone){ DEBUG(DEB_LEV_ERR, "Error in getting OMX_PORT_PARAM_TYPE parameter\n"); exit(1); } setHeader(&sPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); sPortDef.nPortIndex = 0; err = OMX_GetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef); sPortDef.nBufferCountActual = 2; err = OMX_SetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef); if(err != OMX_ErrorNone){ DEBUG(DEB_LEV_ERR, "Error in getting OMX_PORT_PARAM_TYPE parameter\n"); exit(1); } sPortDef.nPortIndex = 1; err = OMX_GetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef); sPortDef.nBufferCountActual = 2; err = OMX_SetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef); if(err != OMX_ErrorNone){ DEBUG(DEB_LEV_ERR, "Error in getting OMX_PORT_PARAM_TYPE parameter\n"); exit(1); } err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateIdle, NULL); inBuffer1 = inBuffer2 = outBuffer1 = outBuffer2 = NULL; err = OMX_AllocateBuffer(handle, &inBuffer1, 0, NULL, BUFFER_IN_SIZE); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer in 1%i\n", err); exit(1); } err = OMX_AllocateBuffer(handle, &inBuffer2, 0, NULL, BUFFER_IN_SIZE); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer in 2 %i\n", err); exit(1); } err = OMX_AllocateBuffer(handle, &outBuffer1, 1, NULL, BUFFER_IN_SIZE); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer out 1 %i\n", err); exit(1); } err = OMX_AllocateBuffer(handle, &outBuffer2, 1, NULL, BUFFER_IN_SIZE); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer out 2 %i\n", err); exit(1); } tsem_down(appPriv->eventSem); err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); /* Wait for commands to complete */ tsem_down(appPriv->eventSem); DEBUG(DEB_LEV_PARAMS, "Had buffers at:\n0x%08x\n0x%08x\n0x%08x\n0x%08x\n", (int)inBuffer1->pBuffer, (int)inBuffer2->pBuffer, (int)outBuffer1->pBuffer, (int)outBuffer2->pBuffer); DEBUG(DEB_LEV_PARAMS, "After switch to executing\n"); data_read1 = read(fd, inBuffer1->pBuffer, BUFFER_IN_SIZE); inBuffer1->nFilledLen = data_read1; filesize -= data_read1; data_read2 = read(fd, inBuffer2->pBuffer, BUFFER_IN_SIZE); inBuffer2->nFilledLen = data_read2; filesize -= data_read2; DEBUG(DEB_LEV_PARAMS, "Empty first buffer %x\n", (int)inBuffer1); err = OMX_EmptyThisBuffer(handle, inBuffer1); DEBUG(DEB_LEV_PARAMS, "Empty second buffer %x\n", (int)inBuffer2); err = OMX_EmptyThisBuffer(handle, inBuffer2); /** Schedule a couple of buffers to be filled on the output port * The callback itself will re-schedule them. */ err = OMX_FillThisBuffer(handle, outBuffer1); err = OMX_FillThisBuffer(handle, outBuffer2); tsem_down(appPriv->eofSem); err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateIdle, NULL); /* Wait for commands to complete */ tsem_down(appPriv->eventSem); err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateLoaded, NULL); err = OMX_FreeBuffer(handle, 0, inBuffer1); err = OMX_FreeBuffer(handle, 0, inBuffer2); err = OMX_FreeBuffer(handle, 1, outBuffer1); err = OMX_FreeBuffer(handle, 1, outBuffer2); /* Wait for commands to complete */ tsem_down(appPriv->eventSem); OMX_FreeHandle(handle); free(appPriv->eventSem); free(appPriv); if (flagOutputReceived) { if(fclose(outfile) != 0) { DEBUG(DEB_LEV_ERR,"Error in closing output file\n"); exit(1); } free(output_file); } close(fd); free(input_file); return 0; }
/** 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; }
int main(int argc, char** argv) { OMX_ERRORTYPE err = OMX_ErrorNone; OMX_BOOL bOmxInitialized = OMX_FALSE; OMX_PARAM_PORTDEFINITIONTYPE sOmxPortDefinition; OMX_CONFIG_BOOLEANTYPE sOmxCapturing; OMX_CONFIG_BOOLEANTYPE sOmxAutoPause; OMX_STATETYPE sOmxState; OMX_U32 nBufferCount; OMX_U32 nBufferSize; OMX_U32 nPortIndex; OMX_U32 i; unsigned int nPreviewTime = 5;/* By default, running for 5 sec for preview */ unsigned int nCaptureTime = 5;/* By default, running for 5 sec for video capture */ char *cCaptureFileName = g_DefaultCaptureFileName; char *cThumbnailFileName = g_DefaultThumbnailFileName; OMX_BOOL bCameraStillImageMode = OMX_FALSE; /* By default, the camera is running in video capture mode */ OMX_BOOL bCameraAutoPause = OMX_FALSE; /* By default, the camera is not running in autopause mode */ unsigned int nMaxRunCount = 1;/* By default, running once */ unsigned int nRunCount = 0; /* Parse arguments */ for ( i = 1; i < argc && argv[i][0] == '-'; i++) { switch (argv[i][1]) { case 'i': bCameraStillImageMode = OMX_TRUE; break; case 'p': bCameraAutoPause = OMX_TRUE; break; case 't': i++; if (i>=argc ||argv[i][0] == '-') { DEBUG(DEB_LEV_ERR, "preview_time expected!\n"); display_help(argv[0]); exit(-1); } nPreviewTime = (unsigned int)atoi(argv[i]); break; case 's': i++; if (i>=argc ||argv[i][0] == '-') { DEBUG(DEB_LEV_ERR, "capture_time expected!\n"); display_help(argv[0]); exit(-1); } nCaptureTime = (unsigned int)atoi(argv[i]); break; case 'c': i++; if (i>=argc ||argv[i][0] == '-') { DEBUG(DEB_LEV_ERR, "capture_file expected!\n"); display_help(argv[0]); exit(-1); } cCaptureFileName = argv[i]; break; case 'm': i++; if (i>=argc ||argv[i][0] == '-') { DEBUG(DEB_LEV_ERR, "thumbnail_file expected!\n"); display_help(argv[0]); exit(-1); } cThumbnailFileName = argv[i]; break; case 'n': i++; if (i>=argc ||argv[i][0] == '-') { DEBUG(DEB_LEV_ERR, "run_count expected!\n"); display_help(argv[0]); exit(-1); } nMaxRunCount = (unsigned int)atoi(argv[i]); break; case 'h': display_help(argv[0]); exit(0); break; default: DEBUG(DEB_LEV_ERR, "Unrecognized option -%c!\n", argv[i][1]); display_help(argv[0]); exit(-1); } } /* Init the Omx core */ DEBUG(DEB_LEV_SIMPLE_SEQ, "Init the OMX core\n"); if ((err = OMX_Init()) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "The OpenMAX core can not be initialized. Exiting...\n"); goto EXIT; } bOmxInitialized = OMX_TRUE; /* Initialize application private data */ appPriv = malloc(sizeof(appPrivateType)); if (appPriv == NULL) { DEBUG(DEB_LEV_ERR, "Allocate app private data failed!Exiting...\n"); err = OMX_ErrorInsufficientResources; goto EXIT; } memset(appPriv, 0, sizeof(appPrivateType)); memset(&sCameraPortBufferList, 0, NUM_CAMERAPORTS*sizeof(OMX_PORTBUFFERCTXT)); /* Open output file for camera capture and thumbnail port */ fCapture=fopen(cCaptureFileName, "wb"); fThumbnail=fopen(cThumbnailFileName, "wb"); /* Getting camera component handle */ if ((err = OMX_GetHandle(&appPriv->camerahandle, "OMX.st.v4l.camera_source", appPriv, &camera_source_callbacks)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Getting camera component handle failed!Exiting...\n"); goto EXIT; } /* Getting fbsink component handle */ if ((err = OMX_GetHandle(&appPriv->colorconvhandle, "OMX.st.video_colorconv.ffmpeg", appPriv, &colorconv_callbacks)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Getting color conv component handle failed!Exiting...\n"); goto EXIT; } /* Getting fbsink component handle */ if ((err = OMX_GetHandle(&appPriv->fbsinkhandle, "OMX.st.fbdev.fbdev_sink", appPriv, &fbsink_callbacks)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Getting fbsink component handle failed!Exiting...\n"); goto EXIT; } /* Setting parameters for camera component */ if ((err = setCameraParameters(bCameraStillImageMode)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set camera parameters failed! Use default settings...\n"); /* Do not exit! */ } /* Setting parameters for color converter component */ if ((err = setColorConvParameters()) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set fbsink parameters failed! Use default settings...\n"); /* Do not exit! */ } /* Setting parameters for fbsink component */ if ((err = setFbsinkParameters()) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set fbsink parameters failed! Use default settings...\n"); /* Do not exit! */ } /* Allocate and init semaphores */ appPriv->cameraSourceEventSem = malloc(sizeof(tsem_t)); if (appPriv->cameraSourceEventSem == NULL) { DEBUG(DEB_LEV_ERR, "Allocate camera event semaphore failed!Exiting...\n"); err = OMX_ErrorInsufficientResources; goto EXIT; } tsem_init(appPriv->cameraSourceEventSem, 0); appPriv->fbsinkEventSem = malloc(sizeof(tsem_t)); if (appPriv->fbsinkEventSem == NULL) { DEBUG(DEB_LEV_ERR, "Allocate fbsink event semaphore failed!Exiting...\n"); err = OMX_ErrorInsufficientResources; goto EXIT; } tsem_init(appPriv->fbsinkEventSem, 0); appPriv->colorconvEventSem = malloc(sizeof(tsem_t)); if (appPriv->colorconvEventSem == NULL) { DEBUG(DEB_LEV_ERR, "Allocate colorconv event semaphore failed!Exiting...\n"); err = OMX_ErrorInsufficientResources; goto EXIT; } tsem_init(appPriv->colorconvEventSem, 0); /* Setup tunnel between camera preview port, color converter and fbsink */ if ((err = OMX_SetupTunnel(appPriv->camerahandle, OMX_CAMPORT_INDEX_VF, appPriv->colorconvhandle, 0)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Setup tunnel between camera preview port and color converter failed!Exiting...\n"); goto EXIT; } if ((err = OMX_SetupTunnel(appPriv->colorconvhandle, 1, appPriv->fbsinkhandle, 0)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Setup tunnel between color conv port and fbsink failed!Exiting...\n"); goto EXIT; } RUN_AGAIN: /* Transition camera component Loaded-->Idle */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Loaded-->Idle failed!Exiting...\n"); goto EXIT; } /* Transition color conv component Loaded-->Idle */ if ((err = OMX_SendCommand(appPriv->colorconvhandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Color Conv Loaded-->Idle failed!Exiting...\n"); goto EXIT; } /* Transition fbsink component Loaded-->Idle */ if ((err = OMX_SendCommand(appPriv->fbsinkhandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fbsink Loaded-->Idle failed!Exiting...\n"); goto EXIT; } /* Allocate port buffers for camera component */ for (nPortIndex = OMX_CAMPORT_INDEX_CP; nPortIndex <= OMX_CAMPORT_INDEX_CP_T; nPortIndex++) { setHeader(&sOmxPortDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); sOmxPortDefinition.nPortIndex = nPortIndex; if ((err = OMX_GetParameter(appPriv->camerahandle, OMX_IndexParamPortDefinition, &sOmxPortDefinition)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "OMX_GetParameter for camera on OMX_IndexParamPortDefinition index failed!Exiting...\n"); goto EXIT; } nBufferCount = sOmxPortDefinition.nBufferCountActual; nBufferSize = sOmxPortDefinition.nBufferSize; DEBUG(DEB_LEV_SIMPLE_SEQ, "Camera port[%ld] needs %ld buffers each of which is %ld bytes\n", nPortIndex, nBufferCount, nBufferSize); for (i = 0; i < nBufferCount; i++) { if ((err = OMX_AllocateBuffer(appPriv->camerahandle, &sCameraPortBufferList[nPortIndex].pBufHeaderList[i], nPortIndex, NULL, nBufferSize)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Allocate port buffer for camera failed!Exiting...\n"); goto EXIT; } sCameraPortBufferList[nPortIndex].nBufferCountActual++; } } /* Wait camera (Loaded-->Idle) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Wait fbsink (Loaded-->Idle) to complete */ tsem_down(appPriv->colorconvEventSem); /* Wait fbsink (Loaded-->Idle) to complete */ tsem_down(appPriv->fbsinkEventSem); /* Transition camera component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Transition color conv component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->colorconvhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Colorconv Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Transition fbsink component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->fbsinkhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fbsink Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Wait camera (Idle-->Exec) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Wait color conv (Idle-->Exec) to complete */ tsem_down(appPriv->colorconvEventSem); /* Wait fbsink (Idle-->Exec) to complete */ tsem_down(appPriv->fbsinkEventSem); fprintf(stdout, "Start preview, for %d sec...\n", nPreviewTime); sleep(nPreviewTime); /* Fill buffers to camera capture port */ for (i = 0; i < sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].nBufferCountActual; i++) { sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]->nFilledLen = 0; sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]->nOffset = 0; if ((err = OMX_FillThisBuffer(appPriv->camerahandle, sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i])) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fill buffer to camera capture port failed!Exiting...\n"); goto EXIT; } DEBUG(DEB_LEV_SIMPLE_SEQ, "%s: Fill buffer[%ld] (0x%lX) to camera capture port\n", __func__, i, (OMX_U32)sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]); } /* Fill buffers to camera thumbnail port */ for (i = 0; i < sCameraPortBufferList[OMX_CAMPORT_INDEX_CP_T].nBufferCountActual; i++) { sCameraPortBufferList[OMX_CAMPORT_INDEX_CP_T].pBufHeaderList[i]->nFilledLen = 0; sCameraPortBufferList[OMX_CAMPORT_INDEX_CP_T].pBufHeaderList[i]->nOffset = 0; if ((err = OMX_FillThisBuffer(appPriv->camerahandle, sCameraPortBufferList[OMX_CAMPORT_INDEX_CP_T].pBufHeaderList[i])) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fill buffer to camera capture port failed!Exiting...\n"); goto EXIT; } DEBUG(DEB_LEV_SIMPLE_SEQ, "%s: Fill buffer[%ld] (0x%lX) to camera capture port\n", __func__, i, (OMX_U32)sCameraPortBufferList[OMX_CAMPORT_INDEX_CP_T].pBufHeaderList[i]); } /* Set up autopause mode */ setHeader(&sOmxAutoPause, sizeof(OMX_CONFIG_BOOLEANTYPE)); sOmxAutoPause.bEnabled = bCameraAutoPause; if ((err = OMX_SetConfig(appPriv->camerahandle, OMX_IndexAutoPauseAfterCapture, &sOmxAutoPause)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set autopause mode failed!Use default settings...\n"); /* Do not exit */ } /* Start capturing */ setHeader(&sOmxCapturing, sizeof(OMX_CONFIG_BOOLEANTYPE)); sOmxCapturing.bEnabled = OMX_TRUE; if ((err = OMX_SetConfig(appPriv->camerahandle, OMX_IndexConfigCapturing, &sOmxCapturing)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Start capturing failed!Exiting...\n"); goto EXIT; } fprintf(stdout, "Start capturing, for %d sec...\n", nCaptureTime); sleep(nCaptureTime); /* Stop capturing */ if (!bCameraStillImageMode) { setHeader(&sOmxCapturing, sizeof(OMX_CONFIG_BOOLEANTYPE)); sOmxCapturing.bEnabled = OMX_FALSE; if ((err = OMX_SetConfig(appPriv->camerahandle, OMX_IndexConfigCapturing, &sOmxCapturing)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Stop capturing failed!Exiting...\n"); goto EXIT; } fprintf(stdout, "Stop capturing...\n"); } /* If in autopause mode, stay for a while before exit */ if (bCameraAutoPause) { fprintf(stdout, "Now the camera is in autopause mode, wait for %d sec before out of this mode...\n", 5); sleep(5); /* Stop autopause mode */ if ((err = OMX_GetState(appPriv->camerahandle,&sOmxState)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Get camera state failed!Exiting...\n"); goto EXIT; } if (sOmxState == OMX_StatePause) { if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateExecuting, 0 )) != OMX_ErrorNone ) { DEBUG(DEB_LEV_ERR, "Pause-->Exec failed!Exiting...\n"); goto EXIT; } /* Wait camera (Pause-->Exec) to complete */ tsem_down(appPriv->cameraSourceEventSem); fprintf(stdout, "Now the camera is out of autopause mode, wait for %d sec before exit...\n", 5); sleep(5); } else { DEBUG(DEB_LEV_ERR, "The camera is not in Pause state in autopause mode, ignore...\n"); } } /* Transition camera component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Transition colorconv component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->colorconvhandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Color conv Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Transition fbsink component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->fbsinkhandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fbsink Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Wait camera (Exec-->Idle) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Wait color conv (Exec-->Idle) to complete */ tsem_down(appPriv->colorconvEventSem); /* Wait fbsink (Exec-->Idle) to complete */ tsem_down(appPriv->fbsinkEventSem); /* Transition camera component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Transition color conv component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->colorconvhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Colorconv Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Transition fbsink component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->fbsinkhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fbsink Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Wait camera (Idle-->Exec) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Wait color conv (Exec-->Idle) to complete */ tsem_down(appPriv->colorconvEventSem); /* Wait fbsink (Idle-->Exec) to complete */ tsem_down(appPriv->fbsinkEventSem); fprintf(stdout, "Continue to preview, for %d sec...\n", nPreviewTime); sleep(nPreviewTime); /* Transition camera component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Transition color conv component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->colorconvhandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Color conv Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Transition fbsink component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->fbsinkhandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fbsink Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Wait camera (Exec-->Idle) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Wait color conv (Exec-->Idle) to complete */ tsem_down(appPriv->colorconvEventSem); /* Wait fbsink (Exec-->Idle) to complete */ tsem_down(appPriv->fbsinkEventSem); /* Transition camera component Idle-->Loaded */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateLoaded, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Idle-->Loaded failed!Exiting...\n"); goto EXIT; } /* Transition color conv component Idle-->Loaded */ if ((err = OMX_SendCommand(appPriv->colorconvhandle, OMX_CommandStateSet, OMX_StateLoaded, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Color conv Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Transition fbsink component Idle-->Loaded */ if ((err = OMX_SendCommand(appPriv->fbsinkhandle, OMX_CommandStateSet, OMX_StateLoaded, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fbsink Idle-->Loaded failed!Exiting...\n"); goto EXIT; } /* Free bufers for each non-tunneled port of camera component */ for (nPortIndex = OMX_CAMPORT_INDEX_CP; nPortIndex <= OMX_CAMPORT_INDEX_CP_T; nPortIndex++) { for (i = 0; i < sCameraPortBufferList[nPortIndex].nBufferCountActual; i++) { if (sCameraPortBufferList[nPortIndex].pBufHeaderList[i] != NULL) { OMX_FreeBuffer(appPriv->camerahandle, nPortIndex, sCameraPortBufferList[nPortIndex].pBufHeaderList[i]); } } sCameraPortBufferList[nPortIndex].nBufferCountActual = 0; } /* Wait camera (Idle-->Loaded) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Wait color conv (Exec-->Idle) to complete */ tsem_down(appPriv->colorconvEventSem); /* Wait fbsink (Idle-->Loaded) to complete */ tsem_down(appPriv->fbsinkEventSem); nRunCount++; if (nRunCount < nMaxRunCount) { goto RUN_AGAIN; } fprintf(stdout, "The captured videos are saved in file \"%s\"\n", cCaptureFileName); fprintf(stdout, "The thumbnail image is saved in file \"%s\"\n", cThumbnailFileName); EXIT: if (fCapture != NULL) { fclose(fCapture); } if (fThumbnail != NULL) { fclose(fThumbnail); } /* Free app private data */ if (appPriv != NULL) { /* Free semaphores */ if (appPriv->cameraSourceEventSem != NULL) { tsem_deinit(appPriv->cameraSourceEventSem); free(appPriv->cameraSourceEventSem); } if (appPriv->colorconvEventSem != NULL) { tsem_deinit(appPriv->colorconvEventSem); free(appPriv->colorconvEventSem); } if (appPriv->fbsinkEventSem != NULL) { tsem_deinit(appPriv->fbsinkEventSem); free(appPriv->fbsinkEventSem); } /* Free camera component handle */ if (appPriv->camerahandle != NULL) { OMX_FreeHandle(appPriv->camerahandle); } /* Free Color conv component handle */ if (appPriv->colorconvhandle != NULL) { OMX_FreeHandle(appPriv->colorconvhandle); } /* Free fbsink component handle */ if (appPriv->fbsinkhandle != NULL) { OMX_FreeHandle(appPriv->fbsinkhandle); } free(appPriv); } /* Deinit the Omx core */ if (bOmxInitialized) { OMX_Deinit(); } return (int) err; }
int main(int argc, char** argv) { OMX_ERRORTYPE err; int argn_dec; OMX_STRING full_component_name; if(argc < 2){ display_help(); } else { flagIsOutputExpected = 0; argn_dec = 1; while (argn_dec < argc) { if (*(argv[argn_dec]) == '-') { if (flagIsOutputExpected) { display_help(); } switch (*(argv[argn_dec] + 1)) { case 'h' : display_help(); break; case 'o': flagIsOutputExpected = 1; break; default: display_help(); } } else { if (flagIsOutputExpected) { if(strstr(argv[argn_dec], ".yuv") == NULL && strstr(argv[argn_dec], ".rgb") == NULL) { output_file = malloc(strlen(argv[argn_dec]) * sizeof(char) + 5); strcpy(output_file,argv[argn_dec]); strcat(output_file, ".rgb"); } else { output_file = malloc(strlen(argv[argn_dec]) * sizeof(char) + 1); strcpy(output_file,argv[argn_dec]); } flagIsOutputExpected = 0; } } argn_dec++; } } if(output_file==NULL) { output_file = malloc(30); strcpy(output_file,"default_camera_out.rgb"); } outfile = fopen(output_file, "wb"); if(outfile == NULL) { DEBUG(DEB_LEV_ERR, "Error in opening output file %s\n", output_file); exit(1); } /** setting input picture width to a default value (vga format) for allocation of video videosrc buffers */ out_width = 176; out_height = 144; /* Initialize application private data */ appPriv = malloc(sizeof(appPrivateType)); appPriv->videosrcEventSem = malloc(sizeof(tsem_t)); appPriv->eofSem = malloc(sizeof(tsem_t)); tsem_init(appPriv->videosrcEventSem, 0); tsem_init(appPriv->eofSem, 0); DEBUG(DEB_LEV_SIMPLE_SEQ, "Init the Omx core\n"); err = OMX_Init(); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "The OpenMAX core can not be initialized. Exiting...\n"); exit(1); } else { DEBUG(DEB_LEV_SIMPLE_SEQ, "Omx core is initialized \n"); } test_OpenClose(COMPONENT_NAME); DEBUG(DEFAULT_MESSAGES, "------------------------------------\n"); full_component_name = (OMX_STRING) malloc(sizeof(char*) * OMX_MAX_STRINGNAME_SIZE); strcpy(full_component_name, COMPONENT_NAME); DEBUG(DEFAULT_MESSAGES, "The component selected for capturing is %s\n", full_component_name); /** getting video videosrc handle */ err = OMX_GetHandle(&appPriv->videosrchandle, full_component_name, NULL, &videosrccallbacks); if(err != OMX_ErrorNone){ DEBUG(DEB_LEV_ERR, "No video videosrc component found. Exiting...\n"); exit(1); } else { DEBUG(DEFAULT_MESSAGES, "Found The component for capturing is %s\n", full_component_name); } /** output buffer size calculation based on input dimension speculation */ buffer_out_size = out_width * out_height * 3; //yuv420 format -- bpp = 12 DEBUG(DEB_LEV_SIMPLE_SEQ, "\n buffer_out_size : %d \n", (int)buffer_out_size); /** sending command to video videosrc component to go to idle state */ err = OMX_SendCommand(appPriv->videosrchandle, OMX_CommandStateSet, OMX_StateIdle, NULL); pOutBuffer1 = pOutBuffer2 = NULL; err = OMX_AllocateBuffer(appPriv->videosrchandle, &pOutBuffer1, 0, NULL, buffer_out_size); err = OMX_AllocateBuffer(appPriv->videosrchandle, &pOutBuffer2, 0, NULL, buffer_out_size); DEBUG(DEB_LEV_SIMPLE_SEQ, "Before locking on idle wait semaphore\n"); tsem_down(appPriv->videosrcEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "videosrc Sem free\n"); /** sending command to video videosrc component to go to executing state */ err = OMX_SendCommand(appPriv->videosrchandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); tsem_down(appPriv->videosrcEventSem); err = OMX_FillThisBuffer(appPriv->videosrchandle, pOutBuffer1); err = OMX_FillThisBuffer(appPriv->videosrchandle, pOutBuffer2); DEBUG(DEFAULT_MESSAGES,"Waiting for EOS\n"); /*Capture video for 10 seconds*/ sleep(10); bEOS = OMX_TRUE; DEBUG(DEFAULT_MESSAGES,"Set EOS\n"); sleep(1); //tsem_down(appPriv->eofSem); DEBUG(DEFAULT_MESSAGES, "The execution of the video capturing process is terminated\n"); /** state change of all components from executing to idle */ err = OMX_SendCommand(appPriv->videosrchandle, OMX_CommandStateSet, OMX_StateIdle, NULL); tsem_down(appPriv->videosrcEventSem); DEBUG(DEFAULT_MESSAGES, "All video components Transitioned to Idle\n"); /** sending command to all components to go to loaded state */ err = OMX_SendCommand(appPriv->videosrchandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); /** freeing buffers of video videosrc input ports */ DEBUG(DEB_LEV_PARAMS, "Free Video dec output ports\n"); err = OMX_FreeBuffer(appPriv->videosrchandle, 0, pOutBuffer1); err = OMX_FreeBuffer(appPriv->videosrchandle, 0, pOutBuffer2); tsem_down(appPriv->videosrcEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "All components released\n"); OMX_FreeHandle(appPriv->videosrchandle); DEBUG(DEB_LEV_SIMPLE_SEQ, "video dec freed\n"); OMX_Deinit(); DEBUG(DEFAULT_MESSAGES, "All components freed. Closing...\n"); free(appPriv->videosrcEventSem); free(appPriv->eofSem); free(appPriv); /** closing the output file */ fclose(outfile); return 0; }
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; }
/** 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; }
int useBufTest() { OMX_ERRORTYPE err = OMX_ErrorNone; OMX_BOOL bOmxInitialized = OMX_FALSE; OMX_PARAM_PORTDEFINITIONTYPE sOmxPortDefinition; OMX_CONFIG_BOOLEANTYPE sOmxCapturing; OMX_CONFIG_BOOLEANTYPE sOmxAutoPause; OMX_STATETYPE sOmxState; OMX_U32 nBufferCount; OMX_U32 nBufferSize; OMX_U32 nPortIndex; OMX_U32 i; unsigned int nPreviewTime = 5;/* By default, running for 5 sec for preview */ unsigned int nCaptureTime = 5;/* By default, running for 5 sec for video capture */ OMX_BOOL bCameraStillImageMode = OMX_FALSE; /* By default, the camera is running in video capture mode */ OMX_BOOL bCameraAutoPause = OMX_FALSE; /* By default, the camera is not running in autopause mode */ unsigned int nMaxRunCount = 1;/* By default, running once */ unsigned int nRunCount = 0; OMX_U8 *buf = NULL; surface_display_main_init(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT); /* Init the Omx core */ DEBUG(DEB_LEV_SIMPLE_SEQ, "Init the OMX core\n"); if ((err = OMX_Init()) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "The OpenMAX core can not be initialized. Exiting...\n"); goto EXIT; } bOmxInitialized = OMX_TRUE; /* Initialize application private data */ appPriv = malloc(sizeof(appPrivateType)); if (appPriv == NULL) { DEBUG(DEB_LEV_ERR, "Allocate app private data failed!Exiting...\n"); err = OMX_ErrorInsufficientResources; goto EXIT; } memset(appPriv, 0, sizeof(appPrivateType)); memset(&sCameraPortBufferList, 0, NUM_CAMERAPORTS * sizeof(OMX_PORTBUFFERCTXT)); /* Getting camera component handle */ if ((err = OMX_GetHandle(&appPriv->camerahandle, "OMX.Action.Camera.Yuv", appPriv, &camera_source_callbacks)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Getting camera component handle failed!Exiting...\n"); goto EXIT; } /* Setting parameters for camera component */ if ((err = setCameraParameters(bCameraStillImageMode)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set camera parameters failed! Use default settings...\n"); /* Do not exit! */ } /* Allocate and init semaphores */ appPriv->cameraSourceEventSem = malloc(sizeof(tsem_t)); if (appPriv->cameraSourceEventSem == NULL) { DEBUG(DEB_LEV_ERR, "Allocate camera event semaphore failed!Exiting...\n"); err = OMX_ErrorInsufficientResources; goto EXIT; } tsem_init(appPriv->cameraSourceEventSem, 0); RUN_AGAIN: for (nPortIndex = OMX_CAMPORT_INDEX_VF; nPortIndex <= OMX_CAMPORT_INDEX_CP; nPortIndex++) { if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandPortEnable, nPortIndex, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Idle-->Exec failed!Exiting...\n"); goto EXIT; } tsem_down(appPriv->cameraSourceEventSem); } /* Transition camera component Loaded-->Idle */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Loaded-->Idle failed!Exiting...\n"); goto EXIT; } /* Allocate port buffers for camera component */ for (nPortIndex = OMX_CAMPORT_INDEX_VF; nPortIndex <= OMX_CAMPORT_INDEX_CP; nPortIndex++) { setHeader(&sOmxPortDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); sOmxPortDefinition.nPortIndex = nPortIndex; if ((err = OMX_GetParameter(appPriv->camerahandle, OMX_IndexParamPortDefinition, &sOmxPortDefinition)) != OMX_ErrorNone) { DEBUG( DEB_LEV_ERR, "OMX_GetParameter for camera on OMX_IndexParamPortDefinition index failed!Exiting...\n"); goto EXIT; } nBufferCount = sOmxPortDefinition.nBufferCountActual; nBufferSize = sOmxPortDefinition.nBufferSize; DEBUG( DEB_LEV_SIMPLE_SEQ, "Camera port[%ld] needs %ld buffers each of which is %ld bytes\n", nPortIndex, nBufferCount, nBufferSize); for (i = 0; i < nBufferCount; i++) { buf = (OMX_U8 *)malloc(nBufferSize); if(buf == NULL){ DEBUG(DEB_LEV_ERR, "Allocate port buffer for camera failed!Exiting...\n"); goto EXIT; } if ((err = OMX_UseBuffer(appPriv->camerahandle, &sCameraPortBufferList[nPortIndex].pBufHeaderList[i], nPortIndex, NULL, nBufferSize, buf)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Allocate port buffer for camera failed!Exiting...\n"); goto EXIT; } sCameraPortBufferList[nPortIndex].nBufferCountActual++; } } /* Wait camera (Loaded-->Idle) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Transition camera component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Wait camera (Idle-->Exec) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Fill buffers to camera preview port */ for (i = 0; i < sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].nBufferCountActual; i++) { sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i]->nFilledLen = 0; sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i]->nOffset = 0; if ((err = OMX_FillThisBuffer(appPriv->camerahandle, sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i])) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fill buffer to camera capture port failed!Exiting...\n"); goto EXIT; } DEBUG( DEB_LEV_SIMPLE_SEQ, "%s: Fill buffer[%ld] (0x%lX) to camera capture port\n", __func__, i, (OMX_U32) sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i]); } /* Fill buffers to camera capture port */ for (i = 0; i < sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].nBufferCountActual; i++) { sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]->nFilledLen = 0; sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]->nOffset = 0; if ((err = OMX_FillThisBuffer(appPriv->camerahandle, sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i])) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fill buffer to camera capture port failed!Exiting...\n"); goto EXIT; } DEBUG( DEB_LEV_SIMPLE_SEQ, "%s: Fill buffer[%ld] (0x%lX) to camera capture port\n", __func__, i, (OMX_U32) sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]); } fprintf(stdout, "Start preview, for %d sec...\n", nPreviewTime); sleep(nPreviewTime); /* Set up autopause mode */ setHeader(&sOmxAutoPause, sizeof(OMX_CONFIG_BOOLEANTYPE)); sOmxAutoPause.bEnabled = bCameraAutoPause; if ((err = OMX_SetConfig(appPriv->camerahandle, OMX_IndexAutoPauseAfterCapture, &sOmxAutoPause)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set autopause mode failed!Use default settings...\n"); /* Do not exit */ } /* Start capturing */ setHeader(&sOmxCapturing, sizeof(OMX_CONFIG_BOOLEANTYPE)); sOmxCapturing.bEnabled = OMX_TRUE; if ((err = OMX_SetConfig(appPriv->camerahandle, OMX_IndexConfigCapturing, &sOmxCapturing)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Start capturing failed!Exiting...\n"); goto EXIT; } fprintf(stdout, "Start capturing, for %d sec...\n", nCaptureTime); sleep(nCaptureTime); /* Stop capturing */ if (!bCameraStillImageMode) { setHeader(&sOmxCapturing, sizeof(OMX_CONFIG_BOOLEANTYPE)); sOmxCapturing.bEnabled = OMX_FALSE; if ((err = OMX_SetConfig(appPriv->camerahandle, OMX_IndexConfigCapturing, &sOmxCapturing)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Stop capturing failed!Exiting...\n"); goto EXIT; } fprintf(stdout, "Stop capturing...\n"); } /* If in autopause mode, stay for a while before exit */ if (bCameraAutoPause) { fprintf( stdout,"pause state for capture, sleep(%d)\n",5); sleep(5); /* Stop autopause mode */ if ((err = OMX_GetState(appPriv->camerahandle, &sOmxState)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Get camera state failed!Exiting...\n"); goto EXIT; } if (sOmxState == OMX_StatePause) { if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateExecuting, 0)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Pause-->Exec failed!Exiting...\n"); goto EXIT; } /* Wait camera (Pause-->Exec) to complete */ tsem_down(appPriv->cameraSourceEventSem); fprintf( stdout, "Now the camera is out of autopause mode, wait for %d sec before exit...\n", 5); sleep(5); } else { DEBUG(DEB_LEV_ERR, "The camera is not in Pause state in autopause mode, ignore...\n"); } } #if 1 /* Transition camera component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Wait camera (Exec-->Idle) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Transition camera component Idle-->Exec */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Idle-->Exec failed!Exiting...\n"); goto EXIT; } /* Wait camera (Idle-->Exec) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Fill buffers to camera preview port */ for (i = 0; i < sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].nBufferCountActual; i++) { sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i]->nFilledLen = 0; sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i]->nOffset = 0; if ((err = OMX_FillThisBuffer(appPriv->camerahandle, sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i])) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fill buffer to camera capture port failed!Exiting...\n"); goto EXIT; } DEBUG( DEB_LEV_SIMPLE_SEQ, "%s: Fill buffer[%ld] (0x%lX) to camera capture port\n", __func__, i, (OMX_U32) sCameraPortBufferList[OMX_CAMPORT_INDEX_VF].pBufHeaderList[i]); } /* Fill buffers to camera capture port */ for (i = 0; i < sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].nBufferCountActual; i++) { sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]->nFilledLen = 0; sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]->nOffset = 0; if ((err = OMX_FillThisBuffer(appPriv->camerahandle, sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i])) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Fill buffer to camera capture port failed!Exiting...\n"); goto EXIT; } DEBUG( DEB_LEV_SIMPLE_SEQ, "%s: Fill buffer[%ld] (0x%lX) to camera capture port\n", __func__, i, (OMX_U32) sCameraPortBufferList[OMX_CAMPORT_INDEX_CP].pBufHeaderList[i]); } fprintf(stdout, "Continue to preview, for %d sec...\n", nPreviewTime); sleep(nPreviewTime); #endif /* Transition camera component Exec-->Idle */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Exec-->Idle failed!Exiting...\n"); goto EXIT; } /* Wait camera (Exec-->Idle) to complete */ tsem_down(appPriv->cameraSourceEventSem); /* Transition camera component Idle-->Loaded */ if ((err = OMX_SendCommand(appPriv->camerahandle, OMX_CommandStateSet, OMX_StateLoaded, NULL)) != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Camera Idle-->Loaded failed!Exiting...\n"); goto EXIT; } #if 1 /* Free bufers for each non-tunneled port of camera component */ for (nPortIndex = OMX_CAMPORT_INDEX_VF; nPortIndex <= OMX_CAMPORT_INDEX_CP; nPortIndex++) { for (i = 0; i < sCameraPortBufferList[nPortIndex].nBufferCountActual; i++) { if (sCameraPortBufferList[nPortIndex].pBufHeaderList[i] != NULL) { buf = sCameraPortBufferList[nPortIndex].pBufHeaderList[i]->pBuffer; OMX_FreeBuffer(appPriv->camerahandle, nPortIndex, sCameraPortBufferList[nPortIndex].pBufHeaderList[i]); if(buf){ free(buf); } sCameraPortBufferList[nPortIndex].pBufHeaderList[i]=NULL; } } sCameraPortBufferList[nPortIndex].nBufferCountActual = 0; } #endif /* Wait camera (Idle-->Loaded) to complete */ tsem_down(appPriv->cameraSourceEventSem); nRunCount++; if (nRunCount < nMaxRunCount) { goto RUN_AGAIN; } EXIT: for (nPortIndex = OMX_CAMPORT_INDEX_VF; nPortIndex <= OMX_CAMPORT_INDEX_CP; nPortIndex++) { for (i = 0; i < sCameraPortBufferList[nPortIndex].nBufferCountActual; i++) { if (sCameraPortBufferList[nPortIndex].pBufHeaderList[i] != NULL) { buf = sCameraPortBufferList[nPortIndex].pBufHeaderList[i]->pBuffer; OMX_FreeBuffer(appPriv->camerahandle, nPortIndex, sCameraPortBufferList[nPortIndex].pBufHeaderList[i]); if(buf){ free(buf); } sCameraPortBufferList[nPortIndex].pBufHeaderList[i]=NULL; } } sCameraPortBufferList[nPortIndex].nBufferCountActual = 0; } /* Free app private data */ if (appPriv != NULL) { /* Free semaphores */ if (appPriv->cameraSourceEventSem != NULL) { tsem_deinit(appPriv->cameraSourceEventSem); free(appPriv->cameraSourceEventSem); } /* Free camera component handle */ if (appPriv->camerahandle != NULL) { OMX_FreeHandle(appPriv->camerahandle); } free(appPriv); } /* Deinit the Omx core */ if (bOmxInitialized) { OMX_Deinit(); } return (int) err; }
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; }
int main(int argc, char** argv) { OMX_ERRORTYPE err; int argn_dec; OMX_STRING full_component_name; int isRate=0,isChannel=0; OMX_AUDIO_PARAM_PCMMODETYPE sPCMModeParam; if(argc < 2) { display_help(); } else { flagIsOutputExpected = 0; flagDecodedOutputReceived = 0; flagIsVolCompRequested = 0; flagSetupTunnel = 0; flagIsSinkRequested = 0; argn_dec = 1; while (argn_dec < argc) { if (*(argv[argn_dec]) == '-') { if (flagIsOutputExpected) { display_help(); } switch (*(argv[argn_dec] + 1)) { case 'h' : display_help(); break; case 't' : flagSetupTunnel = 1; flagIsSinkRequested = 1; flagIsVolCompRequested = 1; break; case 's': flagIsSinkRequested = 1; break; case 'o': flagIsOutputExpected = 1; break; case 'v': flagIsVolCompRequested = 1; break; case 'r' : isRate = 1; break; case 'n' : isChannel = 1; break; default: display_help(); } } else { if (flagIsOutputExpected) { if(strstr(argv[argn_dec], ".pcm") == NULL) { output_file = malloc(strlen(argv[argn_dec]) + 5); strcpy(output_file,argv[argn_dec]); strcat(output_file, ".pcm"); } else { output_file = malloc(strlen(argv[argn_dec]) + 1); strcpy(output_file,argv[argn_dec]); } flagIsOutputExpected = 0; flagDecodedOutputReceived = 1; } else if(isRate) { rate=atoi(argv[argn_dec]); isRate=0; if(rate <0 || rate >48000) { DEBUG(DEB_LEV_ERR, "Bad Parameter rate\n"); display_help(); } } else if(isChannel) { channel=atoi(argv[argn_dec]); isChannel = 0; if(channel <0 || channel >6) { DEBUG(DEB_LEV_ERR, "Bad Parameter channel\n"); display_help(); } } } argn_dec++; } /** if volume componenterter component is not selected then sink component will not work, even if specified */ if(!flagIsVolCompRequested && flagIsSinkRequested) { DEBUG(DEB_LEV_ERR, "You requested for sink - not producing any output file\n"); flagIsVolCompRequested = 1; flagDecodedOutputReceived = 0; } /** output file name check */ //case 1 - user did not specify any output file if(!flagIsOutputExpected && !flagDecodedOutputReceived && !flagIsSinkRequested) { DEBUG(DEB_LEV_ERR,"\n you did not enter any output file name"); output_file = malloc(20); strcpy(output_file,"output.pcm"); DEBUG(DEB_LEV_ERR,"\n the decoded output file name will be %s \n", output_file); } else if(flagDecodedOutputReceived) { if(flagIsSinkRequested || flagSetupTunnel) { flagDecodedOutputReceived = 0; DEBUG(DEB_LEV_ERR, "Sink Requested or Components are tunneled. No FILE Output will be produced\n"); } else { //case 2 - user has given wrong format if(flagIsVolCompRequested && strstr(output_file, ".pcm") == NULL) { output_file[strlen(output_file) - strlen(strstr(output_file, "."))] = '\0'; strcat(output_file, ".rgb"); DEBUG(DEB_LEV_ERR,"\n volume component option is selected - so the output file is %s \n", output_file); } } } if(flagSetupTunnel) { DEBUG(DEFAULT_MESSAGES,"The components are tunneled between themselves\n"); } } if(!flagIsSinkRequested) { outfile = fopen(output_file, "wb"); if(outfile == NULL) { DEBUG(DEB_LEV_ERR, "Error in opening output file %s\n", output_file); exit(1); } } /* Initialize application private data */ appPriv = malloc(sizeof(appPrivateType)); appPriv->sourceEventSem = malloc(sizeof(tsem_t)); if(flagIsVolCompRequested == 1) { if(flagIsSinkRequested == 1) { appPriv->alsasinkEventSem = malloc(sizeof(tsem_t)); } appPriv->volumeEventSem = malloc(sizeof(tsem_t)); } appPriv->eofSem = malloc(sizeof(tsem_t)); tsem_init(appPriv->sourceEventSem, 0); if(flagIsVolCompRequested == 1) { if(flagIsSinkRequested == 1) { tsem_init(appPriv->alsasinkEventSem, 0); } tsem_init(appPriv->volumeEventSem, 0); } tsem_init(appPriv->eofSem, 0); DEBUG(DEB_LEV_SIMPLE_SEQ, "Init the Omx core\n"); err = OMX_Init(); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "The OpenMAX core can not be initialized. Exiting...\n"); exit(1); } else { DEBUG(DEB_LEV_SIMPLE_SEQ, "Omx core is initialized \n"); } DEBUG(DEFAULT_MESSAGES, "------------------------------------\n"); test_OMX_ComponentNameEnum(); DEBUG(DEFAULT_MESSAGES, "------------------------------------\n"); test_OMX_RoleEnum(COMPONENT_NAME_BASE); DEBUG(DEFAULT_MESSAGES, "------------------------------------\n"); test_OMX_ComponentEnumByRole(BASE_ROLE); DEBUG(DEFAULT_MESSAGES, "------------------------------------\n"); test_OpenClose(COMPONENT_NAME_BASE); DEBUG(DEFAULT_MESSAGES, "------------------------------------\n"); full_component_name = malloc(OMX_MAX_STRINGNAME_SIZE); strcpy(full_component_name, "OMX.st.alsa.alsasrc"); DEBUG(DEFAULT_MESSAGES, "The component selected for decoding is %s\n", full_component_name); /** getting audio source handle */ err = OMX_GetHandle(&appPriv->audiosrchandle, full_component_name, NULL, &audiosrccallbacks); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "No audio source component found. Exiting...\n"); exit(1); } else { DEBUG(DEFAULT_MESSAGES, "Found The component for capturing is %s\n", full_component_name); } /** getting volume componenterter component handle, if specified */ if(flagIsVolCompRequested == 1) { err = OMX_GetHandle(&appPriv->volume_handle, "OMX.st.volume.component", NULL, &volume_callbacks); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "No volume componenterter component found. Exiting...\n"); exit(1); } else { DEBUG(DEFAULT_MESSAGES, "Found The component for volume componenterter \n"); } /** getting sink component handle - if reqd' */ if(flagIsSinkRequested == 1) { err = OMX_GetHandle(&appPriv->alsasink_handle, "OMX.st.alsa.alsasink", NULL, &alsasink_callbacks); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "No audio sink component component found. Exiting...\n"); exit(1); } else { DEBUG(DEFAULT_MESSAGES, "Found The audio sink component for volume componenterter \n"); } } } if(rate >0 || channel >0) { setHeader(&sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); err = OMX_GetParameter(appPriv->audiosrchandle,OMX_IndexParamAudioPcm,&sPCMModeParam); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Err in GetParameter OMX_AUDIO_PARAM_PCMMODETYPE in AlsaSrc. Exiting...\n"); exit(1); } sPCMModeParam.nChannels = (channel >0 ) ? channel:sPCMModeParam.nChannels; sPCMModeParam.nSamplingRate = (rate >0 ) ? rate:sPCMModeParam.nSamplingRate; err = OMX_SetParameter(appPriv->audiosrchandle,OMX_IndexParamAudioPcm,&sPCMModeParam); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Err in SetParameter OMX_AUDIO_PARAM_PCMMODETYPE in AlsaSrc. Exiting...\n"); exit(1); } if(flagIsSinkRequested) { err = OMX_SetParameter(appPriv->alsasink_handle,OMX_IndexParamAudioPcm,&sPCMModeParam); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Err in SetParameter OMX_AUDIO_PARAM_PCMMODETYPE in AlsaSink. Exiting...\n"); exit(1); } } } else if(flagIsSinkRequested) { setHeader(&sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); err = OMX_GetParameter(appPriv->audiosrchandle,OMX_IndexParamAudioPcm,&sPCMModeParam); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Err in GetParameter OMX_AUDIO_PARAM_PCMMODETYPE in AlsaSrc. Exiting...\n"); exit(1); } err = OMX_SetParameter(appPriv->alsasink_handle,OMX_IndexParamAudioPcm,&sPCMModeParam); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Err in SetParameter OMX_AUDIO_PARAM_PCMMODETYPE in AlsaSink. Exiting...\n"); exit(1); } } /** output buffer size calculation based on input dimension speculation */ DEBUG(DEB_LEV_SIMPLE_SEQ, "\n buffer_out_size : %d \n", (int)buffer_out_size); /** if tunneling option is given then set up the tunnel between the components */ if (flagSetupTunnel) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Setting up Tunnel\n"); err = OMX_SetupTunnel(appPriv->audiosrchandle, 0, appPriv->volume_handle, 0); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set up Tunnel between audio src & volume component Failed\n"); exit(1); } err = OMX_SetupTunnel(appPriv->volume_handle, 1, appPriv->alsasink_handle, 0); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set up Tunnel between volume component & audio sink Failed\n"); exit(1); } DEBUG(DEFAULT_MESSAGES, "Set up Tunnel Completed\n"); } /** sending command to audio source component to go to idle state */ err = OMX_SendCommand(appPriv->audiosrchandle, OMX_CommandStateSet, OMX_StateIdle, NULL); /** in tunnel case, change the volume component and sink comp state to idle */ if(flagIsVolCompRequested && flagSetupTunnel) { err = OMX_SendCommand(appPriv->volume_handle, OMX_CommandStateSet, OMX_StateIdle, NULL); if(flagIsSinkRequested && flagSetupTunnel) { err = OMX_SendCommand(appPriv->alsasink_handle, OMX_CommandStateSet, OMX_StateIdle, NULL); } } if(flagSetupTunnel) { if(flagIsSinkRequested) { tsem_down(appPriv->alsasinkEventSem); } if(flagIsVolCompRequested) { tsem_down(appPriv->volumeEventSem); } } /** if tunneling option is not given then allocate buffers on audio source output port */ if (!flagSetupTunnel) { pOutBuffer[0] = pOutBuffer[1] = NULL; err = OMX_AllocateBuffer(appPriv->audiosrchandle, &pOutBuffer[0], 0, NULL, buffer_out_size); err = OMX_AllocateBuffer(appPriv->audiosrchandle, &pOutBuffer[1], 0, NULL, buffer_out_size); } DEBUG(DEB_LEV_SIMPLE_SEQ, "Before locking on idle wait semaphore\n"); tsem_down(appPriv->sourceEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "source Sem free\n"); if(!flagSetupTunnel) { if(flagIsVolCompRequested == 1) { pOutBufferVolc[0] = pOutBufferVolc[1] = NULL; err = OMX_SendCommand(appPriv->volume_handle, OMX_CommandStateSet, OMX_StateIdle, NULL); /** in non tunneled case, using buffers in volume component input port, allocated by audio dec component output port */ err = OMX_UseBuffer(appPriv->volume_handle, &pInBufferVolc[0], 0, NULL, buffer_out_size, pOutBuffer[0]->pBuffer); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Unable to use the volume component comp allocate buffer\n"); exit(1); } err = OMX_UseBuffer(appPriv->volume_handle, &pInBufferVolc[1], 0, NULL, buffer_out_size, pOutBuffer[1]->pBuffer); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Unable to use the volume component comp allocate buffer\n"); exit(1); } /** allocating buffers in the volume componenterter compoennt output port */ err = OMX_AllocateBuffer(appPriv->volume_handle, &pOutBufferVolc[0], 1, NULL, buffer_out_size); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Unable to allocate buffer in volume component\n"); exit(1); } err = OMX_AllocateBuffer(appPriv->volume_handle, &pOutBufferVolc[1], 1, NULL, buffer_out_size); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Unable to allocate buffer in colro conv\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ, "Before locking on idle wait semaphore\n"); tsem_down(appPriv->volumeEventSem); DEBUG(DEFAULT_MESSAGES, "volume Event Sem free\n"); if(flagIsSinkRequested == 1) { err = OMX_SendCommand(appPriv->alsasink_handle, OMX_CommandStateSet, OMX_StateIdle, NULL); err = OMX_UseBuffer(appPriv->alsasink_handle, &pInBufferSink[0], 0, NULL, buffer_out_size, pOutBufferVolc[0]->pBuffer); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Unable to use the alsasink_handle comp allocate buffer\n"); exit(1); } err = OMX_UseBuffer(appPriv->alsasink_handle, &pInBufferSink[1], 0, NULL, buffer_out_size, pOutBufferVolc[1]->pBuffer); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Unable to use the alsasink_handle comp allocate buffer\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ, "Before locking on idle wait semaphore\n"); tsem_down(appPriv->alsasinkEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "audio sink comp Sem free\n"); } } if(flagIsVolCompRequested == 1) { err = OMX_SendCommand(appPriv->volume_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); tsem_down(appPriv->volumeEventSem); if(flagIsSinkRequested == 1) { err = OMX_SendCommand(appPriv->alsasink_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); tsem_down(appPriv->alsasinkEventSem); } } } /** send command to change color onv and sink comp in executing state */ if(flagIsVolCompRequested == 1 && flagSetupTunnel) { err = OMX_SendCommand(appPriv->volume_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); tsem_down(appPriv->volumeEventSem); if(flagIsSinkRequested == 1) { err = OMX_SendCommand(appPriv->alsasink_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); tsem_down(appPriv->alsasinkEventSem); } } /** sending command to audio source component to go to executing state */ err = OMX_SendCommand(appPriv->audiosrchandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); tsem_down(appPriv->sourceEventSem); if(flagIsVolCompRequested == 1 && !flagSetupTunnel) { err = OMX_FillThisBuffer(appPriv->volume_handle, pOutBufferVolc[0]); err = OMX_FillThisBuffer(appPriv->volume_handle, pOutBufferVolc[1]); DEBUG(DEFAULT_MESSAGES, "---> After fill this buffer function calls to the volume component output buffers\n"); } if (!flagSetupTunnel) { err = OMX_FillThisBuffer(appPriv->audiosrchandle, pOutBuffer[0]); err = OMX_FillThisBuffer(appPriv->audiosrchandle, pOutBuffer[1]); } DEBUG(DEB_LEV_SIMPLE_SEQ, "---> Before locking on condition and sourceMutex\n"); DEBUG(DEFAULT_MESSAGES,"Enter 'q' or 'Q' to exit\n"); while(1) { if('Q' == toupper(getchar())) { DEBUG(DEFAULT_MESSAGES,"Stoping capture\n"); bEOS = OMX_TRUE; usleep(10000); break; } } DEBUG(DEFAULT_MESSAGES, "The execution of the audio decoding process is terminated\n"); /** state change of all components from executing to idle */ err = OMX_SendCommand(appPriv->audiosrchandle, OMX_CommandStateSet, OMX_StateIdle, NULL); if(flagIsVolCompRequested == 1) { err = OMX_SendCommand(appPriv->volume_handle, OMX_CommandStateSet, OMX_StateIdle, NULL); if(flagIsSinkRequested == 1) { err = OMX_SendCommand(appPriv->alsasink_handle, OMX_CommandStateSet, OMX_StateIdle, NULL); } } tsem_down(appPriv->sourceEventSem); if(flagIsVolCompRequested == 1) { tsem_down(appPriv->volumeEventSem); if(flagIsSinkRequested == 1) { tsem_down(appPriv->alsasinkEventSem); } } DEBUG(DEFAULT_MESSAGES, "All audio components Transitioned to Idle\n"); /** sending command to all components to go to loaded state */ err = OMX_SendCommand(appPriv->audiosrchandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); if(flagIsVolCompRequested == 1) { err = OMX_SendCommand(appPriv->volume_handle, OMX_CommandStateSet, OMX_StateLoaded, NULL); if(flagIsSinkRequested == 1) { err = OMX_SendCommand(appPriv->alsasink_handle, OMX_CommandStateSet, OMX_StateLoaded, NULL); } } /** freeing buffers of volume component and sink component */ if(flagIsVolCompRequested == 1 && !flagSetupTunnel) { DEBUG(DEB_LEV_SIMPLE_SEQ, "volume component to loaded\n"); err = OMX_FreeBuffer(appPriv->volume_handle, 0, pInBufferVolc[0]); err = OMX_FreeBuffer(appPriv->volume_handle, 0, pInBufferVolc[1]); err = OMX_FreeBuffer(appPriv->volume_handle, 1, pOutBufferVolc[0]); err = OMX_FreeBuffer(appPriv->volume_handle, 1, pOutBufferVolc[1]); if(flagIsSinkRequested == 1) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Audio sink to loaded\n"); err = OMX_FreeBuffer(appPriv->alsasink_handle, 0, pInBufferSink[0]); err = OMX_FreeBuffer(appPriv->alsasink_handle, 0, pInBufferSink[1]); } } /** freeing buffers of audio source input ports */ DEBUG(DEB_LEV_SIMPLE_SEQ, "Audio dec to loaded\n"); if(!flagSetupTunnel) { DEBUG(DEB_LEV_PARAMS, "Free Audio dec output ports\n"); err = OMX_FreeBuffer(appPriv->audiosrchandle, 0, pOutBuffer[0]); err = OMX_FreeBuffer(appPriv->audiosrchandle, 0, pOutBuffer[1]); } if(flagIsVolCompRequested == 1) { if(flagIsSinkRequested == 1) { tsem_down(appPriv->alsasinkEventSem); } tsem_down(appPriv->volumeEventSem); } tsem_down(appPriv->sourceEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "All components released\n"); OMX_FreeHandle(appPriv->audiosrchandle); if(flagIsVolCompRequested == 1) { if(flagIsSinkRequested == 1) { OMX_FreeHandle(appPriv->alsasink_handle); } OMX_FreeHandle(appPriv->volume_handle); } DEBUG(DEB_LEV_SIMPLE_SEQ, "audio dec freed\n"); OMX_Deinit(); DEBUG(DEFAULT_MESSAGES, "All components freed. Closing...\n"); free(appPriv->sourceEventSem); if(flagIsVolCompRequested == 1) { if(flagIsSinkRequested == 1) { free(appPriv->alsasinkEventSem); } free(appPriv->volumeEventSem); } free(appPriv->eofSem); free(appPriv); free(full_component_name); /** closing the output file */ if(!flagIsSinkRequested) { fclose(outfile); } if(output_file) { free(output_file); } return 0; }
/** 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; }
int main(int argc, char** argv) { int argn_dec; OMX_ERRORTYPE err; OMX_INDEXTYPE eIndexParamFilename; int gain=-1; OMX_AUDIO_CONFIG_VOLUMETYPE sVolume; OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp; OMX_PARAM_COMPONENTROLETYPE sComponentRole; char *stream_dir=NULL; DIR *dirp; struct dirent *dp; int seek=1; flagSetupTunnel = 1; flagPlaybackOn = 1; flagUsingFFMpeg = 1; flagIsGain = 0; if(argc <= 3) { argn_dec = 1; while (argn_dec<argc) { if (*(argv[argn_dec]) =='-') { switch (*(argv[argn_dec]+1)) { case 's': seek = 0; break; //case 't': // flagSetupTunnel = 0; // break; default: display_help(); } } else { stream_dir = malloc(strlen(argv[argn_dec]) * sizeof(char) + 1); strcpy(stream_dir,argv[argn_dec]); } argn_dec++; } } else if(argc > 3) { display_help(); } if(stream_dir==NULL) { stream_dir = malloc(strlen(getenv("HOME")) * sizeof(char) + 20); memset(stream_dir, 0, sizeof(stream_dir)); strcat(stream_dir, getenv("HOME")); strcat(stream_dir, "/stream/audio/"); } DEBUG(DEFAULT_MESSAGES, "Directory Name=%s\n",stream_dir); /* Populate the registry file */ dirp = opendir(stream_dir); if(dirp == NULL){ int err = errno; DEBUG(DEB_LEV_ERR, "Cannot open directory %s\n", stream_dir); return err; } /** initializing appPriv structure */ appPriv = malloc(sizeof(appPrivateType)); appPriv->filereaderEventSem = malloc(sizeof(tsem_t)); appPriv->decoderEventSem = malloc(sizeof(tsem_t)); appPriv->eofSem = malloc(sizeof(tsem_t)); if (flagPlaybackOn) { appPriv->sinkEventSem = malloc(sizeof(tsem_t)); tsem_init(appPriv->sinkEventSem, 0); appPriv->volumeEventSem = malloc(sizeof(tsem_t)); tsem_init(appPriv->volumeEventSem, 0); } tsem_init(appPriv->filereaderEventSem, 0); tsem_init(appPriv->decoderEventSem, 0); tsem_init(appPriv->eofSem, 0); /** initialising openmax */ err = OMX_Init(); if (err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "The OpenMAX core can not be initialized. Exiting...\n"); exit(1); } if(flagUsingFFMpeg) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Using File Reader\n"); /** file reader component name -- gethandle*/ err = OMX_GetHandle(&appPriv->filereaderhandle, FILE_READER, NULL , &filereadercallbacks); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "FileReader Component Not Found\n"); exit(1); } err = OMX_GetExtensionIndex(appPriv->filereaderhandle,"OMX.ST.index.param.inputfilename",&eIndexParamFilename); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"\n error in get extension index\n"); exit(1); } } /** getting the handle of audio decoder */ err = OMX_GetHandle(&appPriv->audiodechandle, COMPONENT_NAME_BASE, NULL , &audiodeccallbacks); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Audio Decoder Component Not Found\n"); exit(1); } DEBUG(DEFAULT_MESSAGES, "Component %s opened\n", COMPONENT_NAME_BASE); if (flagPlaybackOn) { err = OMX_GetHandle(&appPriv->audiosinkhandle, SINK_NAME, NULL , &audiosinkcallbacks); if(err != OMX_ErrorNone){ DEBUG(DEB_LEV_ERR, "No sink found. Exiting...\n"); exit(1); } DEBUG(DEFAULT_MESSAGES, "Getting Handle for Component %s\n", AUDIO_EFFECT); err = OMX_GetHandle(&appPriv->volumehandle, AUDIO_EFFECT, NULL , &volumecallbacks); if(err != OMX_ErrorNone){ DEBUG(DEB_LEV_ERR, "No sink found. Exiting...\n"); exit(1); } if((gain >= 0) && (gain <100)) { err = OMX_GetConfig(appPriv->volumehandle, OMX_IndexConfigAudioVolume, &sVolume); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_GetConfig 0 \n",err); } sVolume.sVolume.nValue = gain; DEBUG(DEFAULT_MESSAGES, "Setting Gain %d \n", gain); err = OMX_SetConfig(appPriv->volumehandle, OMX_IndexConfigAudioVolume, &sVolume); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig 0 \n",err); } } } if (flagSetupTunnel) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Setting up Tunnel\n"); if(flagUsingFFMpeg) { err = OMX_SetupTunnel(appPriv->filereaderhandle, 0, appPriv->audiodechandle, 0); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set up Tunnel Failed\n"); exit(1); } } err = OMX_SetupTunnel(appPriv->audiodechandle, 1, appPriv->volumehandle, 0); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set up Tunnel Failed\n"); exit(1); } err = OMX_SetupTunnel(appPriv->volumehandle, 1, appPriv->audiosinkhandle, 0); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR, "Set up Tunnel Failed\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ, "Set up Tunnel Completed\n"); } if(flagUsingFFMpeg) { /** now set the filereader component to idle and executing state */ OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StateIdle, NULL); } /*Send State Change Idle command to Audio Decoder*/ DEBUG(DEB_LEV_SIMPLE_SEQ, "Send Command Idle to Audio Dec\n"); err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandStateSet, OMX_StateIdle, NULL); if (flagPlaybackOn) { DEBUG(DEB_LEV_SIMPLE_SEQ, "Send Command Idle to Audio Sink\n"); err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandStateSet, OMX_StateIdle, NULL); err = OMX_SendCommand(appPriv->audiosinkhandle, OMX_CommandStateSet, OMX_StateIdle, NULL); } if(flagUsingFFMpeg) { /*Wait for File reader state change to */ tsem_down(appPriv->filereaderEventSem); DEBUG(DEFAULT_MESSAGES,"File reader idle state \n"); } tsem_down(appPriv->decoderEventSem); if (flagPlaybackOn) { tsem_down(appPriv->volumeEventSem); DEBUG(DEFAULT_MESSAGES,"volume state idle\n"); tsem_down(appPriv->sinkEventSem); DEBUG(DEFAULT_MESSAGES,"audio sink state idle\n"); } if (flagPlaybackOn) { err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"volume state executing failed\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ,"waiting for volume state executing\n"); tsem_down(appPriv->volumeEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ,"sending audio sink state executing\n"); err = OMX_SendCommand(appPriv->audiosinkhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"audio sink state executing failed\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ,"waiting for audio sink state executing\n"); tsem_down(appPriv->sinkEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ, "audio sink state executing successful\n"); } setHeader(&sComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); strcpy((char*)&sComponentRole.cRole[0], MP3_ROLE); while((dp = readdir(dirp)) != NULL) { int len = strlen(dp->d_name); if(len >= 3){ if(strncmp(dp->d_name+len-4, ".mp3", 4) == 0){ if(input_file!=NULL) { free(input_file); input_file=NULL; } input_file = malloc(strlen(stream_dir) * sizeof(char) + sizeof(dp->d_name) +1); strcpy(input_file,stream_dir); strcat(input_file, dp->d_name); DEBUG(DEFAULT_MESSAGES, "Input Mp3 File Name=%s\n",input_file); flagUsingFFMpeg = 1; strcpy((char*)&sComponentRole.cRole[0], MP3_ROLE); } else if(strncmp(dp->d_name+len-4, ".ogg", 4) == 0){ if(input_file!=NULL) { free(input_file); input_file=NULL; } input_file = malloc(strlen(stream_dir) * sizeof(char) + sizeof(dp->d_name) +1); strcpy(input_file,stream_dir); strcat(input_file, dp->d_name); DEBUG(DEFAULT_MESSAGES, "Input Vorbis File Name=%s\n",input_file); flagUsingFFMpeg = 1; strcpy((char*)&sComponentRole.cRole[0], VORBIS_ROLE); } else if(strncmp(dp->d_name+len-4, ".aac", 4) == 0){ if(input_file!=NULL) { free(input_file); input_file=NULL; } input_file = malloc(strlen(stream_dir) * sizeof(char) + sizeof(dp->d_name) +1); strcpy(input_file,stream_dir); strcat(input_file, dp->d_name); DEBUG(DEFAULT_MESSAGES, "Input AAC File Name=%s\n",input_file); flagUsingFFMpeg = 1; strcpy((char*)&sComponentRole.cRole[0], AAC_ROLE); } else { continue; } } else { continue; } /*Reset Global Variables*/ tsem_reset(appPriv->eofSem); bEOS=OMX_FALSE; if (flagUsingFFMpeg) { DEBUG(DEB_LEV_SIMPLE_SEQ,"Sending Port Disable Command State Idle\n"); /*Port Disable for filereader is sent from Port Settings Changed event of FileReader*/ err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandPortDisable, 0, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"file reader port disable failed\n"); exit(1); } err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandPortDisable, OMX_ALL, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"audio decoder port disable failed\n"); exit(1); } err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandPortDisable, 0, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"audio sink port disable failed\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ,"Waiting File reader Port Disable event \n"); /*Wait for File Reader Ports Disable Event*/ tsem_down(appPriv->filereaderEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ,"File reader Port Disable State Idle\n"); /*Wait for Audio Decoder Ports Disable Event*/ tsem_down(appPriv->decoderEventSem); tsem_down(appPriv->decoderEventSem); tsem_down(appPriv->volumeEventSem); err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); tsem_down(appPriv->decoderEventSem); } DEBUG(DEB_LEV_SIMPLE_SEQ,"Setting Role\n"); err = OMX_SetParameter(appPriv->audiodechandle,OMX_IndexParamStandardComponentRole,&sComponentRole); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"\n error in input audio format - exiting\n"); exit(1); } if(flagUsingFFMpeg) { /** setting the input audio format in file reader */ DEBUG(DEB_LEV_SIMPLE_SEQ,"FileName Param index : %x \n",eIndexParamFilename); err = OMX_SetParameter(appPriv->filereaderhandle,eIndexParamFilename,input_file); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"\n error in input audio format - exiting\n"); exit(1); } } if (flagUsingFFMpeg) { DEBUG(DEB_LEV_SIMPLE_SEQ,"Sending Port Enable Command State Idle\n"); err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandStateSet, OMX_StateIdle, NULL); tsem_down(appPriv->decoderEventSem); err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandPortEnable, 0, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"file reader port enable failed\n"); exit(1); } err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandPortEnable, OMX_ALL, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"audio decoder port enable failed\n"); exit(1); } err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandPortEnable, 0, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"audio sink port enable failed\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ,"Waiting File reader Port Disable event \n"); /*Wait for File Reader Ports Disable Event*/ tsem_down(appPriv->filereaderEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ,"File reader Port Disable State Idle\n"); /*Wait for Audio Decoder Ports Disable Event*/ tsem_down(appPriv->decoderEventSem); tsem_down(appPriv->decoderEventSem); tsem_down(appPriv->volumeEventSem); } if(flagUsingFFMpeg) { err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"file reader state executing failed\n"); exit(1); } /*Wait for File reader state change to executing*/ tsem_down(appPriv->filereaderEventSem); DEBUG(DEFAULT_MESSAGES,"File reader executing state \n"); } err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"audio decoder state executing failed\n"); exit(1); } DEBUG(DEB_LEV_SIMPLE_SEQ,"Waiting for audio dec state exec\n"); /*Wait for decoder state change to executing*/ tsem_down(appPriv->decoderEventSem); DEBUG(DEB_LEV_SIMPLE_SEQ,"All Component state changed to Executing\n"); DEBUG(DEFAULT_MESSAGES,"Waiting for EOS = %d\n",appPriv->eofSem->semval); if (seek==1) { DEBUG(DEFAULT_MESSAGES,"Sleeping for 5 Secs \n"); /* Play for 5 Secs */ sleep(5); DEBUG(DEFAULT_MESSAGES,"Sleep for 5 Secs is over\n"); /*Then Pause the filereader component*/ err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StatePause, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"file reader state executing failed\n"); exit(1); } /*Wait for File reader state change to Pause*/ tsem_down(appPriv->filereaderEventSem); setHeader(&sTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); sTimeStamp.nPortIndex=0; /*Seek to 30 secs and play for 10 secs*/ sTimeStamp.nTimestamp = 2351*38*30; // 23.51ms*38fps*30secs //sTimeStamp.nTimestamp = 2351*38*60*3; // 23.51ms*38fps*60secs*4mins DEBUG(DEFAULT_MESSAGES, "nTimestamp %llx \n", sTimeStamp.nTimestamp); err = OMX_SetConfig(appPriv->filereaderhandle, OMX_IndexConfigTimePosition, &sTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetParameter 0 \n",err); } err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"file reader state executing failed\n"); exit(1); } /*Wait for File reader state change to Pause*/ tsem_down(appPriv->filereaderEventSem); DEBUG(DEFAULT_MESSAGES,"Sleeping for 10 Secs \n"); /*Play for 10 secs*/ sleep(10); DEBUG(DEFAULT_MESSAGES,"Sleep for 10 Secs is over\n"); if(!bEOS) { /*Then Pause the filereader component*/ err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StatePause, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"file reader state executing failed\n"); exit(1); } /*Wait for File reader state change to Pause*/ tsem_down(appPriv->filereaderEventSem); /*Seek to 5 mins or EOF*/ sTimeStamp.nTimestamp = 2351*38*60*5; // 23.51ms*38fps*30secs //sTimeStamp.nTimestamp = 2351*38*60*3; // 23.51ms*38fps*60secs*4mins DEBUG(DEFAULT_MESSAGES, "nTimestamp %llx \n", sTimeStamp.nTimestamp); err = OMX_SetConfig(appPriv->filereaderhandle, OMX_IndexConfigTimePosition, &sTimeStamp); if(err!=OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetParameter 0 \n",err); } err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); if(err != OMX_ErrorNone) { DEBUG(DEB_LEV_ERR,"file reader state executing failed\n"); exit(1); } /*Wait for File reader state change to Pause*/ tsem_down(appPriv->filereaderEventSem); } } tsem_down(appPriv->eofSem); DEBUG(DEFAULT_MESSAGES,"Received EOS \n"); /*Send Idle Command to all components*/ DEBUG(DEFAULT_MESSAGES, "The execution of the decoding process is terminated\n"); if(flagUsingFFMpeg) { err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StateIdle, NULL); } err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandStateSet, OMX_StateIdle, NULL); if(flagUsingFFMpeg) { tsem_down(appPriv->filereaderEventSem); DEBUG(DEFAULT_MESSAGES,"File reader idle state \n"); } tsem_down(appPriv->decoderEventSem); DEBUG(DEFAULT_MESSAGES, "All component Transitioned to Idle\n"); } /*Loop While Play List*/ if (flagPlaybackOn) { err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandStateSet, OMX_StateIdle, NULL); err = OMX_SendCommand(appPriv->audiosinkhandle, OMX_CommandStateSet, OMX_StateIdle, NULL); } if (flagPlaybackOn) { tsem_down(appPriv->volumeEventSem); tsem_down(appPriv->sinkEventSem); } /*Send Loaded Command to all components*/ if(flagUsingFFMpeg) { err = OMX_SendCommand(appPriv->filereaderhandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); } err = OMX_SendCommand(appPriv->audiodechandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); if (flagPlaybackOn) { err = OMX_SendCommand(appPriv->volumehandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); err = OMX_SendCommand(appPriv->audiosinkhandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); } DEBUG(DEFAULT_MESSAGES, "Audio dec to loaded\n"); if(flagUsingFFMpeg) { tsem_down(appPriv->filereaderEventSem); DEBUG(DEFAULT_MESSAGES,"File reader loaded state \n"); } tsem_down(appPriv->decoderEventSem); if (flagPlaybackOn) { tsem_down(appPriv->volumeEventSem); tsem_down(appPriv->sinkEventSem); } if(input_file!=NULL) { free(input_file); input_file=NULL; } closedir(dirp); DEBUG(DEFAULT_MESSAGES, "All components released\n"); /** freeing all handles and deinit omx */ OMX_FreeHandle(appPriv->audiodechandle); DEBUG(DEB_LEV_SIMPLE_SEQ, "audiodec dec freed\n"); if(flagUsingFFMpeg) { OMX_FreeHandle(appPriv->filereaderhandle); DEBUG(DEB_LEV_SIMPLE_SEQ, "filereader freed\n"); } if (flagPlaybackOn) { OMX_FreeHandle(appPriv->volumehandle); DEBUG(DEB_LEV_SIMPLE_SEQ, "volume component freed\n"); OMX_FreeHandle(appPriv->audiosinkhandle); DEBUG(DEB_LEV_SIMPLE_SEQ, "audiosink freed\n"); } OMX_Deinit(); DEBUG(DEB_LEV_SIMPLE_SEQ, "All components freed. Closing...\n"); free(appPriv->filereaderEventSem); appPriv->filereaderEventSem = NULL; free(appPriv->decoderEventSem); appPriv->decoderEventSem = NULL; if (flagPlaybackOn) { free(appPriv->volumeEventSem); appPriv->volumeEventSem = NULL; free(appPriv->sinkEventSem); appPriv->sinkEventSem = NULL; } free(appPriv->eofSem); appPriv->eofSem = NULL; free(appPriv); appPriv = NULL; if(input_file) { free(input_file); } return 0; }