ret_code_t ilcore_clean_tunnel(ilcore_tunnel_h h) { omx_tunnel_t *tunnel = (omx_tunnel_t *)h; OMX_ERRORTYPE omx_err; if (!tunnel || !tunnel->src_comp || !tunnel->dst_comp) { DBG_E("%s: Incorrect parameters\n", __FUNCTION__); return L_FAILED; } ilcore_disable_port(tunnel->src_comp, tunnel->src_port, 0); ilcore_disable_port(tunnel->dst_comp, tunnel->dst_port, 0); omx_err = OMX_SetupTunnel(ilcore_get_handle(tunnel->src_comp), tunnel->src_port, NULL, 0); if(omx_err != OMX_ErrorNone) { DBG_E("%s: could not unset tunnel on comp src %s port %d err = 0x%08x\n", __FUNCTION__, ilcore_get_comp_name(tunnel->src_comp), tunnel->src_port, omx_err); } omx_err = OMX_SetupTunnel(ilcore_get_handle(tunnel->dst_comp), tunnel->dst_port, NULL, 0); if(omx_err != OMX_ErrorNone) { DBG_E("%s: could not unset tunnel on comp dst %s port %d err = 0x%08x\n", __FUNCTION__, ilcore_get_comp_name(tunnel->dst_comp), tunnel->dst_port, omx_err); } return L_OK; }
bool Component::tunnelToNull(int port) { bool result = false; OMX_ERRORTYPE error; if(CustomFillBufferDoneHandler) { CustomFillBufferDoneHandler = NULL; } if(setToStateIdle()) { disableAllPorts(); if(getName() != "OMX.broadcom.clock" && getName() != "OMX.broadcom.audio_render" && getName() != "OMX.broadcom.audio_mixer") { error = OMX_SetupTunnel(handle, port, NULL, 0); OMX_TRACE(error); if(error == OMX_ErrorNone) { result = true; } }else { result = true; } } ofLogVerbose(__func__) << getName() << " TUNNELED TO NULL: " << result; return result; }
omx_tunnel_t * omx_tunnel_create(omx_component_t *src, int srcport, omx_component_t *dst, int dstport, const char *name) { OMX_STATETYPE state; omxchk(OMX_GetState(src->oc_handle, &state)); if(state == OMX_StateLoaded) omx_set_state(src, OMX_StateIdle); omxdbg("Creating tunnel %s from %s:%d to %s:%d\n", name, src->oc_name, srcport, dst->oc_name, dstport); omx_send_command(src, OMX_CommandPortDisable, srcport, NULL, 1); omx_send_command(dst, OMX_CommandPortDisable, dstport, NULL, 1); omxchk(OMX_SetupTunnel(src->oc_handle, srcport, dst->oc_handle, dstport)); omx_send_command(src, OMX_CommandPortEnable, srcport, NULL, 0); omx_send_command(dst, OMX_CommandPortEnable, dstport, NULL, 0); omxchk(OMX_GetState(dst->oc_handle, &state)); if(state == OMX_StateLoaded) omx_set_state(dst, OMX_StateIdle); omx_tunnel_t *ot = malloc(sizeof(omx_tunnel_t)); ot->ot_src = src; ot->ot_srcport = srcport; ot->ot_dst = dst; ot->ot_dstport = dstport; ot->ot_name = name; return ot; }
ret_code_t ilcore_setup_tunnel(ilcore_tunnel_h h) { omx_tunnel_t *tunnel = (omx_tunnel_t *)h; OMX_STATETYPE state; OMX_ERRORTYPE omx_err; if (!tunnel || !tunnel->src_comp || !tunnel->dst_comp) { DBG_E("%s: Incorrect parameters\n", __FUNCTION__); return L_FAILED; } if (ilcore_get_state(tunnel->src_comp, &state) != L_OK) return L_FAILED; if (state == OMX_StateLoaded) { if (ilcore_set_state(tunnel->src_comp, OMX_StateIdle)) return L_FAILED; } if (ilcore_disable_port(tunnel->src_comp, tunnel->src_port, 0) != L_OK) return L_FAILED; if (ilcore_disable_port(tunnel->dst_comp, tunnel->dst_port, 0) != L_OK) return L_FAILED; omx_err = OMX_SetupTunnel(ilcore_get_handle(tunnel->src_comp), tunnel->src_port, ilcore_get_handle(tunnel->dst_comp), tunnel->dst_port); if(omx_err != OMX_ErrorNone) { DBG_E("%s: could not setup tunnel src %s port %d dst %s port %d err = 0x%08x\n", __FUNCTION__, ilcore_get_comp_name(tunnel->src_comp), tunnel->src_port, ilcore_get_comp_name(tunnel->dst_comp), tunnel->dst_port, omx_err); return L_FAILED; } if (ilcore_enable_port(tunnel->src_comp, tunnel->src_port, 0) != L_OK) return L_FAILED; if (ilcore_enable_port(tunnel->dst_comp, tunnel->dst_port, 0) != L_OK) return L_FAILED; if (ilcore_get_state(tunnel->dst_comp, &state) != L_OK) return L_FAILED; omx_err = omx_core_comp_wait_command(tunnel->dst_comp, OMX_CommandPortEnable, tunnel->dst_port, 2000); if(omx_err != OMX_ErrorNone) return L_FAILED; if (state == OMX_StateLoaded) { if (ilcore_set_state(tunnel->dst_comp, OMX_StateIdle)) return L_FAILED; } omx_err = omx_core_comp_wait_command(tunnel->src_comp, OMX_CommandPortEnable, tunnel->src_port, 2000); if(omx_err != OMX_ErrorNone) return L_FAILED; return L_OK; }
OMX_API OMX_ERRORTYPE TIOMX_SetupTunnel(OMX_IN OMX_HANDLETYPE hOutput, OMX_IN OMX_U32 nPortOutput, OMX_IN OMX_HANDLETYPE hInput, OMX_IN OMX_U32 nPortInput) { ALOGV("TIOMX_SetupTunnel\n"); return OMX_SetupTunnel(hOutput, nPortOutput, hInput, nPortInput); }
void omx_tunnel_destroy(omx_tunnel_t *ot) { omxdbg("Destroying tunnel\n"); omx_send_command(ot->ot_src, OMX_CommandPortDisable, ot->ot_srcport, NULL, 0); omx_send_command(ot->ot_dst, OMX_CommandPortDisable, ot->ot_dstport, NULL, 0); omxchk(OMX_SetupTunnel(ot->ot_src->oc_handle, ot->ot_srcport, NULL, 0)); free(ot); }
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; }
OMX_ERRORTYPE PortCommTest_OperateOnPorts(PortCommTestCtxt* pContext, PortOpType eOp) { OMX_PARAM_PORTDEFINITIONTYPE sPortDef; OMX_ERRORTYPE eError = OMX_ErrorNone; OMX_U32 i, j; OMX_BUFFERHEADERTYPE sBufHdr; for (j = 0; j < NUM_DOMAINS; j++) { for (i = pContext->sPortParam[j].nStartPortNumber; i < pContext->sPortParam[j].nStartPortNumber + pContext->sPortParam[j].nPorts; i++) { OMX_CONF_INIT_STRUCT(sPortDef, OMX_PARAM_PORTDEFINITIONTYPE); sPortDef.nPortIndex = i; OMX_CONF_BAIL_IF_ERROR(OMX_GetParameter(pContext->hWComp, OMX_IndexParamPortDefinition , (OMX_PTR)&sPortDef)); switch (eOp) { case AllocBuf: if (0x0 == sPortDef.nBufferCountMin || sPortDef.nBufferCountMin > sPortDef.nBufferCountActual) { OMX_CONF_SET_ERROR_BAIL("PortDefinition nBufferCount incorrect\n", OMX_ErrorUndefined); } OMX_CONF_BAIL_IF_ERROR(PortCommTest_AllocateBuffers(pContext, &sPortDef)); break; case NonTunnelTest: if (sPortDef.eDir == OMX_DirInput) { eError = OMX_SetupTunnel(NULL, 0, pContext->hWComp, sPortDef.nPortIndex); OMX_CONF_ErrorToString(eError, szDesc); OMX_OSAL_Trace(OMX_OSAL_TRACE_INFO, "Setup tunnel reported error code %s\n", szDesc); } else { eError = OMX_SetupTunnel(pContext->hWComp, sPortDef.nPortIndex, NULL, 0); OMX_CONF_ErrorToString(eError, szDesc); OMX_OSAL_Trace(OMX_OSAL_TRACE_INFO, "Setup tunnel reported error code %s\n", szDesc); } eError = OMX_ErrorNone; break; case OpenFile: /* set buffercount actual */ if (0x0 == sPortDef.nBufferCountMin || sPortDef.nBufferCountMin > sPortDef.nBufferCountActual) { OMX_CONF_SET_ERROR_BAIL("PortDefinition nBufferCount incorrect\n", OMX_ErrorUndefined); } sPortDef.nBufferCountActual = sPortDef.nBufferCountMin + 1; OMX_CONF_BAIL_IF_ERROR(OMX_SetParameter(pContext->hWComp, OMX_IndexParamPortDefinition, (OMX_PTR)&sPortDef)); /* open files for input ports */ if (sPortDef.eDir == OMX_DirInput) { OMX_OSAL_Trace(OMX_OSAL_TRACE_INFO, "Opened input file for port %d\n", i); OMX_CONF_BAIL_IF_ERROR(OMX_OSAL_OpenInputFile(i)); } break; case CloseFile: if (sPortDef.eDir == OMX_DirInput) { OMX_CONF_BAIL_IF_ERROR(OMX_OSAL_CloseInputFile(i)); } break; case EmptyFill: OMX_CONF_INIT_STRUCT(sBufHdr, OMX_BUFFERHEADERTYPE); if (sPortDef.eDir == OMX_DirInput) { sBufHdr.nInputPortIndex = i; eError = OMX_EmptyThisBuffer(pContext->hWComp, &sBufHdr); } else { sBufHdr.nOutputPortIndex = i; eError = OMX_FillThisBuffer(pContext->hWComp, &sBufHdr); } if (eError != OMX_ErrorIncorrectStateOperation) OMX_CONF_SET_ERROR_BAIL("Buffer handling while stopped\n", OMX_ErrorUndefined); eError = OMX_ErrorNone; break; default: eError = OMX_ErrorBadParameter; } } } OMX_CONF_TEST_BAIL: return eError; }
// this function cleans up the decoder. void cleanup(OPENMAX_JPEG_DECODER * decoder) { // flush everything through OMX_SendCommand(decoder->imageDecoder->handle, OMX_CommandFlush, decoder->imageDecoder->outPort, NULL); ilclient_wait_for_event(decoder->imageDecoder->component, OMX_EventCmdComplete, OMX_CommandFlush, 0, decoder->imageDecoder->outPort, 0, 0, TIMEOUT_MS); OMX_SendCommand(decoder->imageResizer->handle, OMX_CommandFlush, decoder->imageResizer->inPort, NULL); ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandFlush, 0, decoder->imageResizer->inPort, 1, 0, TIMEOUT_MS); OMX_SendCommand(decoder->imageDecoder->handle, OMX_CommandPortDisable, decoder->imageDecoder->inPort, NULL); int i = 0; for (i = 0; i < decoder->inputBufferHeaderCount; i++) { OMX_BUFFERHEADERTYPE *vpBufHeader = decoder->ppInputBufferHeader[i]; OMX_FreeBuffer(decoder->imageDecoder->handle, decoder->imageDecoder->inPort, vpBufHeader); } ilclient_wait_for_event(decoder->imageDecoder->component, OMX_EventCmdComplete, OMX_CommandPortDisable, 0, decoder->imageDecoder->inPort, 0, 0, TIMEOUT_MS); OMX_SendCommand(decoder->imageResizer->handle, OMX_CommandPortDisable, decoder->imageResizer->outPort, NULL); OMX_FreeBuffer(decoder->imageResizer->handle, decoder->imageResizer->outPort, decoder->pOutputBufferHeader); ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandPortDisable, 0, decoder->imageResizer->outPort, 0, 0, TIMEOUT_MS); OMX_SendCommand(decoder->imageDecoder->handle, OMX_CommandPortDisable, decoder->imageDecoder->outPort, NULL); ilclient_wait_for_event(decoder->imageDecoder->component, OMX_EventCmdComplete, OMX_CommandPortDisable, 0, decoder->imageDecoder->outPort, 0, 0, TIMEOUT_MS); OMX_SendCommand(decoder->imageResizer->handle, OMX_CommandPortDisable, decoder->imageResizer->inPort, NULL); ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandPortDisable, 0, decoder->imageResizer->inPort, 0, 0, TIMEOUT_MS); OMX_SetupTunnel(decoder->imageDecoder->handle, decoder->imageDecoder->outPort, NULL, 0); OMX_SetupTunnel(decoder->imageResizer->handle, decoder->imageResizer->inPort, NULL, 0); ilclient_change_component_state(decoder->imageDecoder->component, OMX_StateIdle); ilclient_change_component_state(decoder->imageResizer->component, OMX_StateIdle); ilclient_wait_for_event(decoder->imageDecoder->component, OMX_EventCmdComplete, OMX_CommandStateSet, 0, OMX_StateIdle, 0, 0, TIMEOUT_MS); ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandStateSet, 0, OMX_StateIdle, 0, 0, TIMEOUT_MS); ilclient_change_component_state(decoder->imageDecoder->component, OMX_StateLoaded); ilclient_change_component_state(decoder->imageResizer->component, OMX_StateLoaded); ilclient_wait_for_event(decoder->imageDecoder->component, OMX_EventCmdComplete, OMX_CommandStateSet, 0, OMX_StateLoaded, 0, 0, TIMEOUT_MS); ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandStateSet, 0, OMX_StateLoaded, 0, 0, TIMEOUT_MS); OMX_Deinit(); if (decoder->client != NULL) { ilclient_destroy(decoder->client); } }
OMX_ERRORTYPE omx_setup_pipeline(struct omx_pipeline_t* pipe, OMX_VIDEO_CODINGTYPE video_codec, char* audio_dest, int is_hd) { OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; OMX_CONFIG_BOOLEANTYPE configBoolTrue; OMX_INIT_STRUCTURE(configBoolTrue); configBoolTrue.bEnabled = OMX_TRUE; pipe->do_deinterlace = 0; if (((is_hd == 0) && (global_settings.deinterlace_sd)) || ((is_hd == 1) && (global_settings.deinterlace_hd))) { DEBUGF("Enabling de-interlace\n"); pipe->do_deinterlace = 1; } omx_init_component(pipe, &pipe->video_decode, "OMX.broadcom.video_decode"); omx_init_component(pipe, &pipe->video_render, "OMX.broadcom.video_render"); if (pipe->do_deinterlace) { DEBUGF("Enabling de-interlacer\n"); /* De-interlacer. Input port 190, Output port 191. Insert between decoder and scheduler */ omx_init_component(pipe, &pipe->image_fx, "OMX.broadcom.image_fx"); /* Configure image_fx */ omx_send_command_and_wait(&pipe->image_fx, OMX_CommandStateSet, OMX_StateIdle, NULL); OMX_CONFIG_IMAGEFILTERPARAMSTYPE imagefilter; OMX_INIT_STRUCTURE(imagefilter); imagefilter.nPortIndex=191; imagefilter.nNumParams=1; imagefilter.nParams[0]=3; //??? imagefilter.eImageFilter=OMX_ImageFilterDeInterlaceAdvanced; OERR(OMX_SetConfig(pipe->image_fx.h, OMX_IndexConfigCommonImageFilterParameters, &imagefilter)); } else { memset(&pipe->image_fx,0,sizeof(struct omx_component_t)); } omx_init_component(pipe, &pipe->clock, "OMX.broadcom.clock"); OMX_INIT_STRUCTURE(cstate); cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = OMX_CLOCKPORT0|OMX_CLOCKPORT1; OERR(OMX_SetParameter(pipe->clock.h, OMX_IndexConfigTimeClockState, &cstate)); OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock; OMX_INIT_STRUCTURE(refClock); refClock.eClock = OMX_TIME_RefClockAudio; OERR(OMX_SetConfig(pipe->clock.h, OMX_IndexConfigTimeActiveRefClock, &refClock)); omx_init_component(pipe, &pipe->video_scheduler, "OMX.broadcom.video_scheduler"); /* Initialise audio output - hardcoded to 48000/Stereo/16-bit */ omx_init_component(pipe, &pipe->audio_render, "OMX.broadcom.audio_render"); OMX_PARAM_PORTDEFINITIONTYPE param; OMX_INIT_STRUCTURE(param); param.nPortIndex = 100; OERR(OMX_GetParameter(pipe->audio_render.h, OMX_IndexParamPortDefinition, ¶m)); param.nBufferSize = 8192; /* Needs to be big enough for one frame of data */ param.nBufferCountActual = 32; /* Arbitrary */ OERR(OMX_SetParameter(pipe->audio_render.h, OMX_IndexParamPortDefinition, ¶m)); omx_config_pcm(&pipe->audio_render, 48000, 2, 16, audio_dest); OERR(OMX_SetConfig(pipe->audio_render.h, OMX_IndexConfigBrcmClockReferenceSource, &configBoolTrue)); omx_send_command_and_wait(&pipe->audio_render, OMX_CommandStateSet, OMX_StateIdle, NULL); omx_send_command_and_wait0(&pipe->audio_render, OMX_CommandPortEnable, 100, NULL); omx_alloc_buffers(&pipe->audio_render, 100); omx_send_command_and_wait1(&pipe->audio_render, OMX_CommandPortEnable, 100, NULL); /* Setup clock tunnels first */ omx_send_command_and_wait(&pipe->clock, OMX_CommandStateSet, OMX_StateIdle, NULL); OERR(OMX_SetupTunnel(pipe->clock.h, 80, pipe->audio_render.h, 101)); OERR(OMX_SetupTunnel(pipe->clock.h, 81, pipe->video_scheduler.h, 12)); OERR(OMX_SendCommand(pipe->clock.h, OMX_CommandPortEnable, 80, NULL)); OERR(OMX_SendCommand(pipe->video_scheduler.h, OMX_CommandPortEnable, 12, NULL)); OERR(OMX_SendCommand(pipe->clock.h, OMX_CommandPortEnable, 81, NULL)); OERR(OMX_SendCommand(pipe->audio_render.h, OMX_CommandPortEnable, 101, NULL)); omx_send_command_and_wait(&pipe->video_scheduler, OMX_CommandStateSet, OMX_StateIdle, NULL); omx_send_command_and_wait(&pipe->clock, OMX_CommandStateSet, OMX_StateExecuting, NULL); /* Configure video_decoder */ omx_send_command_and_wait(&pipe->video_decode, OMX_CommandStateSet, OMX_StateIdle, NULL); /* Enable lazy image pool destroying */ OERR(OMX_SetConfig(pipe->video_decode.h, OMX_IndexParamBrcmLazyImagePoolDestroy, &configBoolTrue)); OMX_INIT_STRUCTURE(format); format.nPortIndex = 130; format.eCompressionFormat = video_codec; OERR(OMX_SetParameter(pipe->video_decode.h, OMX_IndexParamVideoPortFormat, &format)); /* Enable error concealment for H264 only - without this, HD channels don't work reliably */ if (video_codec == OMX_VIDEO_CodingAVC) { OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE ec; OMX_INIT_STRUCTURE(ec); ec.bStartWithValidFrame = OMX_FALSE; OERR(OMX_SetParameter(pipe->video_decode.h, OMX_IndexParamBrcmVideoDecodeErrorConcealment, &ec)); } /* Enable video decoder input port */ omx_send_command_and_wait0(&pipe->video_decode, OMX_CommandPortEnable, 130, NULL); /* Allocate input buffers */ omx_alloc_buffers(&pipe->video_decode, 130); /* Wait for input port to be enabled */ omx_send_command_and_wait1(&pipe->video_decode, OMX_CommandPortEnable, 130, NULL); /* Change video_decode to OMX_StateExecuting */ omx_send_command_and_wait(&pipe->video_decode, OMX_CommandStateSet, OMX_StateExecuting, NULL); /* Change audio_render to OMX_StateExecuting */ omx_send_command_and_wait(&pipe->audio_render, OMX_CommandStateSet, OMX_StateExecuting, NULL); /* Enable passing of buffer marks */ OERR(OMX_SetParameter(pipe->video_decode.h, OMX_IndexParamPassBufferMarks, &configBoolTrue)); OERR(OMX_SetParameter(pipe->video_render.h, OMX_IndexParamPassBufferMarks, &configBoolTrue)); return OMX_ErrorNone; }
int encoder_init(struct picture_t *info,int fps,int bright,int video_bitrate) { //tem_width=info->width; bcm_host_init(); OMX_ERRORTYPE r; if((r = OMX_Init()) != OMX_ErrorNone) { omx_die(r, "OMX initalization failed"); } // Init context memset(&ctx, 0, sizeof(ctx)); if(vcos_semaphore_create(&ctx.handler_lock, "handler_lock", 1) != VCOS_SUCCESS) { die("Failed to create handler lock semaphore"); } // Init component handles OMX_CALLBACKTYPE callbacks; memset(&ctx, 0, sizeof(callbacks)); callbacks.EventHandler = event_handler; callbacks.FillBufferDone = fill_output_buffer_done_handler; init_component_handle("camera", &ctx.camera , &ctx, &callbacks); init_component_handle("video_encode", &ctx.encoder, &ctx, &callbacks); init_component_handle("null_sink", &ctx.null_sink, &ctx, &callbacks); /* OMX_CALLBACKTYPE callbacks1; memset(&ctx, 0, sizeof(callbacks1)); callbacks1.EventHandler = event_handler; callbacks1.FillBufferDone = fill_camera_output_buffer_done_handler; */ init_component_handle("camera", &ctx.camera , &ctx, &callbacks); //===============change^^^^================ //say("Configuring camera..."); //say("Default port definition for camera input port 73"); dump_port(ctx.camera, 73, OMX_TRUE); //say("Default port definition for camera preview output port 70"); dump_port(ctx.camera, 70, OMX_TRUE); //say("Default port definition for camera video output port 71"); dump_port(ctx.camera, 71, OMX_TRUE); // Request a callback to be made when OMX_IndexParamCameraDeviceNumber is // changed signaling that the camera device is ready for use. OMX_CONFIG_REQUESTCALLBACKTYPE cbtype; OMX_INIT_STRUCTURE(cbtype); cbtype.nPortIndex = OMX_ALL; cbtype.nIndex = OMX_IndexParamCameraDeviceNumber; cbtype.bEnable = OMX_TRUE; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigRequestCallback, &cbtype)) != OMX_ErrorNone) { omx_die(r, "Failed to request camera device number parameter change callback for camera"); } // Set device number, this triggers the callback configured just above OMX_PARAM_U32TYPE device; OMX_INIT_STRUCTURE(device); device.nPortIndex = OMX_ALL; device.nU32 = CAM_DEVICE_NUMBER; if((r = OMX_SetParameter(ctx.camera, OMX_IndexParamCameraDeviceNumber, &device)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera parameter device number"); } // Configure video format emitted by camera preview output port OMX_PARAM_PORTDEFINITIONTYPE camera_portdef; OMX_INIT_STRUCTURE(camera_portdef); camera_portdef.nPortIndex = 70; if((r = OMX_GetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to get port definition for camera preview output port 70"); } camera_portdef.format.video.nFrameWidth = info->width; camera_portdef.format.video.nFrameHeight = info->height; camera_portdef.format.video.xFramerate = fps << 16; // Stolen from gstomxvideodec.c of gst-omx camera_portdef.format.video.nStride = (camera_portdef.format.video.nFrameWidth + camera_portdef.nBufferAlignment - 1) & (~(camera_portdef.nBufferAlignment - 1)); camera_portdef.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; if((r = OMX_SetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to set port definition for camera preview output port 70"); } // Configure video format emitted by camera video output port // Use configuration from camera preview output as basis for // camera video output configuration OMX_INIT_STRUCTURE(camera_portdef); camera_portdef.nPortIndex = 70; if((r = OMX_GetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to get port definition for camera preview output port 70"); } camera_portdef.nPortIndex = 71; if((r = OMX_SetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to set port definition for camera video output port 71"); } // Configure frame rate OMX_CONFIG_FRAMERATETYPE framerate; OMX_INIT_STRUCTURE(framerate); framerate.nPortIndex = 70; framerate.xEncodeFramerate = camera_portdef.format.video.xFramerate; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigVideoFramerate, &framerate)) != OMX_ErrorNone) { omx_die(r, "Failed to set framerate configuration for camera preview output port 70"); } framerate.nPortIndex = 71; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigVideoFramerate, &framerate)) != OMX_ErrorNone) { omx_die(r, "Failed to set framerate configuration for camera video output port 71"); } // Configure sharpness OMX_CONFIG_SHARPNESSTYPE sharpness; OMX_INIT_STRUCTURE(sharpness); sharpness.nPortIndex = OMX_ALL; sharpness.nSharpness = CAM_SHARPNESS; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonSharpness, &sharpness)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera sharpness configuration"); } // Configure contrast OMX_CONFIG_CONTRASTTYPE contrast; OMX_INIT_STRUCTURE(contrast); contrast.nPortIndex = OMX_ALL; contrast.nContrast = CAM_CONTRAST; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonContrast, &contrast)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera contrast configuration"); } // Configure saturation OMX_CONFIG_SATURATIONTYPE saturation; OMX_INIT_STRUCTURE(saturation); saturation.nPortIndex = OMX_ALL; saturation.nSaturation = CAM_SATURATION; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonSaturation, &saturation)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera saturation configuration"); } // Configure brightness OMX_CONFIG_BRIGHTNESSTYPE brightness; OMX_INIT_STRUCTURE(brightness); brightness.nPortIndex = OMX_ALL; brightness.nBrightness = bright; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonBrightness, &brightness)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera brightness configuration"); } // Configure exposure value OMX_CONFIG_EXPOSUREVALUETYPE exposure_value; OMX_INIT_STRUCTURE(exposure_value); exposure_value.nPortIndex = OMX_ALL; exposure_value.xEVCompensation = CAM_EXPOSURE_VALUE_COMPENSTAION; exposure_value.bAutoSensitivity = CAM_EXPOSURE_AUTO_SENSITIVITY; exposure_value.nSensitivity = CAM_EXPOSURE_ISO_SENSITIVITY; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonExposureValue, &exposure_value)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera exposure value configuration"); } // Configure frame frame stabilisation OMX_CONFIG_FRAMESTABTYPE frame_stabilisation_control; OMX_INIT_STRUCTURE(frame_stabilisation_control); frame_stabilisation_control.nPortIndex = OMX_ALL; frame_stabilisation_control.bStab = CAM_FRAME_STABILISATION; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonFrameStabilisation, &frame_stabilisation_control)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera frame frame stabilisation control configuration"); } // Configure frame white balance control OMX_CONFIG_WHITEBALCONTROLTYPE white_balance_control; OMX_INIT_STRUCTURE(white_balance_control); white_balance_control.nPortIndex = OMX_ALL; white_balance_control.eWhiteBalControl = CAM_WHITE_BALANCE_CONTROL; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonWhiteBalance, &white_balance_control)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera frame white balance control configuration"); } // Configure image filter OMX_CONFIG_IMAGEFILTERTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = OMX_ALL; image_filter.eImageFilter = CAM_IMAGE_FILTER; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonImageFilter, &image_filter)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera image filter configuration"); } // Configure mirror OMX_MIRRORTYPE eMirror = OMX_MirrorNone; if(CAM_FLIP_HORIZONTAL && !CAM_FLIP_VERTICAL) { eMirror = OMX_MirrorHorizontal; } else if(!CAM_FLIP_HORIZONTAL && CAM_FLIP_VERTICAL) { eMirror = OMX_MirrorVertical; } else if(CAM_FLIP_HORIZONTAL && CAM_FLIP_VERTICAL) { eMirror = OMX_MirrorBoth; } OMX_CONFIG_MIRRORTYPE mirror; OMX_INIT_STRUCTURE(mirror); mirror.nPortIndex = 71; mirror.eMirror = eMirror; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonMirror, &mirror)) != OMX_ErrorNone) { omx_die(r, "Failed to set mirror configuration for camera video output port 71"); } // Ensure camera is ready while(!ctx.camera_ready) { usleep(10000); } //say("Configuring encoder..."); //say("Default port definition for encoder input port 200"); dump_port(ctx.encoder, 200, OMX_TRUE); //say("Default port definition for encoder output port 201"); dump_port(ctx.encoder, 201, OMX_TRUE); // Encoder input port definition is done automatically upon tunneling // Configure video format emitted by encoder output port OMX_PARAM_PORTDEFINITIONTYPE encoder_portdef; OMX_INIT_STRUCTURE(encoder_portdef); encoder_portdef.nPortIndex = 201; if((r = OMX_GetParameter(ctx.encoder, OMX_IndexParamPortDefinition, &encoder_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to get port definition for encoder output port 201"); } // Copy some of the encoder output port configuration // from camera output port encoder_portdef.format.video.nFrameWidth = camera_portdef.format.video.nFrameWidth; encoder_portdef.format.video.nFrameHeight = camera_portdef.format.video.nFrameHeight; encoder_portdef.format.video.xFramerate = camera_portdef.format.video.xFramerate; encoder_portdef.format.video.nStride = camera_portdef.format.video.nStride; // Which one is effective, this or the configuration just below? encoder_portdef.format.video.nBitrate = video_bitrate; if((r = OMX_SetParameter(ctx.encoder, OMX_IndexParamPortDefinition, &encoder_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to set port definition for encoder output port 201"); } // Configure bitrate OMX_VIDEO_PARAM_BITRATETYPE bitrate; OMX_INIT_STRUCTURE(bitrate); bitrate.eControlRate = OMX_Video_ControlRateVariable; bitrate.nTargetBitrate = encoder_portdef.format.video.nBitrate; bitrate.nPortIndex = 201; if((r = OMX_SetParameter(ctx.encoder, OMX_IndexParamVideoBitrate, &bitrate)) != OMX_ErrorNone) { omx_die(r, "Failed to set bitrate for encoder output port 201"); } // Configure format OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_INIT_STRUCTURE(format); format.nPortIndex = 201; format.eCompressionFormat = OMX_VIDEO_CodingAVC; if((r = OMX_SetParameter(ctx.encoder, OMX_IndexParamVideoPortFormat, &format)) != OMX_ErrorNone) { omx_die(r, "Failed to set video format for encoder output port 201"); } OMX_CONFIG_PORTBOOLEANTYPE inlineHeader; OMX_INIT_STRUCTURE(inlineHeader); inlineHeader.nPortIndex = 201; inlineHeader.bEnabled = OMX_TRUE; if((r = OMX_SetParameter(ctx.encoder, OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &inlineHeader)) != OMX_ErrorNone) { omx_die(r, "Failed to switch on inlineHeader on video encoder output port 201"); } OMX_VIDEO_PARAM_AVCTYPE avc_st; OMX_INIT_STRUCTURE (avc_st); avc_st.nPortIndex = 201; if ((r = OMX_GetParameter (ctx.encoder, OMX_IndexParamVideoAvc, &avc_st))){ omx_die(r, "Failed to switch on avc_st on video encoder output port 201"); } avc_st.nPFrames = VIDEO_FRAMERATE-1; if ((r = OMX_SetParameter (ctx.encoder, OMX_IndexParamVideoAvc, &avc_st))){ omx_die(r, "Failed to switch on avc_st on video encoder output port 201"); } //say("Default port definition for null sink input port 240"); dump_port(ctx.null_sink, 240, OMX_TRUE); // Null sink input port definition is done automatically upon tunneling // Tunnel camera preview output port and null sink input port //say("Setting up tunnel from camera preview output port 70 to null sink input port 240..."); if((r = OMX_SetupTunnel(ctx.camera, 70, ctx.null_sink, 240)) != OMX_ErrorNone) { omx_die(r, "Failed to setup tunnel between camera preview output port 70 and null sink input port 240"); } // Tunnel camera video output port and encoder input port //say("Setting up tunnel from camera video output port 71 to encoder input port 200..."); if((r = OMX_SetupTunnel(ctx.camera, 71, ctx.encoder, 200)) != OMX_ErrorNone) { omx_die(r, "Failed to setup tunnel between camera video output port 71 and encoder input port 200"); } // Switch components to idle state //say("Switching state of the camera component to idle..."); if((r = OMX_SendCommand(ctx.camera, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to idle"); } block_until_state_changed(ctx.camera, OMX_StateIdle); //say("Switching state of the encoder component to idle..."); if((r = OMX_SendCommand(ctx.encoder, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the encoder component to idle"); } block_until_state_changed(ctx.encoder, OMX_StateIdle); //say("Switching state of the null sink component to idle..."); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the null sink component to idle"); } block_until_state_changed(ctx.null_sink, OMX_StateIdle); // Enable ports //say("Enabling ports..."); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortEnable, 73, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable camera input port 73"); } block_until_port_changed(ctx.camera, 73, OMX_TRUE); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortEnable, 70, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable camera preview output port 70"); } block_until_port_changed(ctx.camera, 70, OMX_TRUE); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortEnable, 71, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable camera video output port 71"); } block_until_port_changed(ctx.camera, 71, OMX_TRUE); if((r = OMX_SendCommand(ctx.encoder, OMX_CommandPortEnable, 200, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable encoder input port 200"); } block_until_port_changed(ctx.encoder, 200, OMX_TRUE); if((r = OMX_SendCommand(ctx.encoder, OMX_CommandPortEnable, 201, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable encoder output port 201"); } block_until_port_changed(ctx.encoder, 201, OMX_TRUE); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandPortEnable, 240, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable null sink input port 240"); } block_until_port_changed(ctx.null_sink, 240, OMX_TRUE); // Allocate camera input buffer and encoder output buffer, // buffers for tunneled ports are allocated internally by OMX //say("Allocating buffers..."); OMX_INIT_STRUCTURE(camera_portdef); camera_portdef.nPortIndex = 73; if((r = OMX_GetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to get port definition for camera input port 73"); } if((r = OMX_AllocateBuffer(ctx.camera, &ctx.camera_ppBuffer_in, 73, NULL, camera_portdef.nBufferSize)) != OMX_ErrorNone) { omx_die(r, "Failed to allocate buffer for camera input port 73"); } /* camera_portdef.nPortIndex = 71; if((r = OMX_AllocateBuffer(ctx.camera, &ctx.camera_ppBuffer_out, 71, NULL, camera_portdef.nBufferSize)) != OMX_ErrorNone) { omx_die(r, "Failed to allocate buffer for camera output port 71"); } */ OMX_INIT_STRUCTURE(encoder_portdef); encoder_portdef.nPortIndex = 201; if((r = OMX_GetParameter(ctx.encoder, OMX_IndexParamPortDefinition, &encoder_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to get port definition for encoder output port 201"); } if((r = OMX_AllocateBuffer(ctx.encoder, &ctx.encoder_ppBuffer_out, 201, NULL, encoder_portdef.nBufferSize)) != OMX_ErrorNone) { omx_die(r, "Failed to allocate buffer for encoder output port 201"); } // Switch state of the components prior to starting // the video capture and encoding loop //say("Switching state of the camera component to executing..."); if((r = OMX_SendCommand(ctx.camera, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to executing"); } block_until_state_changed(ctx.camera, OMX_StateExecuting); //say("Switching state of the encoder component to executing..."); if((r = OMX_SendCommand(ctx.encoder, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the encoder component to executing"); } block_until_state_changed(ctx.encoder, OMX_StateExecuting); //say("Switching state of the null sink component to executing..."); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the null sink component to executing"); } block_until_state_changed(ctx.null_sink, OMX_StateExecuting); OMX_CONFIG_PORTBOOLEANTYPE capture; OMX_INIT_STRUCTURE(capture); capture.nPortIndex = 71; capture.bEnabled = OMX_TRUE; if((r = OMX_SetParameter(ctx.camera, OMX_IndexConfigPortCapturing, &capture)) != OMX_ErrorNone) { omx_die(r, "Failed to switch on capture on camera video output port 71"); } //say("Configured port definition for camera input port 73"); dump_port(ctx.camera, 73, OMX_FALSE); //say("Configured port definition for camera preview output port 70"); dump_port(ctx.camera, 70, OMX_FALSE); //say("Configured port definition for camera video output port 71"); dump_port(ctx.camera, 71, OMX_FALSE); //say("Configured port definition for encoder input port 200"); dump_port(ctx.encoder, 200, OMX_FALSE); //say("Configured port definition for encoder output port 201"); dump_port(ctx.encoder, 201, OMX_FALSE); //say("Configured port definition for null sink input port 240"); dump_port(ctx.null_sink, 240, OMX_FALSE); //say("Enter capture and encode loop, press Ctrl-C to quit..."); return 1; }
static void configure(struct context *ctx) { pthread_t fpst; pthread_attr_t fpsa; OMX_CONFIG_FRAMERATETYPE *framerate; OMX_VIDEO_PARAM_PROFILELEVELTYPE *level; OMX_VIDEO_PARAM_BITRATETYPE *bitrate; OMX_BUFFERHEADERTYPE *encbufs; OMX_PARAM_PORTDEFINITIONTYPE *portdef, *portimgdef; OMX_VIDEO_PORTDEFINITIONTYPE *viddef; OMX_VIDEO_PARAM_PORTFORMATTYPE *pfmt; OMX_CONFIG_POINTTYPE *pixaspect; int encportidx, decportidx, resizeportidx; OMX_HANDLETYPE m2, m4, resize; encportidx = ctx->encportidx; decportidx = ctx->decportidx; resizeportidx = ctx->resizeportidx; m2 = ctx->m2; m4 = ctx->m4; resize = ctx->resize; MAKEME(portdef, OMX_PARAM_PORTDEFINITIONTYPE); MAKEME(portimgdef, OMX_PARAM_PORTDEFINITIONTYPE); viddef = &portdef->format.video; MAKEME(pixaspect, OMX_CONFIG_POINTTYPE); printf("Decoder has changed settings. Setting up resizer.\n"); /* We need some parameters from de decoder output to put in the resizer: eColorFormat (= YUV42-PackedPlanar) Width of the frame Height of the frame */ portdef->nPortIndex = decportidx+1; OERR(OMX_GetParameter(m2, OMX_IndexParamPortDefinition, portdef), ctx->verbose); portimgdef->nPortIndex = resizeportidx; OERR(OMX_GetParameter(resize, OMX_IndexParamPortDefinition, portimgdef), ctx->verbose); portimgdef->format.image.eColorFormat = portdef->format.video.eColorFormat; portimgdef->format.image.nFrameWidth = portdef->format.video.nFrameWidth; portimgdef->format.image.nFrameHeight = portdef->format.video.nFrameHeight; portimgdef->format.image.nStride = 0; portimgdef->format.image.nSliceHeight = 0; OERR(OMX_SetParameter(resize, OMX_IndexParamPortDefinition, portimgdef), ctx->verbose); // The actual resizing if set at call if(ctx->width) { portimgdef->format.image.nFrameWidth = ctx->width; portimgdef->format.image.nFrameHeight = ctx->height; } portimgdef->format.image.nStride = 0; portimgdef->format.image.nSliceHeight = 0; portimgdef->nPortIndex = resizeportidx+1; OERR(OMX_SetParameter(resize, OMX_IndexParamPortDefinition, portimgdef), ctx->verbose); free (portimgdef); /* Now set the input parameters for the encoder to the scaled height/width */ portdef->format.video.nFrameWidth = portimgdef->format.image.nFrameWidth; portdef->format.video.nFrameHeight = portimgdef->format.image.nFrameHeight; portdef->format.video.nStride = 0; portdef->format.video.nSliceHeight = 0; portdef->nPortIndex = encportidx; OERR(OMX_SetParameter(m4, OMX_IndexParamPortDefinition, portdef), ctx->verbose); /* setup tunnels */ OERR(OMX_SetupTunnel(m2, decportidx+1, resize, resizeportidx), ctx->verbose); OERR(OMX_SetupTunnel(resize, resizeportidx+1, m4, encportidx), ctx->verbose); // OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx->verbose); OERR(OMX_SendCommand(resize, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx->verbose); OERR(OMX_SendCommand(m4, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx->verbose); viddef = &portdef->format.video; if (viddef->nBitrate != 0) { viddef->nBitrate *= 3; viddef->nBitrate /= 4; } else { viddef->nBitrate = (1*1024*1024/2); } // viddef->nBitrate = (2*1024*1024); // viddef->nFrameWidth /= 2; // viddef->nFrameHeight /= 2; viddef->eCompressionFormat = OMX_VIDEO_CodingAVC; viddef->nStride = viddef->nSliceHeight = viddef->eColorFormat = 0; portdef->nPortIndex = encportidx+1; OERR(OMX_SetParameter(m4, OMX_IndexParamPortDefinition, portdef), ctx->verbose); free(portdef); MAKEME(bitrate, OMX_VIDEO_PARAM_BITRATETYPE); bitrate->nPortIndex = encportidx+1; bitrate->eControlRate = OMX_Video_ControlRateVariable; bitrate->nTargetBitrate = viddef->nBitrate; OERR(OMX_SetParameter(m4, OMX_IndexParamVideoBitrate, bitrate), ctx->verbose); free(bitrate); MAKEME(pfmt, OMX_VIDEO_PARAM_PORTFORMATTYPE); pfmt->nPortIndex = encportidx+1; pfmt->nIndex = 0; pfmt->eCompressionFormat = OMX_VIDEO_CodingAVC; pfmt->eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; pfmt->xFramerate = viddef->xFramerate; pixaspect->nPortIndex = encportidx+1; pixaspect->nX = 118; pixaspect->nY = 81; OERR(OMX_SetConfig(m4, OMX_IndexParamBrcmPixelAspectRatio, pixaspect), ctx->verbose); free(pixaspect); // DUMPPORT(m4, encportidx+1); exit(0); pfmt->nPortIndex = encportidx+1; pfmt->nIndex = 1; pfmt->eCompressionFormat = OMX_VIDEO_CodingAVC; pfmt->eColorFormat = 0; pfmt->xFramerate = 0; //viddef->xFramerate; OERR(OMX_SetParameter(m4, OMX_IndexParamVideoPortFormat, pfmt), ctx->verbose); free(pfmt); MAKEME(framerate, OMX_CONFIG_FRAMERATETYPE); framerate->nPortIndex = encportidx+1; framerate->xEncodeFramerate = viddef->xFramerate; OERR(OMX_SetParameter(m4, OMX_IndexConfigVideoFramerate, framerate), ctx->verbose); free(framerate); #if 0 /* Doesn't seem to apply to video? */ printf("Interlacing: %d\n", ic->streams[vidindex]->codec->field_order); if (0 || ic->streams[vidindex]->codec->field_order == AV_FIELD_TT) { interlace->nPortIndex = encportidx+1; interlace->eMode = OMX_InterlaceFieldsInterleavedUpperFirst; interlace->bRepeatFirstField = 0; OERR(OMX_SetParameter(m4, OMX_IndexConfigCommonInterlace, interlace), ctx->verbose); } #endif MAKEME(level, OMX_VIDEO_PARAM_PROFILELEVELTYPE); level->nPortIndex = encportidx+1; OERR(OMX_GetParameter(m4, OMX_IndexParamVideoProfileLevelCurrent, level), ctx->verbose); if (ctx->verbose) printf("Current level:\t\t%d\nCurrent profile:\t%d\n", level->eLevel, level->eProfile); OERR(OMX_SetParameter(m4, OMX_IndexParamVideoProfileLevelCurrent, level), ctx->verbose); free(level); ctx->encbufs = encbufs = allocbufs(m4, encportidx+1, 1); OERR(OMX_SendCommand(m2, OMX_CommandPortEnable, decportidx+1, NULL), ctx->verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortEnable, resizeportidx, NULL), ctx->verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortEnable, resizeportidx+1, NULL), ctx->verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortEnable, encportidx, NULL), ctx->verbose); OERR(OMX_SendCommand(m4, OMX_CommandStateSet, OMX_StateExecuting, NULL), ctx->verbose); OERR(OMX_SendCommand(resize, OMX_CommandStateSet, OMX_StateExecuting, NULL), ctx->verbose); sleep(1); OERR(OMX_FillThisBuffer(m4, encbufs), ctx->verbose); /* Dump current port states: */ if (ctx->verbose) { dumpport(m2, decportidx); dumpport(m2, decportidx+1); dumpport(resize, resizeportidx); dumpport(resize, resizeportidx+1); dumpport(m4, encportidx); dumpport(m4, encportidx+1); } if (ctx->verbose) atexit(dumpportstate); pthread_attr_init(&fpsa); pthread_attr_setdetachstate(&fpsa, PTHREAD_CREATE_DETACHED); pthread_create(&fpst, &fpsa, fps, NULL); }
void *video_decode_test(void* arg) { bcm_host_init(); CUBE_STATE_T *state = (CUBE_STATE_T *)arg; OMX_ERRORTYPE r; if((r = OMX_Init()) != OMX_ErrorNone) { omx_die(r, "OMX initalization failed"); } // Init context appctx ctx; memset(&ctx, 0, sizeof(ctx)); if(vcos_semaphore_create(&ctx.handler_lock, "handler_lock", 1) != VCOS_SUCCESS) { die("Failed to create handler lock semaphore"); } ctx.eglImage = state->eglImage; // Init component handles OMX_CALLBACKTYPE callbacks; memset(&ctx, 0, sizeof(callbacks)); callbacks.EventHandler = event_handler; callbacks.FillBufferDone = my_fill_buffer_done; init_component_handle("camera", &ctx.camera , &ctx, &callbacks); init_component_handle("egl_render", &ctx.render, &ctx, &callbacks); init_component_handle("null_sink", &ctx.null_sink, &ctx, &callbacks); init_component_handle("clock", &ctx.clock, &ctx, &callbacks); OMX_U32 screen_width = state->screen_width, screen_height = state->screen_height; if(graphics_get_display_size(DISPLAY_DEVICE, &screen_width, &screen_height) < 0) { die("Failed to get display size"); } say("Configuring camera..."); dump_port(ctx.clock, 80, OMX_TRUE); say("Default port definition for camera input port 73"); dump_port(ctx.camera, 73, OMX_TRUE); say("Default port definition for camera preview output port 70"); dump_port(ctx.camera, 70, OMX_TRUE); say("Default port definition for camera video output port 71"); dump_port(ctx.camera, 71, OMX_TRUE); OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; OMX_INIT_STRUCTURE(cstate); cstate.eState = OMX_TIME_ClockStateRunning; cstate.nWaitMask = 1; if((r = OMX_SetConfig(ctx.clock, OMX_IndexConfigTimeClockState, &cstate)) != OMX_ErrorNone) { omx_die(r, "Failed to request camera device number parameter change callback for camera"); } // Request a callback to be made when OMX_IndexParamCameraDeviceNumber is // changed signaling that the camera device is ready for use. OMX_CONFIG_REQUESTCALLBACKTYPE cbtype; OMX_INIT_STRUCTURE(cbtype); cbtype.nPortIndex = OMX_ALL; cbtype.nIndex = OMX_IndexParamCameraDeviceNumber; cbtype.bEnable = OMX_TRUE; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigRequestCallback, &cbtype)) != OMX_ErrorNone) { omx_die(r, "Failed to request camera device number parameter change callback for camera"); } // Set device number, this triggers the callback configured just above OMX_PARAM_U32TYPE device; OMX_INIT_STRUCTURE(device); device.nPortIndex = OMX_ALL; device.nU32 = CAM_DEVICE_NUMBER; if((r = OMX_SetParameter(ctx.camera, OMX_IndexParamCameraDeviceNumber, &device)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera parameter device number"); } // Configure video format emitted by camera preview output port OMX_PARAM_PORTDEFINITIONTYPE camera_portdef; OMX_INIT_STRUCTURE(camera_portdef); camera_portdef.nPortIndex = 70; if((r = OMX_GetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to get port definition for camera preview output port 70"); } camera_portdef.format.video.nFrameWidth = state->screen_width; camera_portdef.format.video.nFrameHeight = state->screen_height; camera_portdef.format.video.xFramerate = VIDEO_FRAMERATE << 16; // Stolen from gstomxvideodec.c of gst-omx camera_portdef.format.video.nStride = (camera_portdef.format.video.nFrameWidth + camera_portdef.nBufferAlignment - 1) & (~(camera_portdef.nBufferAlignment - 1)); camera_portdef.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; if((r = OMX_SetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to set port definition for camera preview output port 70"); } // Configure video format emitted by camera video output port // Use configuration from camera preview output as basis for // camera video output configuration OMX_INIT_STRUCTURE(camera_portdef); camera_portdef.nPortIndex = 70; if((r = OMX_GetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to get port definition for camera preview output port 70"); } camera_portdef.nPortIndex = 71; if((r = OMX_SetParameter(ctx.camera, OMX_IndexParamPortDefinition, &camera_portdef)) != OMX_ErrorNone) { omx_die(r, "Failed to set port definition for camera video output port 71"); } // Configure frame rate OMX_CONFIG_FRAMERATETYPE framerate; OMX_INIT_STRUCTURE(framerate); framerate.nPortIndex = 70; framerate.xEncodeFramerate = camera_portdef.format.video.xFramerate; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigVideoFramerate, &framerate)) != OMX_ErrorNone) { omx_die(r, "Failed to set framerate configuration for camera preview output port 70"); } framerate.nPortIndex = 71; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigVideoFramerate, &framerate)) != OMX_ErrorNone) { omx_die(r, "Failed to set framerate configuration for camera video output port 71"); } // Configure sharpness OMX_CONFIG_SHARPNESSTYPE sharpness; OMX_INIT_STRUCTURE(sharpness); sharpness.nPortIndex = OMX_ALL; sharpness.nSharpness = CAM_SHARPNESS; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonSharpness, &sharpness)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera sharpness configuration"); } // Configure contrast OMX_CONFIG_CONTRASTTYPE contrast; OMX_INIT_STRUCTURE(contrast); contrast.nPortIndex = OMX_ALL; contrast.nContrast = CAM_CONTRAST; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonContrast, &contrast)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera contrast configuration"); } // Configure saturation OMX_CONFIG_SATURATIONTYPE saturation; OMX_INIT_STRUCTURE(saturation); saturation.nPortIndex = OMX_ALL; saturation.nSaturation = CAM_SATURATION; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonSaturation, &saturation)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera saturation configuration"); } // Configure brightness OMX_CONFIG_BRIGHTNESSTYPE brightness; OMX_INIT_STRUCTURE(brightness); brightness.nPortIndex = OMX_ALL; brightness.nBrightness = CAM_BRIGHTNESS; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonBrightness, &brightness)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera brightness configuration"); } // Configure exposure value OMX_CONFIG_EXPOSUREVALUETYPE exposure_value; OMX_INIT_STRUCTURE(exposure_value); exposure_value.nPortIndex = OMX_ALL; exposure_value.xEVCompensation = CAM_EXPOSURE_VALUE_COMPENSTAION; exposure_value.bAutoSensitivity = CAM_EXPOSURE_AUTO_SENSITIVITY; exposure_value.bAutoShutterSpeed = OMX_TRUE; // exposure_value.nShutterSpeedMsec = 10; exposure_value.nSensitivity = CAM_EXPOSURE_ISO_SENSITIVITY; exposure_value.eMetering = OMX_MeteringModeAverage; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonExposureValue, &exposure_value)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera exposure value configuration"); } OMX_CONFIG_EXPOSURECONTROLTYPE exposure; OMX_INIT_STRUCTURE(exposure); exposure.nPortIndex = OMX_ALL; exposure.eExposureControl = OMX_ExposureControlAuto; OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonExposure, &exposure); // Configure frame frame stabilisation OMX_CONFIG_FRAMESTABTYPE frame_stabilisation_control; OMX_INIT_STRUCTURE(frame_stabilisation_control); frame_stabilisation_control.nPortIndex = OMX_ALL; frame_stabilisation_control.bStab = CAM_FRAME_STABILISATION; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonFrameStabilisation, &frame_stabilisation_control)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera frame frame stabilisation control configuration"); } // Configure frame white balance control /* OMX_CONFIG_LIGHTNESSTYPE lightness_control; OMX_INIT_STRUCTURE(lightness_control); lightness_control.nPortIndex = OMX_ALL; lightness_control.nLightness = 0; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonLightness, &lightness_control)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera frame white balance control configuration"); }*/ // Configure frame white balance control OMX_CONFIG_WHITEBALCONTROLTYPE white_balance_control; OMX_INIT_STRUCTURE(white_balance_control); white_balance_control.nPortIndex = OMX_ALL; white_balance_control.eWhiteBalControl = CAM_WHITE_BALANCE_CONTROL; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonWhiteBalance, &white_balance_control)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera frame white balance control configuration"); } // Configure image filter OMX_CONFIG_IMAGEFILTERTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = OMX_ALL; image_filter.eImageFilter = CAM_IMAGE_FILTER; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonImageFilter, &image_filter)) != OMX_ErrorNone) { omx_die(r, "Failed to set camera image filter configuration"); } /* Set colour effect */ OMX_CONFIG_COLORENHANCEMENTTYPE colour; OMX_INIT_STRUCTURE(colour); colour.nPortIndex = OMX_ALL; colour.bColorEnhancement = OMX_FALSE; colour.nCustomizedU = 128; colour.nCustomizedV = 128; OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonColorEnhancement, &colour); // Configure mirror OMX_MIRRORTYPE eMirror = OMX_MirrorNone; if(CAM_FLIP_HORIZONTAL && !CAM_FLIP_VERTICAL) { eMirror = OMX_MirrorHorizontal; } else if(!CAM_FLIP_HORIZONTAL && CAM_FLIP_VERTICAL) { eMirror = OMX_MirrorVertical; } else if(CAM_FLIP_HORIZONTAL && CAM_FLIP_VERTICAL) { eMirror = OMX_MirrorBoth; } OMX_CONFIG_MIRRORTYPE mirror; OMX_INIT_STRUCTURE(mirror); mirror.nPortIndex = 71; mirror.eMirror = eMirror; if((r = OMX_SetConfig(ctx.camera, OMX_IndexConfigCommonMirror, &mirror)) != OMX_ErrorNone) { omx_die(r, "Failed to set mirror configuration for camera video output port 71"); } // Ensure camera is ready while(!ctx.camera_ready) { usleep(10000); } say("Configuring render..."); say("Default port definition for render input port 90"); dump_port(ctx.render, 220, OMX_TRUE); // Render input port definition is done automatically upon tunneling say("Configuring null sink..."); say("Default port definition for null sink input port 240"); dump_port(ctx.null_sink, 240, OMX_TRUE); // Null sink input port definition is done automatically upon tunneling // Tunnel camera preview output port and null sink input port say("Setting up tunnel from camera preview output port 70 to null sink input port 240..."); if((r = OMX_SetupTunnel(ctx.clock, 80, ctx.camera, 73)) != OMX_ErrorNone) { omx_die(r, "Failed to setup tunnel between camera preview output port 70 and null sink input port 240"); } // Tunnel camera preview output port and null sink input port say("Setting up tunnel from camera preview output port 70 to null sink input port 240..."); if((r = OMX_SetupTunnel(ctx.camera, 70, ctx.null_sink, 240)) != OMX_ErrorNone) { omx_die(r, "Failed to setup tunnel between camera preview output port 70 and null sink input port 240"); } // Tunnel camera video output port and render input port say("Setting up tunnel from camera video output port 71 to render input port 220..."); if((r = OMX_SetupTunnel(ctx.camera, 71, ctx.render, 220)) != OMX_ErrorNone) { omx_die(r, "Failed to setup tunnel between camera video output port 71 and render input port 90"); } // Switch components to idle state say("Switching state of the camera component to idle..."); if((r = OMX_SendCommand(ctx.clock, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to idle"); } block_until_state_changed(ctx.clock, OMX_StateIdle); say("Switching state of the camera component to idle..."); if((r = OMX_SendCommand(ctx.camera, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to idle"); } block_until_state_changed(ctx.camera, OMX_StateIdle); say("Switching state of the render component to idle..."); if((r = OMX_SendCommand(ctx.render, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the render component to idle"); } block_until_state_changed(ctx.render, OMX_StateIdle); say("Switching state of the null sink component to idle..."); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the null sink component to idle"); } block_until_state_changed(ctx.null_sink, OMX_StateIdle); // Enable ports say("Enabling ports..."); if((r = OMX_SendCommand(ctx.clock, OMX_CommandPortEnable, 80, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable camera input port 73"); } block_until_port_changed(ctx.clock, 80, OMX_TRUE); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortEnable, 73, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable camera input port 73"); } block_until_port_changed(ctx.camera, 73, OMX_TRUE); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortEnable, 70, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable camera preview output port 70"); } block_until_port_changed(ctx.camera, 70, OMX_TRUE); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortEnable, 71, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable camera video output port 71"); } block_until_port_changed(ctx.camera, 71, OMX_TRUE); if((r = OMX_SendCommand(ctx.render, OMX_CommandPortEnable, 220, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable render input port 220"); } block_until_port_changed(ctx.render, 220, OMX_TRUE); if((r = OMX_SendCommand(ctx.render, OMX_CommandPortEnable, 221, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable render input port 221"); } block_until_port_changed(ctx.render, 220, OMX_TRUE); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandPortEnable, 240, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to enable null sink input port 240"); } block_until_port_changed(ctx.null_sink, 240, OMX_TRUE); // Allocate camera input buffer, buffers for tunneled // ports are allocated internally by OMX if((r = OMX_UseEGLImage(ctx.render, &ctx.eglBuffer, 221, NULL, ctx.eglImage)) != OMX_ErrorNone) { omx_die(r, "Failed to use eglimage"); } // Switch state of the components prior to starting // the video capture and encoding loop say("Switching state of the camera component to executing..."); if((r = OMX_SendCommand(ctx.clock, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to executing"); } say("Switching state of the camera component to executing..."); if((r = OMX_SendCommand(ctx.camera, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to executing"); } block_until_state_changed(ctx.camera, OMX_StateExecuting); say("Switching state of the render component to executing..."); if((r = OMX_SendCommand(ctx.render, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the render component to executing"); } block_until_state_changed(ctx.render, OMX_StateExecuting); say("Switching state of the null sink component to executing..."); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandStateSet, OMX_StateExecuting, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the null sink component to executing"); } block_until_state_changed(ctx.null_sink, OMX_StateExecuting); // Start capturing video with the camera say("Switching on capture on camera video output port 71..."); OMX_CONFIG_PORTBOOLEANTYPE capture; OMX_INIT_STRUCTURE(capture); capture.nPortIndex = 71; capture.bEnabled = OMX_TRUE; if((r = OMX_SetParameter(ctx.camera, OMX_IndexConfigPortCapturing, &capture)) != OMX_ErrorNone) { omx_die(r, "Failed to switch on capture on camera video output port 71"); } say("Configured port definition for camera input port 73"); dump_port(ctx.camera, 73, OMX_FALSE); say("Configured port definition for camera preview output port 70"); dump_port(ctx.camera, 70, OMX_FALSE); say("Configured port definition for camera video output port 71"); dump_port(ctx.camera, 71, OMX_FALSE); say("Configured port definition for render input port 90"); dump_port(ctx.render, 220, OMX_FALSE); say("Configured port definition for null sink input port 240"); dump_port(ctx.null_sink, 240, OMX_FALSE); say("Enter capture and playback loop, press Ctrl-C to quit..."); if((r = OMX_FillThisBuffer(ctx.render, ctx.eglBuffer)) != OMX_ErrorNone) { omx_die(r, "Failed to fill buffer"); } signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGQUIT, signal_handler); while(!want_quit) { // Would be better to use signaling here but hey this works too usleep(1000); } say("Cleaning up..."); // Restore signal handlers signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGQUIT, SIG_DFL); // Stop capturing video with the camera OMX_INIT_STRUCTURE(capture); capture.nPortIndex = 71; capture.bEnabled = OMX_FALSE; if((r = OMX_SetParameter(ctx.camera, OMX_IndexConfigPortCapturing, &capture)) != OMX_ErrorNone) { omx_die(r, "Failed to switch off capture on camera video output port 71"); } // Flush the buffers on each component if((r = OMX_SendCommand(ctx.camera, OMX_CommandFlush, 73, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to flush buffers of camera input port 73"); } block_until_flushed(&ctx); if((r = OMX_SendCommand(ctx.camera, OMX_CommandFlush, 70, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to flush buffers of camera preview output port 70"); } block_until_flushed(&ctx); if((r = OMX_SendCommand(ctx.camera, OMX_CommandFlush, 71, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to flush buffers of camera video output port 71"); } block_until_flushed(&ctx); if((r = OMX_SendCommand(ctx.render, OMX_CommandFlush, 220, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to flush buffers of render input port 220"); } block_until_flushed(&ctx); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandFlush, 240, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to flush buffers of null sink input port 240"); } block_until_flushed(&ctx); // Disable all the ports if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortDisable, 73, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to disable camera input port 73"); } block_until_port_changed(ctx.camera, 73, OMX_FALSE); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortDisable, 70, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to disable camera preview output port 70"); } block_until_port_changed(ctx.camera, 70, OMX_FALSE); if((r = OMX_SendCommand(ctx.camera, OMX_CommandPortDisable, 71, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to disable camera video output port 71"); } block_until_port_changed(ctx.camera, 71, OMX_FALSE); if((r = OMX_SendCommand(ctx.render, OMX_CommandPortDisable, 220, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to disable render input port 90"); } if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandPortDisable, 240, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to disable null sink input port 240"); } block_until_port_changed(ctx.null_sink, 240, OMX_FALSE); // Free all the buffers if((r = OMX_FreeBuffer(ctx.camera, 73, ctx.camera_ppBuffer_in)) != OMX_ErrorNone) { omx_die(r, "Failed to free buffer for camera input port 73"); } // Transition all the components to idle and then to loaded states if((r = OMX_SendCommand(ctx.camera, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to idle"); } block_until_state_changed(ctx.camera, OMX_StateIdle); if((r = OMX_SendCommand(ctx.render, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the render component to idle"); } block_until_state_changed(ctx.render, OMX_StateIdle); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandStateSet, OMX_StateIdle, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the null sink component to idle"); } block_until_state_changed(ctx.null_sink, OMX_StateIdle); if((r = OMX_SendCommand(ctx.camera, OMX_CommandStateSet, OMX_StateLoaded, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the camera component to loaded"); } block_until_state_changed(ctx.camera, OMX_StateLoaded); if((r = OMX_SendCommand(ctx.render, OMX_CommandStateSet, OMX_StateLoaded, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the render component to loaded"); } block_until_state_changed(ctx.render, OMX_StateLoaded); if((r = OMX_SendCommand(ctx.null_sink, OMX_CommandStateSet, OMX_StateLoaded, NULL)) != OMX_ErrorNone) { omx_die(r, "Failed to switch state of the null sink component to loaded"); } block_until_state_changed(ctx.null_sink, OMX_StateLoaded); // Free the component handles if((r = OMX_FreeHandle(ctx.camera)) != OMX_ErrorNone) { omx_die(r, "Failed to free camera component handle"); } if((r = OMX_FreeHandle(ctx.render)) != OMX_ErrorNone) { omx_die(r, "Failed to free render component handle"); } if((r = OMX_FreeHandle(ctx.null_sink)) != OMX_ErrorNone) { omx_die(r, "Failed to free null sink component handle"); } // Exit vcos_semaphore_delete(&ctx.handler_lock); if((r = OMX_Deinit()) != OMX_ErrorNone) { omx_die(r, "OMX de-initalization failed"); } say("Exit!"); return 0; }
CTunnel(CComponentPort* pSource, CComponentPort* pSink) { OMX_HANDLETYPE hSource = pSource ? pSource->m_hComponent : 0, hSink = pSink ? pSink->m_hComponent : 0; unsigned int nSourcePort = pSource ? pSource->m_nId : 0, nSinkPort = pSink ? pSink->m_nId : 0; CHECK_OMX(OMX_SetupTunnel(hSource, nSourcePort, hSink, nSinkPort), "failed to setup tunnel"); }
OMXCAM_ERROR OMXCAM_still (OMXCAM_STILL_SETTINGS* settings){ OMXCAM_trace ("Capturing still"); if (!settings->bufferCallback){ OMXCAM_error ("The 'bufferCallback' field must be defined"); return OMXCAM_ErrorBadParameter; } OMXCAM_ERROR err; if ((err = OMXCAM_init ())) return err; int useEncoder; OMX_COLOR_FORMATTYPE colorFormat; OMX_U32 stride; OMXCAM_COMPONENT* fillComponent; OMX_ERRORTYPE error; //Stride is byte-per-pixel*width //See mmal/util/mmal_util.c, mmal_encoding_width_to_stride() switch (settings->format){ case OMXCAM_FormatRGB888: OMXCAM_ctx.camera.bufferCallback = settings->bufferCallback; useEncoder = 0; colorFormat = OMX_COLOR_Format24bitRGB888; stride = settings->camera.width*3; fillComponent = &OMXCAM_ctx.camera; break; case OMXCAM_FormatRGBA8888: OMXCAM_ctx.camera.bufferCallback = settings->bufferCallback; useEncoder = 0; colorFormat = OMX_COLOR_Format32bitABGR8888; stride = settings->camera.width*4; fillComponent = &OMXCAM_ctx.camera; break; case OMXCAM_FormatYUV420: OMXCAM_ctx.camera.bufferCallback = settings->bufferCallback; useEncoder = 0; colorFormat = OMX_COLOR_FormatYUV420PackedPlanar; stride = settings->camera.width; fillComponent = &OMXCAM_ctx.camera; break; case OMXCAM_FormatJPEG: OMXCAM_ctx.image_encode.bufferCallback = settings->bufferCallback; useEncoder = 1; colorFormat = OMX_COLOR_FormatYUV420PackedPlanar; stride = settings->camera.width; fillComponent = &OMXCAM_ctx.image_encode; break; default: return OMXCAM_ErrorFormat; } if (OMXCAM_initComponent (&OMXCAM_ctx.camera)){ return OMXCAM_ErrorInitCamera; } if (useEncoder && OMXCAM_initComponent (&OMXCAM_ctx.image_encode)){ return OMXCAM_ErrorInitImageEncoder; } if (OMXCAM_loadCameraDrivers ()) return OMXCAM_ErrorInitCamera; //Configure camera sensor OMXCAM_trace ("Configuring '%s' sensor", OMXCAM_ctx.camera.name); OMX_PARAM_SENSORMODETYPE sensor; OMX_INIT_STRUCTURE (sensor); sensor.nPortIndex = OMX_ALL; OMX_INIT_STRUCTURE (sensor.sFrameSize); sensor.sFrameSize.nPortIndex = OMX_ALL; if ((error = OMX_GetParameter (OMXCAM_ctx.camera.handle, OMX_IndexParamCommonSensorMode, &sensor))){ OMXCAM_error ("OMX_GetParameter - OMX_IndexParamCommonSensorMode: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorInitCamera; } sensor.bOneShot = OMX_TRUE; //sensor.sFrameSize.nWidth and sensor.sFrameSize.nHeight can be ignored, //they are configured with the port definition if ((error = OMX_SetParameter (OMXCAM_ctx.camera.handle, OMX_IndexParamCommonSensorMode, &sensor))){ OMXCAM_error ("OMX_SetParameter - OMX_IndexParamCommonSensorMode: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorInitCamera; } //Change to Idle if (changeStillState (OMX_StateIdle, useEncoder)){ return OMXCAM_ErrorIdle; } //Configure camera port definition OMXCAM_trace ("Configuring '%s' port definition", OMXCAM_ctx.camera.name); OMX_PARAM_PORTDEFINITIONTYPE def; OMX_INIT_STRUCTURE (def); def.nPortIndex = 72; if ((error = OMX_GetParameter (OMXCAM_ctx.camera.handle, OMX_IndexParamPortDefinition, &def))){ OMXCAM_error ("OMX_GetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorStill; } def.format.image.nFrameWidth = settings->camera.width; def.format.image.nFrameHeight = settings->camera.height; def.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused; def.format.image.eColorFormat = colorFormat; //TODO: stride, sliceHeight? http://www.raspberrypi.org/phpBB3/viewtopic.php?f=28&t=22019 def.format.image.nStride = stride; if ((error = OMX_SetParameter (OMXCAM_ctx.camera.handle, OMX_IndexParamPortDefinition, &def))){ OMXCAM_error ("OMX_SetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorBadParameter; } //Configure camera settings if (OMXCAM_setCameraSettings (&settings->camera)){ return OMXCAM_ErrorBadParameter; } if (useEncoder){ OMXCAM_trace ("Configuring '%s' port definition", OMXCAM_ctx.image_encode.name); OMX_INIT_STRUCTURE (def); def.nPortIndex = 341; if ((error = OMX_GetParameter (OMXCAM_ctx.image_encode.handle, OMX_IndexParamPortDefinition, &def))){ OMXCAM_error ("OMX_GetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorStill; } def.format.image.nFrameWidth = settings->camera.width; def.format.image.nFrameHeight = settings->camera.height; def.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG; def.format.image.eColorFormat = OMX_COLOR_FormatUnused; if ((error = OMX_SetParameter (OMXCAM_ctx.image_encode.handle, OMX_IndexParamPortDefinition, &def))){ OMXCAM_error ("OMX_SetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorBadParameter; } //Configure JPEG settings if (OMXCAM_setJpegSettings (&settings->jpeg)){ return OMXCAM_ErrorBadParameter; } //Setup tunnel: camera (still) -> image_encode OMXCAM_trace ("Configuring tunnel '%s' -> '%s'", OMXCAM_ctx.camera.name, OMXCAM_ctx.image_encode.name); if ((error = OMX_SetupTunnel (OMXCAM_ctx.camera.handle, 72, OMXCAM_ctx.image_encode.handle, 340))){ OMXCAM_error ("OMX_SetupTunnel: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorSetupTunnel; } } //Enable the ports if (OMXCAM_enablePort (&OMXCAM_ctx.camera, 72)){ return OMXCAM_ErrorStill; } if (!useEncoder && OMXCAM_allocateBuffer (&OMXCAM_ctx.camera, 72)){ return OMXCAM_ErrorStill; } if (OMXCAM_wait (&OMXCAM_ctx.camera, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorStill; } if (useEncoder){ if (OMXCAM_enablePort (&OMXCAM_ctx.image_encode, 340)){ return OMXCAM_ErrorStill; } if (OMXCAM_wait (&OMXCAM_ctx.image_encode, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorStill; } if (OMXCAM_enablePort (&OMXCAM_ctx.image_encode, 341)){ return OMXCAM_ErrorStill; } if (OMXCAM_allocateBuffer (&OMXCAM_ctx.image_encode, 341)){ return OMXCAM_ErrorStill; } if (OMXCAM_wait (&OMXCAM_ctx.image_encode, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorStill; } } //Change to Executing if (changeStillState (OMX_StateExecuting, useEncoder)){ return OMXCAM_ErrorExecuting; } //Set camera capture port if (OMXCAM_setCapturePort (72)){ return OMXCAM_ErrorStill; } //Start consuming the buffers VCOS_UNSIGNED endFlags = OMXCAM_EventBufferFlag | OMXCAM_EventFillBufferDone; VCOS_UNSIGNED retrievedEvents; while (1){ //Get the buffer data (a slice of the image) if ((error = OMX_FillThisBuffer (fillComponent->handle, OMXCAM_ctx.outputBuffer))){ OMXCAM_error ("OMX_FillThisBuffer: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorStill; } //Wait until it's filled if (OMXCAM_wait (fillComponent, OMXCAM_EventFillBufferDone, &retrievedEvents)){ return OMXCAM_ErrorStill; } //Emit the buffer if (OMXCAM_ctx.outputBuffer->nFilledLen){ settings->bufferCallback (OMXCAM_ctx.outputBuffer->pBuffer, OMXCAM_ctx.outputBuffer->nFilledLen); } //When it's the end of the stream, an OMX_EventBufferFlag is emitted in all //the components in use. Then the FillBufferDone function is called in the //last component in the component's chain if (retrievedEvents == endFlags){ //Clear the EOS flags if (OMXCAM_wait (&OMXCAM_ctx.camera, OMXCAM_EventBufferFlag, 0)){ return OMXCAM_ErrorStill; } if (useEncoder && OMXCAM_wait (&OMXCAM_ctx.image_encode, OMXCAM_EventBufferFlag, 0)){ return OMXCAM_ErrorStill; } break; } } //Reset camera capture port if (OMXCAM_resetCapturePort (72)){ return OMXCAM_ErrorStill; } //Change to Idle if (changeStillState (OMX_StateIdle, useEncoder)){ return OMXCAM_ErrorIdle; } //Disable the ports if (OMXCAM_disablePort (&OMXCAM_ctx.camera, 72)){ return OMXCAM_ErrorStill; } if (!useEncoder && OMXCAM_freeBuffer (&OMXCAM_ctx.camera, 72)){ return OMXCAM_ErrorStill; } if (OMXCAM_wait (&OMXCAM_ctx.camera, OMXCAM_EventPortDisable, 0)){ return OMXCAM_ErrorStill; } if (useEncoder){ if (OMXCAM_disablePort (&OMXCAM_ctx.image_encode, 340)){ return OMXCAM_ErrorStill; } if (OMXCAM_wait (&OMXCAM_ctx.image_encode, OMXCAM_EventPortDisable, 0)){ return OMXCAM_ErrorStill; } if (OMXCAM_disablePort (&OMXCAM_ctx.image_encode, 341)){ return OMXCAM_ErrorStill; } if (OMXCAM_freeBuffer (&OMXCAM_ctx.image_encode, 341)){ return OMXCAM_ErrorStill; } if (OMXCAM_wait (&OMXCAM_ctx.image_encode, OMXCAM_EventPortDisable, 0)){ return OMXCAM_ErrorStill; } } //Change to Loaded if (changeStillState (OMX_StateLoaded, useEncoder)){ return OMXCAM_ErrorLoaded; } if (OMXCAM_deinitComponent (&OMXCAM_ctx.camera)){ return OMXCAM_ErrorDeinitCamera; } if (useEncoder && OMXCAM_deinitComponent (&OMXCAM_ctx.image_encode)){ return OMXCAM_ErrorDeinitImageEncoder; } return OMXCAM_deinit (); }
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; }
OMX_ERRORTYPE Tunnel::Deestablish(string caller) { string debugString = sourceComponent->getName() + " : " + destinationComponent->getName(); ofLogVerbose(__func__)<< " caller: " << caller << " components: " << debugString; if (!isEstablished) { return OMX_ErrorNone; } if(!sourceComponent || !destinationComponent) { return OMX_ErrorUndefined; } lock(); OMX_ERRORTYPE error = OMX_ErrorNone; if(havePortSettingsChanged) { error = sourceComponent->waitForEvent(OMX_EventPortSettingsChanged); OMX_TRACE(error); } bool didTearDownTunnel = sourceComponent->tunnelToNull(sourcePort); didTearDownTunnel = destinationComponent->tunnelToNull(destinationPort); #if 0 error = sourceComponent->disableAllPorts(); OMX_TRACE(error, debugString); error = destinationComponent->disableAllPorts(); OMX_TRACE(error, debugString); error = sourceComponent->disablePort(sourcePort); OMX_TRACE(error); error = destinationComponent->disablePort(destinationPort); OMX_TRACE(error, debugString); sourceComponent->setToStateLoaded(); destinationComponent->setToStateLoaded(); error = OMX_SetupTunnel(destinationComponent->getHandle(), destinationPort, NULL, 0); OMX_TRACE(error, debugString); if(error == OMX_ErrorNone) { ofLogVerbose(__func__) << destinationComponent->getName() << " TUNNELED TO NULL SUCCESS"; }else { ofLogVerbose(__func__) << destinationComponent->getName() << " TUNNELED TO NULL FAIL"; if(error == OMX_ErrorIncorrectStateOperation) { ofLogVerbose(__func__) << GetOMXStateString(destinationComponent->getState()); } } error = OMX_SetupTunnel(sourceComponent->getHandle(), sourcePort, NULL, 0); OMX_TRACE(error, debugString); if(error == OMX_ErrorNone) { ofLogVerbose(__func__) << sourceComponent->getName() << " TUNNELED TO NULL SUCCESS"; }else { ofLogVerbose(__func__) << sourceComponent->getName() << " TUNNELED TO NULL FAIL"; if(error == OMX_ErrorIncorrectStateOperation) { ofLogVerbose(__func__) << GetOMXStateString(sourceComponent->getState()); } } #endif unlock(); isEstablished = false; return error; }
OMX_ERRORTYPE Tunnel::Establish(bool portSettingsChanged) { lock(); OMX_ERRORTYPE error = OMX_ErrorNone; OMX_PARAM_U32TYPE param; OMX_INIT_STRUCTURE(param); if(!sourceComponent || !destinationComponent || !sourceComponent->getHandle() || !destinationComponent->getHandle()) { unlock(); return OMX_ErrorUndefined; } error = sourceComponent->setState(OMX_StateIdle); OMX_TRACE(error); if(error != OMX_ErrorNone) { unlock(); return error; } #ifdef DEBUG_TUNNELS ofLogVerbose(__func__) << sourceComponent->getName() << " TUNNELING TO " << destinationComponent->getName(); ofLogVerbose(__func__) << "portSettingsChanged: " << portSettingsChanged; #endif if(portSettingsChanged) { error = sourceComponent->waitForEvent(OMX_EventPortSettingsChanged); OMX_TRACE(error); if(error != OMX_ErrorNone) { unlock(); return error; } } error = sourceComponent->disablePort(sourcePort); OMX_TRACE(error); error = destinationComponent->disablePort(destinationPort); OMX_TRACE(error); error = OMX_SetupTunnel(sourceComponent->getHandle(), sourcePort, destinationComponent->getHandle(), destinationPort); OMX_TRACE(error); if(error != OMX_ErrorNone) { unlock(); return error; } else { isEstablished =true; } error = sourceComponent->enablePort(sourcePort); OMX_TRACE(error); if(error != OMX_ErrorNone) { unlock(); return error; } error = destinationComponent->enablePort(destinationPort); OMX_TRACE(error); if(error != OMX_ErrorNone) { unlock(); return error; } if(destinationComponent->getState() == OMX_StateLoaded) { //important to wait for audio error = destinationComponent->waitForCommand(OMX_CommandPortEnable, destinationPort); OMX_TRACE(error); if(error != OMX_ErrorNone) { unlock(); return error; } error = destinationComponent->setState(OMX_StateIdle); OMX_TRACE(error); if(error != OMX_ErrorNone) { unlock(); return error; } } error = sourceComponent->waitForCommand(OMX_CommandPortEnable, sourcePort); if(error != OMX_ErrorNone) { unlock(); return error; } havePortSettingsChanged = portSettingsChanged; unlock(); return error; }
void omx_teardown_pipeline(struct omx_pipeline_t* pipe) { OMX_BUFFERHEADERTYPE *buf; int i=1; DEBUGF("[vcodec] omx_teardown pipeline:\n"); DEBUGF("pipe->video_decode.port_settings_changed = %d\n",pipe->video_decode.port_settings_changed); DEBUGF("pipe->image_fx.port_settings_changed = %d\n",pipe->image_fx.port_settings_changed); DEBUGF("pipe->video_scheduler.port_settings_changed = %d\n",pipe->video_scheduler.port_settings_changed); //dumpport(pipe->video_decode.h,130); #if 0 /* Indicate end of video stream */ buf = get_next_buffer(&pipe->video_decode); buf->nFilledLen = 0; buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; OERR(OMX_EmptyThisBuffer(pipe->video_decode.h, buf)); /* NOTE: Three events are sent after the previous command: [EVENT] Got an event of type 4 on video_decode 0x426a10 (d1: 83, d2 1) [EVENT] Got an event of type 4 on video_scheduler 0x430d10 (d1: b, d2 1) [EVENT] Got an event of type 4 on video_render 0x430b30 (d1: 5a, d2 1) 5a = port (90) 1 = OMX_BUFFERFLAG_EOS */ #endif #if 0 DEBUGF("[vcodec] omx_teardown pipeline 2\n"); /* Wait for video_decode to shutdown */ pthread_mutex_lock(&pipe->video_decode.eos_mutex); while (!pipe->video_decode.eos) pthread_cond_wait(&pipe->video_decode.eos_cv,&pipe->video_decode.eos_mutex); pthread_mutex_unlock(&pipe->video_decode.eos_mutex); #endif DEBUGF("[vcodec] omx_teardown pipeline 1\n"); /* Transition all components to Idle, if they have been initialised */ omx_send_command_and_wait(&pipe->video_decode, OMX_CommandStateSet, OMX_StateIdle, NULL); omx_send_command_and_wait(&pipe->clock, OMX_CommandStateSet, OMX_StateIdle, NULL); DEBUGF("pipe->do_deinterlace=%d, pipe->image_fx=%d\n",pipe->do_deinterlace,(int)pipe->image_fx.h); if (pipe->video_decode.port_settings_changed == 2) { if (pipe->do_deinterlace) { omx_send_command_and_wait(&pipe->image_fx, OMX_CommandStateSet, OMX_StateIdle, NULL); } else { omx_send_command_and_wait(&pipe->video_scheduler, OMX_CommandStateSet, OMX_StateIdle, NULL); } } if (pipe->image_fx.port_settings_changed == 2) { omx_send_command_and_wait(&pipe->video_scheduler, OMX_CommandStateSet, OMX_StateIdle, NULL); } if (pipe->video_scheduler.port_settings_changed == 2) { omx_send_command_and_wait(&pipe->video_render, OMX_CommandStateSet, OMX_StateIdle, NULL); } omx_send_command_and_wait(&pipe->audio_render, OMX_CommandStateSet, OMX_StateIdle, NULL); #if 0 DEBUGF("[vcodec] omx_teardown pipeline 2\n"); /* Wait for video_render to shutdown */ pthread_mutex_lock(&pipe->video_render.eos_mutex); while (!pipe->video_render.eos) pthread_cond_wait(&pipe->video_render.eos_cv,&pipe->video_render.eos_mutex); pthread_mutex_unlock(&pipe->video_render.eos_mutex); #endif /* Pipeline is as follows: [video data] -> 130 video_decode 131 -> 190 image_fx 191 -> 10 video_scheduler 11 -> 90 video_render clock 81 -> 12 video_scheduler clock 80 -> 101 audio_render [audio data] -> 100 audio_render */ /* Flush entrances to pipeline */ omx_send_command_and_wait(&pipe->video_decode,OMX_CommandFlush,130,NULL); omx_send_command_and_wait(&pipe->audio_render,OMX_CommandFlush,100,NULL); /* Flush all tunnels */ DEBUGF("[vcodec] omx_teardown pipeline 3\n"); if (pipe->do_deinterlace) { omx_flush_tunnel(&pipe->video_decode, 131, &pipe->image_fx, 190); omx_flush_tunnel(&pipe->image_fx, 191, &pipe->video_scheduler, 10); } else { omx_flush_tunnel(&pipe->video_decode, 131, &pipe->video_scheduler, 10); } DEBUGF("[vcodec] omx_teardown pipeline 4\n"); omx_flush_tunnel(&pipe->video_scheduler, 11, &pipe->video_render, 90); omx_flush_tunnel(&pipe->clock, 81, &pipe->video_scheduler, 12); DEBUGF("[vcodec] omx_teardown pipeline 2b\n"); omx_send_command_and_wait(&pipe->video_scheduler,OMX_CommandFlush,10,NULL); DEBUGF("[vcodec] omx_teardown pipeline 5\n"); omx_flush_tunnel(&pipe->clock, 80, &pipe->audio_render, 101); /* Disable audio_render input port and buffers */ omx_send_command_and_wait0(&pipe->audio_render, OMX_CommandPortDisable, 100, NULL); omx_free_buffers(&pipe->audio_render, 100); omx_send_command_and_wait1(&pipe->audio_render, OMX_CommandPortDisable, 100, NULL); DEBUGF("[vcodec] omx_teardown pipeline 9\n"); /* Scheduler -> render tunnel */ if (pipe->video_scheduler.port_settings_changed == 2) { omx_send_command_and_wait(&pipe->video_scheduler, OMX_CommandPortDisable, 11, NULL); omx_send_command_and_wait(&pipe->video_render, OMX_CommandPortDisable, 90, NULL); omx_send_command_and_wait(&pipe->video_scheduler, OMX_CommandPortDisable, 10, NULL); } if ((pipe->image_fx.port_settings_changed == 2) && (pipe->do_deinterlace)) { omx_send_command_and_wait(&pipe->image_fx, OMX_CommandPortDisable, 190, NULL); omx_send_command_and_wait(&pipe->image_fx, OMX_CommandPortDisable, 191, NULL); } DEBUGF("[vcodec] omx_teardown pipeline 8a\n"); //dumpport(pipe->video_scheduler.h,10); /* Teardown tunnels */ /* Pipeline is as follows: [video data] -> 130 video_decode 131 -> 190 image_fx 191 -> 10 video_scheduler 11 -> 90 video_render clock 81 -> 12 video_scheduler clock 80 -> 101 audio_render [audio data] -> 100 audio_render */ //dumpport(pipe->video_decode.h,131); OERR(OMX_SetupTunnel(pipe->video_scheduler.h, 10, NULL, 0)); DEBUGF("[vcodec] omx_teardown pipeline 10\n"); /* NOTE: The clock disable doesn't complete until after the video scheduler port is disabled (but it completes before the video scheduler port disabling completes). */ OERR(OMX_SendCommand(pipe->clock.h, OMX_CommandPortDisable, 80, NULL)); omx_send_command_and_wait(&pipe->audio_render, OMX_CommandPortDisable, 101, NULL); OERR(OMX_SendCommand(pipe->clock.h, OMX_CommandPortDisable, 81, NULL)); omx_send_command_and_wait(&pipe->video_scheduler, OMX_CommandPortDisable, 12, NULL); DEBUGF("[vcodec] omx_teardown pipeline 12b\n"); if (pipe->do_deinterlace) { OERR(OMX_SetupTunnel(pipe->image_fx.h, 190, NULL, 0)); OERR(OMX_SetupTunnel(pipe->image_fx.h, 191, NULL, 0)); } DEBUGF("[vcodec] omx_teardown pipeline 13\n"); OERR(OMX_SetupTunnel(pipe->video_scheduler.h, 11, NULL, 0)); OERR(OMX_SetupTunnel(pipe->video_render.h, 90, NULL, 0)); OERR(OMX_SetupTunnel(pipe->clock.h, 81, NULL, 0)); OERR(OMX_SetupTunnel(pipe->video_scheduler.h, 12, NULL, 0)); DEBUGF("[vcodec] omx_teardown pipeline 13b\n"); OERR(OMX_SetupTunnel(pipe->clock.h, 80, NULL, 0)); OERR(OMX_SetupTunnel(pipe->audio_render.h, 101, NULL, 0)); DEBUGF("[vcodec] omx_teardown pipeline 8b\n"); /* Pipeline is as follows: [video data] -> 130 video_decode 131 -> 190 image_fx 191 -> 10 video_scheduler 11 -> 90 video_render clock 81 -> 12 video_scheduler clock 80 -> 101 audio_render [audio data] -> 100 audio_render */ omx_show_state(&pipe->video_decode,130,131,0); dumpport(pipe->video_decode.h,131); omx_show_state(&pipe->video_scheduler,10,11,12); if (pipe->do_deinterlace) { omx_show_state(&pipe->image_fx,190,191,0); } omx_show_state(&pipe->video_render,90,0,0); omx_show_state(&pipe->audio_render,100,101,0); omx_show_state(&pipe->clock,80,81,0); if (pipe->video_decode.port_settings_changed == 2) { //dumpport(pipe->video_decode.h,131); omx_send_command_and_wait(&pipe->video_decode, OMX_CommandPortDisable, 131, NULL); } DEBUGF("[vcodec] omx_teardown pipeline 11\n"); /* Disable video_decode input port and buffers */ //dumpport(pipe->video_decode.h,130); omx_send_command_and_wait0(&pipe->video_decode, OMX_CommandPortDisable, 130, NULL); DEBUGF("[vcodec] omx_teardown pipeline 6\n"); omx_free_buffers(&pipe->video_decode, 130); DEBUGF("[vcodec] omx_teardown pipeline 7\n"); //omx_send_command_and_wait1(&pipe->video_decode, OMX_CommandPortDisable, 130, NULL); //dumpport(pipe->video_decode.h,130); if (is_port_enabled(pipe->video_decode.h, 130)) { fprintf(stderr,"Unexpected error video_decode port 130 is not disabled\n"); exit(1); } DEBUGF("[vcodec] omx_teardown pipeline 12\n"); OERR(OMX_SetupTunnel(pipe->video_decode.h, 131, NULL, 0)); DEBUGF("[vcodec] omx_teardown pipeline 15\n"); omx_show_state(&pipe->video_decode,130,131,0); /* Transition all components to Loaded */ DEBUGF("[vcodec] omx_teardown pipeline 15a\n"); omx_send_command_and_wait(&pipe->video_decode, OMX_CommandStateSet, OMX_StateLoaded, NULL); DEBUGF("[vcodec] omx_teardown pipeline 15b\n"); omx_send_command_and_wait(&pipe->video_scheduler, OMX_CommandStateSet, OMX_StateLoaded, NULL); DEBUGF("[vcodec] omx_teardown pipeline 15c\n"); if (((pipe->video_decode.port_settings_changed == 2) && (pipe->do_deinterlace)) || (pipe->image_fx.port_settings_changed == 2)) { omx_send_command_and_wait(&pipe->video_render, OMX_CommandStateSet, OMX_StateLoaded, NULL); } DEBUGF("[vcodec] omx_teardown pipeline 15d\n"); omx_send_command_and_wait(&pipe->audio_render, OMX_CommandStateSet, OMX_StateLoaded, NULL); DEBUGF("[vcodec] omx_teardown pipeline 15e\n"); omx_send_command_and_wait(&pipe->clock, OMX_CommandStateSet, OMX_StateLoaded, NULL); DEBUGF("[vcodec] omx_teardown pipeline 15f\n"); if (pipe->do_deinterlace) { omx_send_command_and_wait(&pipe->image_fx, OMX_CommandStateSet, OMX_StateLoaded, NULL); } DEBUGF("[vcodec] omx_teardown pipeline 16\n"); /* Finally free the component handles */ OERR(OMX_FreeHandle(pipe->video_decode.h)); OERR(OMX_FreeHandle(pipe->video_scheduler.h)); OERR(OMX_FreeHandle(pipe->video_render.h)); OERR(OMX_FreeHandle(pipe->audio_render.h)); OERR(OMX_FreeHandle(pipe->clock.h)); if (pipe->do_deinterlace) { OERR(OMX_FreeHandle(pipe->image_fx.h)); } DEBUGF("[vcodec] omx_teardown pipeline 17\n"); }
static OMXCAM_ERROR initOMX (OMXCAM_VIDEO_SETTINGS* settings){ OMXCAM_trace ("Initializing video"); OMX_COLOR_FORMATTYPE colorFormat; OMX_U32 stride; OMXCAM_COMPONENT* fillComponent; OMX_ERRORTYPE error; //Stride is byte-per-pixel*width //See mmal/util/mmal_util.c, mmal_encoding_width_to_stride() switch (settings->format){ case OMXCAM_FormatRGB888: OMXCAM_ctx.camera.bufferCallback = settings->bufferCallback; useEncoder = 0; colorFormat = OMX_COLOR_Format24bitRGB888; stride = settings->camera.width*3; fillComponent = &OMXCAM_ctx.camera; break; case OMXCAM_FormatRGBA8888: OMXCAM_ctx.camera.bufferCallback = settings->bufferCallback; useEncoder = 0; colorFormat = OMX_COLOR_Format32bitABGR8888; stride = settings->camera.width*4; fillComponent = &OMXCAM_ctx.camera; break; case OMXCAM_FormatYUV420: OMXCAM_ctx.camera.bufferCallback = settings->bufferCallback; useEncoder = 0; colorFormat = OMX_COLOR_FormatYUV420PackedPlanar; stride = settings->camera.width; fillComponent = &OMXCAM_ctx.camera; break; case OMXCAM_FormatH264: OMXCAM_ctx.video_encode.bufferCallback = settings->bufferCallback; useEncoder = 1; colorFormat = OMX_COLOR_FormatYUV420PackedPlanar; stride = settings->camera.width; fillComponent = &OMXCAM_ctx.video_encode; break; default: return OMXCAM_ErrorFormat; } threadArg.bufferCallback = settings->bufferCallback; threadArg.fillComponent = fillComponent; if (OMXCAM_initComponent (&OMXCAM_ctx.camera)){ return OMXCAM_ErrorInitCamera; } if (OMXCAM_initComponent (&OMXCAM_ctx.null_sink)){ return OMXCAM_ErrorInitNullSink; } if (useEncoder && OMXCAM_initComponent (&OMXCAM_ctx.video_encode)){ return OMXCAM_ErrorInitVideoEncoder; } if (OMXCAM_loadCameraDrivers ()){ return OMXCAM_ErrorInitCamera; } //Configure camera port definition OMXCAM_trace ("Configuring '%s' port definition", OMXCAM_ctx.camera.name); OMX_PARAM_PORTDEFINITIONTYPE portDefinition; OMX_INIT_STRUCTURE (portDefinition); portDefinition.nPortIndex = 71; if ((error = OMX_GetParameter (OMXCAM_ctx.camera.handle, OMX_IndexParamPortDefinition, &portDefinition))){ OMXCAM_error ("OMX_GetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorVideo; } portDefinition.format.video.nFrameWidth = settings->camera.width; portDefinition.format.video.nFrameHeight = settings->camera.height; portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; portDefinition.format.video.eColorFormat = colorFormat; portDefinition.format.video.xFramerate = settings->camera.framerate << 16; //TODO: stride, sliceHeight? http://www.raspberrypi.org/phpBB3/viewtopic.php?f=28&t=22019 portDefinition.format.video.nStride = stride; if ((error = OMX_SetParameter (OMXCAM_ctx.camera.handle, OMX_IndexParamPortDefinition, &portDefinition))){ OMXCAM_error ("OMX_SetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorBadParameter; } //The preview port must be configured with the same settings as the video port portDefinition.nPortIndex = 70; if ((error = OMX_SetParameter (OMXCAM_ctx.camera.handle, OMX_IndexParamPortDefinition, &portDefinition))){ OMXCAM_error ("OMX_SetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorBadParameter; } //The framerate must be configured (again) with its own structure in the video //and preview ports OMXCAM_trace ("Configuring %s framerate", OMXCAM_ctx.camera.name); OMX_CONFIG_FRAMERATETYPE framerate; OMX_INIT_STRUCTURE (framerate); framerate.nPortIndex = 71; framerate.xEncodeFramerate = portDefinition.format.video.xFramerate; if ((error = OMX_SetConfig (OMXCAM_ctx.camera.handle, OMX_IndexConfigVideoFramerate, &framerate))){ OMXCAM_error ("OMX_SetConfig - OMX_IndexConfigVideoFramerate: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorBadParameter; } //Preview port framerate.nPortIndex = 70; if ((error = OMX_SetConfig (OMXCAM_ctx.camera.handle, OMX_IndexConfigVideoFramerate, &framerate))){ OMXCAM_error ("OMX_SetConfig - OMX_IndexConfigVideoFramerate: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorBadParameter; } //Configure camera settings if (OMXCAM_setCameraSettings (&settings->camera)){ return OMXCAM_ErrorBadParameter; } if (useEncoder){ OMXCAM_trace ("Configuring '%s' port definition", OMXCAM_ctx.video_encode.name); OMX_INIT_STRUCTURE (portDefinition); portDefinition.nPortIndex = 201; if ((error = OMX_GetParameter (OMXCAM_ctx.video_encode.handle, OMX_IndexParamPortDefinition, &portDefinition))){ OMXCAM_error ("OMX_GetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorStill; } portDefinition.format.video.nFrameWidth = settings->camera.width; portDefinition.format.video.nFrameHeight = settings->camera.height; portDefinition.format.video.xFramerate = settings->camera.framerate << 16; portDefinition.format.video.nStride = stride; //Despite being configured later, these two fields need to be set portDefinition.format.video.nBitrate = settings->h264.bitrate; portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; if ((error = OMX_SetParameter (OMXCAM_ctx.video_encode.handle, OMX_IndexParamPortDefinition, &portDefinition))){ OMXCAM_error ("OMX_SetParameter - OMX_IndexParamPortDefinition: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorBadParameter; } //Configure H264 settings if (OMXCAM_setH264Settings (&settings->h264)){ return OMXCAM_ErrorBadParameter; } //Setup tunnel: camera (video) -> video_encode OMXCAM_trace ("Configuring tunnel '%s' -> '%s'", OMXCAM_ctx.camera.name, OMXCAM_ctx.video_encode.name); if ((error = OMX_SetupTunnel (OMXCAM_ctx.camera.handle, 71, OMXCAM_ctx.video_encode.handle, 200))){ OMXCAM_error ("OMX_SetupTunnel: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorSetupTunnel; } } //Setup tunnel: camera (preview) -> null_sink OMXCAM_trace ("Configuring tunnel '%s' -> '%s'", OMXCAM_ctx.camera.name, OMXCAM_ctx.null_sink.name); if ((error = OMX_SetupTunnel (OMXCAM_ctx.camera.handle, 70, OMXCAM_ctx.null_sink.handle, 240))){ OMXCAM_error ("OMX_SetupTunnel: %s", OMXCAM_dump_OMX_ERRORTYPE (error)); return OMXCAM_ErrorSetupTunnel; } //Change to Idle if (changeVideoState (OMX_StateIdle, useEncoder)){ return OMXCAM_ErrorIdle; } //Enable the ports if (OMXCAM_enablePort (&OMXCAM_ctx.camera, 71)){ return OMXCAM_ErrorVideo; } if (!useEncoder && OMXCAM_allocateBuffer (&OMXCAM_ctx.camera, 71)){ return OMXCAM_ErrorVideo; } if (OMXCAM_wait (&OMXCAM_ctx.camera, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorVideo; } if (OMXCAM_enablePort (&OMXCAM_ctx.camera, 70)){ return OMXCAM_ErrorVideo; } if (OMXCAM_wait (&OMXCAM_ctx.camera, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorVideo; } if (OMXCAM_enablePort (&OMXCAM_ctx.null_sink, 240)){ return OMXCAM_ErrorVideo; } if (OMXCAM_wait (&OMXCAM_ctx.null_sink, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorVideo; } if (useEncoder){ if (OMXCAM_enablePort (&OMXCAM_ctx.video_encode, 200)){ return OMXCAM_ErrorVideo; } if (OMXCAM_wait (&OMXCAM_ctx.video_encode, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorVideo; } if (OMXCAM_enablePort (&OMXCAM_ctx.video_encode, 201)){ return OMXCAM_ErrorVideo; } if (OMXCAM_allocateBuffer (&OMXCAM_ctx.video_encode, 201)){ return OMXCAM_ErrorVideo; } if (OMXCAM_wait (&OMXCAM_ctx.video_encode, OMXCAM_EventPortEnable, 0)){ return OMXCAM_ErrorVideo; } } //Change to Executing if (changeVideoState (OMX_StateExecuting, useEncoder)){ return OMXCAM_ErrorExecuting; } //Set camera capture port if (OMXCAM_setCapturePort (71)){ return OMXCAM_ErrorVideo; } return OMXCAM_ErrorNone; }
static void handle_msg(int fd, struct msg* m) { switch (m->type) { case MSG_GET_HANDLE: { struct comp* c = (struct comp*) malloc(sizeof(struct comp)); fprintf(stderr, "ILSRV: GetHandle '%s'\n", m->cmd.get_handle.name); m->result = OMX_GetHandle(&c->real_handle, m->cmd.get_handle.name, c, &callbacks); m->cmd.get_handle.out_srv_handle = (int) c; c->client_handle = m->cmd.get_handle.in_client_handle; c->client_fd = fd; c->state = OMX_StateLoaded; strncpy(c->name, m->cmd.get_handle.name, sizeof(c->name)); c->name[sizeof(c->name)-1]=0; add_component(c); fprintf(stderr, "ILSRV: %08X [%20s] --> %s%s\n", c->real_handle, last_part(c->name), m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_SET_PARAM:{ struct comp* c = (struct comp*) m->cmd.param.srv_handle; verify_component(c); fprintf(stderr, "ILSRV: %08X [%20s] SetParam %s\n", c->real_handle, last_part(c->name), adm_log_index2str(m->cmd.param.index)); m->result = OMX_SetParameter(c->real_handle, (OMX_INDEXTYPE) m->cmd.param.index, m->cmd.param.buf); // TODO: Protect fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_GET_PARAM:{ struct comp* c = (struct comp*) m->cmd.param.srv_handle; verify_component(c); fprintf(stderr, "ILSRV: %08X [%20s] GetParam %s\n", c->real_handle, last_part(c->name), adm_log_index2str(m->cmd.param.index)); m->result = OMX_GetParameter(c->real_handle, (OMX_INDEXTYPE)m->cmd.param.index, m->cmd.param.buf); // TODO: Protect fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_GET_CONFIG:{ struct comp* c = (struct comp*) m->cmd.param.srv_handle; verify_component(c); fprintf(stderr, "ILSRV: %08X [%20s] GetConfig %s\n", c->real_handle, last_part(c->name), adm_log_index2str(m->cmd.param.index)); m->result = OMX_GetConfig(c->real_handle, (OMX_INDEXTYPE)m->cmd.param.index, m->cmd.param.buf); // TODO: Protect fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_SET_CONFIG: { struct comp* c = (struct comp*) m->cmd.param.srv_handle; verify_component(c); fprintf(stderr, "ILSRV: %08X [%20s] SetConfig %s\n", c->real_handle, last_part(c->name), adm_log_index2str(m->cmd.param.index)); m->result = OMX_SetConfig(c->real_handle, (OMX_INDEXTYPE)m->cmd.param.index, m->cmd.param.buf); // TODO: Protect fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_FREE_HANDLE: { struct comp* c = (struct comp*) m->cmd.free_handle.srv_handle; verify_component(c); if (c->state != OMX_StateLoaded) { fprintf(stderr, "ILSRV: FreeHandle called for %X which is in wrong state (%s)\m", c->real_handle, adm_log_state2str(c->state)); error_found(); } fprintf(stderr, "ILSRV: %08X [%20s] Freehandle (internal=%X)\n", c->real_handle, last_part(c->name), c); m->result = OMX_FreeHandle(c->real_handle); fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); del_component(c); memset(c, 0xFE, sizeof(*c)); free(c); return; } case MSG_SEND_COMMAND: { struct comp* c = (struct comp*) m->cmd.free_handle.srv_handle; verify_component(c); if (m->cmd.command.cmd == OMX_CommandStateSet) { fprintf(stderr, "ILSRV: %08X [%20s] SendCommand StateSet %s\n", c->real_handle, last_part(c->name), adm_log_state2str((OMX_STATETYPE) m->cmd.command.nParam1)); } else { fprintf(stderr, "ILSRV: %08X [%20s] SendCommand StateSet %s 0x%X\n", c->real_handle, last_part(c->name), adm_log_cmd2str(m->cmd.command.cmd), m->cmd.command.nParam1); } m->result = OMX_SendCommand(c->real_handle, m->cmd.command.cmd, m->cmd.command.nParam1, 0); fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_SETUP_TUNNEL: { struct comp* c_in = (struct comp*) m->cmd.tunnel.srv_handle_in; struct comp* c_out = (struct comp*) m->cmd.tunnel.srv_handle_out; verify_component(c_in); verify_component(c_out); fprintf(stderr, "ILSRV: SetupTunnel %08X [%20s].%d --> %08X [%20s].%d\n", c_out->real_handle, last_part(c_out->name), m->cmd.tunnel.port_out, c_in->real_handle, last_part(c_in->name), m->cmd.tunnel.port_in); m->result = OMX_SetupTunnel(c_out->real_handle, m->cmd.tunnel.port_out, c_in->real_handle, m->cmd.tunnel.port_in); fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_GET_STATE: { struct comp* c = (struct comp*) m->cmd.get_state.in_srv_handle; verify_component(c); fprintf(stderr, "ILSRV: %08X [%20s] GetState\n", c->real_handle, last_part(c->name)); m->result = OMX_GetState(c->real_handle, &m->cmd.get_state.out_state); fprintf(stderr, "ILSRV: --> %s %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result), adm_log_state2str(m->cmd.get_state.out_state)); return; } case MSG_ALLOC_BUFFER: { struct comp* c = (struct comp*) m->cmd.alloc_buffer.in_srv_handle; verify_component(c); OMX_BUFFERHEADERTYPE* bufhdr; fprintf(stderr, "ILSRV: %08X [%20s] AllocBuf port=%d size=%d\n", c->real_handle, last_part(c->name), m->cmd.alloc_buffer.port, m->cmd.alloc_buffer.size); m->result = OMX_AllocateBuffer(c->real_handle, &bufhdr, m->cmd.alloc_buffer.port, (void*) m->cmd.alloc_buffer.in_client_buf_hdr, m->cmd.alloc_buffer.size); if (m->result == OMX_ErrorNone) { memcpy(&m->cmd.alloc_buffer.out_buf_hdr, bufhdr, sizeof(OMX_BUFFERHEADERTYPE)); m->cmd.alloc_buffer.out_srv_buf_hdr = (int) bufhdr; add_bufhdr(bufhdr); } fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_EMPTY_BUFFER: { struct comp* c = (struct comp*) m->cmd.empty_buffer.in_srv_handle; verify_component(c); OMX_BUFFERHEADERTYPE* client_bufhdr = (OMX_BUFFERHEADERTYPE*) &m->cmd.empty_buffer.in_buf_hdr; OMX_BUFFERHEADERTYPE* bufhdr = (OMX_BUFFERHEADERTYPE*) client_bufhdr->pPlatformPrivate; verify_bufhdr(bufhdr); if (bufhdr->nAllocLen <= sizeof(m->cmd.empty_buffer.in_buf)) { bufhdr->nOffset = client_bufhdr->nOffset; bufhdr->nTimeStamp = client_bufhdr->nTimeStamp; bufhdr->nFilledLen = client_bufhdr->nFilledLen; bufhdr->nFlags = client_bufhdr->nFlags; memcpy(bufhdr->pBuffer, &m->cmd.empty_buffer.in_buf, bufhdr->nAllocLen); fprintf(stderr, "ILSRV: %08X [%20s] EmptyBuffer port=%d size=%d\n", c->real_handle, last_part(c->name), bufhdr->nInputPortIndex, bufhdr->nAllocLen); m->result = OMX_EmptyThisBuffer(c->real_handle, bufhdr); fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); } else { assert(0); } return; } case MSG_FILL_BUFFER: { struct comp* c = (struct comp*) m->cmd.empty_buffer.in_srv_handle; verify_component(c); OMX_BUFFERHEADERTYPE* client_bufhdr = (OMX_BUFFERHEADERTYPE*) &m->cmd.fill_buffer.in_buf_hdr; OMX_BUFFERHEADERTYPE* bufhdr = (OMX_BUFFERHEADERTYPE*) client_bufhdr->pPlatformPrivate; verify_bufhdr(bufhdr); fprintf(stderr, "ILSRV: %08X [%20s] FillBuffer port=%d size=%d\n", c->real_handle, last_part(c->name), bufhdr->nOutputPortIndex, bufhdr->nAllocLen); m->result = OMX_FillThisBuffer(c->real_handle, bufhdr); fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } case MSG_FREE_BUFFER: { struct comp* c = (struct comp*) m->cmd.empty_buffer.in_srv_handle; verify_component(c); OMX_BUFFERHEADERTYPE* bufhdr = (OMX_BUFFERHEADERTYPE*) m->cmd.free_buffer.in_srv_buf_hdr; verify_bufhdr(bufhdr); del_bufhdr(bufhdr); fprintf(stderr, "ILSRV: %08X [%20s] FreeBuffer\n", c->real_handle, last_part(c->name)); m->result = OMX_FreeBuffer(c->real_handle, m->cmd.free_buffer.in_port, bufhdr); fprintf(stderr, "ILSRV: --> %s %s\n", m->result == OMX_ErrorNone ? "" : "ERROR ", adm_log_err2str(m->result)); return; } default: fprintf(stderr, "ILSRV: Unhandled request received\n"); m->result = OMX_ErrorNotImplemented; error_found(); return; }
/* will be feeding stuff into the encoding pipeline */ void * decode_thread(void *context) { OMX_BUFFERHEADERTYPE *input_buffer; // buffer taken from the OMX decoder OMX_PARAM_PORTDEFINITIONTYPE encoder_config; OMX_PARAM_PORTDEFINITIONTYPE decoder_config; OMX_PARAM_PORTDEFINITIONTYPE deinterlacer_config; OMX_VIDEO_PARAM_PORTFORMATTYPE encoder_format_config; //used for the output of the encoder OMX_VIDEO_PARAM_BITRATETYPE encoder_bitrate_config; //used for the output of the encoder struct transcoder_ctx_t *ctx = (struct transcoder_ctx_t *) context; struct packet_t *current_packet; int bytes_left; uint8_t *p; // points to currently copied buffer // omx_setup_encoding_pipeline(&decoder_ctx->pipeline, OMX_VIDEO_CodingAVC); omx_setup_encoding_pipeline(&ctx->pipeline, OMX_VIDEO_CodingMPEG2); // main loop that will poll packets and render while (ctx->input_video_queue->queue_count != 0 || ctx->input_video_queue->queue_finished != 1) { //TODO a memory barrier is going to be needed so that we don't race current_packet = packet_queue_get_next_item(ctx->input_video_queue); p = current_packet->data; bytes_left = current_packet->data_length; while (bytes_left > 0) { fprintf(stderr, "OMX buffers: v: %02d/20, vcodec queue: %4d\r", omx_get_free_buffer_count(&ctx->pipeline.video_decode), ctx->input_video_queue->queue_count); input_buffer = omx_get_next_input_buffer(&ctx->pipeline.video_decode); // This will block if there are no empty buffers // copy at most the length of the OMX buf int copy_length = OMX_MIN(bytes_left, input_buffer->nAllocLen); memcpy(input_buffer->pBuffer, p, copy_length); p += copy_length; bytes_left -= copy_length; input_buffer->nFilledLen = copy_length; input_buffer->nTimeStamp = pts_to_omx(current_packet->PTS); if (ctx->first_packet) { input_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME; ctx->first_packet = 0; } else { //taken from ilclient input_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; } if (current_packet->flags & AV_PKT_FLAG_KEY) { input_buffer->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; } if(bytes_left == 0) { input_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; } //configure the resizer after the decoder has got output if (ctx->pipeline.video_decode.port_settings_changed == 1) { ctx->pipeline.video_decode.port_settings_changed = 0; #if 0 int x = 640; int y = 480; // rounding the dimensions up to the next multiple of 16. x += 0x0f; x &= ~0x0f; y += 0x0f; y &= ~0x0f; //the above code is used if resizer is used //get information about the decoded video OMX_INIT_STRUCTURE(decoder_config); decoder_config.nPortIndex = 131; OERR(OMX_GetParameter(ctx->pipeline.video_decode.h, OMX_IndexParamPortDefinition, &decoder_config)); decoder_config.nPortIndex = 190; OERR(OMX_GetParameter(ctx->pipeline.image_fx.h, OMX_IndexParamPortDefinition, &decoder_config)); decoder_config.nPortIndex = 191; OERR(OMX_GetParameter(ctx->pipeline.image_fx.h, OMX_IndexParamPortDefinition, &decoder_config)); #endif OERR(OMX_SetupTunnel(ctx->pipeline.video_decode.h, 131, ctx->pipeline.image_fx.h, 190)); omx_send_command_and_wait(&ctx->pipeline.video_decode, OMX_CommandPortEnable, 131, NULL); omx_send_command_and_wait(&ctx->pipeline.image_fx, OMX_CommandPortEnable, 190, NULL); omx_send_command_and_wait(&ctx->pipeline.image_fx, OMX_CommandStateSet, OMX_StateExecuting, NULL); fprintf(stderr, "configuring deinterlacer done\n"); } if(ctx->pipeline.image_fx.port_settings_changed == 1) { OMX_ERRORTYPE error; ctx->pipeline.image_fx.port_settings_changed = 0; #if 0 //get info from deinterlacer output OMX_INIT_STRUCTURE(deinterlacer_config); deinterlacer_config.nPortIndex = 191; OERR(OMX_GetParameter(ctx->pipeline.image_fx.h, OMX_IndexParamPortDefinition, &deinterlacer_config)); //get default from encoder input OMX_INIT_STRUCTURE(encoder_config); encoder_config.nPortIndex = 200; OERR(OMX_GetParameter(ctx->pipeline.video_encode.h, OMX_IndexParamPortDefinition, &encoder_config)); //modify it with deinterlacer encoder_config.format.video.nFrameHeight = deinterlacer_config.format.image.nFrameHeight; encoder_config.format.video.nFrameWidth = deinterlacer_config.format.image.nFrameWidth; encoder_config.format.video.eCompressionFormat = deinterlacer_config.format.image.eCompressionFormat; encoder_config.format.video.eColorFormat = deinterlacer_config.format.image.eColorFormat; encoder_config.format.video.nSliceHeight = deinterlacer_config.format.image.nSliceHeight; encoder_config.format.video.nStride = deinterlacer_config.format.image.nStride; //and feed it OERR(OMX_SetParameter(ctx->pipeline.video_encode.h, OMX_IndexParamPortDefinition, &encoder_config)); #endif //configure encoder output format OMX_INIT_STRUCTURE(encoder_format_config); encoder_format_config.nPortIndex = 201; //encoder output port encoder_format_config.eCompressionFormat = OMX_VIDEO_CodingAVC; OERR(OMX_SetParameter(ctx->pipeline.video_encode.h, OMX_IndexParamVideoPortFormat, &encoder_format_config)); //configure encoder output bitrate OMX_INIT_STRUCTURE(encoder_bitrate_config); encoder_bitrate_config.nPortIndex = 201; encoder_bitrate_config.eControlRate = OMX_Video_ControlRateVariable; //var bitrate encoder_bitrate_config.nTargetBitrate = ENCODED_BITRATE; //1 mbit OERR(OMX_SetParameter(ctx->pipeline.video_encode.h, OMX_IndexParamVideoBitrate, &encoder_bitrate_config)); //setup tunnel from decoder to encoder OERR(OMX_SetupTunnel(ctx->pipeline.image_fx.h, 191, ctx->pipeline.video_encode.h, 200)); //set encoder to idle after we have finished configuring it omx_send_command_and_wait0(&ctx->pipeline.video_encode, OMX_CommandStateSet, OMX_StateIdle, NULL); //allocate buffers for output of the encoder //send the enable command, which won't complete until the bufs are alloc'ed omx_send_command_and_wait0(&ctx->pipeline.video_encode, OMX_CommandPortEnable, 201, NULL); omx_alloc_buffers(&ctx->pipeline.video_encode, 201); //allocate output buffers //block until the port is fully enabled omx_send_command_and_wait1(&ctx->pipeline.video_encode, OMX_CommandPortEnable, 201, NULL); omx_send_command_and_wait1(&ctx->pipeline.video_encode, OMX_CommandStateSet, OMX_StateIdle, NULL); //enable the two ports omx_send_command_and_wait0(&ctx->pipeline.image_fx, OMX_CommandPortEnable, 191, NULL); omx_send_command_and_wait0(&ctx->pipeline.video_encode, OMX_CommandPortEnable, 200, NULL); omx_send_command_and_wait1(&ctx->pipeline.video_encode, OMX_CommandPortEnable, 200, NULL); omx_send_command_and_wait1(&ctx->pipeline.image_fx, OMX_CommandPortEnable, 191, NULL); omx_send_command_and_wait(&ctx->pipeline.video_encode, OMX_CommandStateSet, OMX_StateExecuting, NULL); fprintf(stderr, "finished configuring encoder\n"); } if(ctx->pipeline.video_encode.port_settings_changed == 1) { fprintf(stderr, "encoder enabled\n"); ctx->pipeline.video_encode.port_settings_changed = 0; //signal the consumer thread it can start polling for data ctx->pipeline.video_encode.is_running = 1; pthread_cond_signal(&ctx->pipeline.video_encode.is_running_cv); } OERR(OMX_EmptyThisBuffer(ctx->pipeline.video_decode.h, input_buffer)); } packet_queue_free_packet(current_packet, 1); current_packet = NULL; } printf("Finishing stream \n"); /* Indicate end of video stream */ input_buffer = omx_get_next_input_buffer(&ctx->pipeline.video_decode); input_buffer->nFilledLen = 0; input_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; OERR(OMX_EmptyThisBuffer(ctx->pipeline.video_decode.h, input_buffer)); // omx_teardown_pipeline(&decoder_ctx->pipeline); }
int main(int argc, char **argv) { int i; char *decodeComponentName; char *renderComponentName; int err; ILCLIENT_T *handle; COMPONENT_T *decodeComponent; COMPONENT_T *renderComponent; COMPONENT_T *fxComponent; int do_deinterlace = 0; if (argc >= 2) { IMG = argv[1]; } if (argc >= 3) { if (strcmp(argv[2],"d")==0) do_deinterlace = 1; } FILE *fp = fopen(IMG, "r"); int toread = get_file_size(IMG); OMX_BUFFERHEADERTYPE *buff_header; decodeComponentName = "video_decode"; renderComponentName = "video_render"; bcm_host_init(); handle = ilclient_init(); if (handle == NULL) { fprintf(stderr, "IL client init failed\n"); exit(1); } if (OMX_Init() != OMX_ErrorNone) { ilclient_destroy(handle); fprintf(stderr, "OMX init failed\n"); exit(1); } ilclient_set_error_callback(handle, error_callback, NULL); ilclient_set_eos_callback(handle, eos_callback, NULL); setup_decodeComponent(handle, decodeComponentName, &decodeComponent); setup_renderComponent(handle, renderComponentName, &renderComponent); if (do_deinterlace) setup_fxComponent(handle, "image_fx", &fxComponent); // both components now in Idle state, no buffers, ports disabled // input port ilclient_enable_port_buffers(decodeComponent, 130, NULL, NULL, NULL); ilclient_enable_port(decodeComponent, 130); err = ilclient_change_component_state(decodeComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change state to Executing\n"); exit(1); } printState(ilclient_get_handle(decodeComponent)); // Read the first block so that the decodeComponent can get // the dimensions of the video and call port settings // changed on the output port to configure it while (toread > 0) { buff_header = ilclient_get_input_buffer(decodeComponent, 130, 1 /* block */); if (buff_header != NULL) { read_into_buffer_and_empty(fp, decodeComponent, buff_header, &toread); // If all the file has been read in, then // we have to re-read this first block. // Broadcom bug? if (toread <= 0) { printf("Rewinding\n"); // wind back to start and repeat fp = freopen(IMG, "r", fp); toread = get_file_size(IMG); } } if (toread > 0 && ilclient_remove_event(decodeComponent, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) { printf("Removed port settings event\n"); break; } else { printf("No port setting seen yet\n"); } // wait for first input block to set params for output port if (toread == 0) { // wait for first input block to set params for output port err = ilclient_wait_for_event(decodeComponent, OMX_EventPortSettingsChanged, 131, 0, 0, 1, ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 2000); if (err < 0) { fprintf(stderr, "No port settings change\n"); //exit(1); } else { printf("Port settings changed\n"); break; } } } // set the decode component to idle and disable its ports err = ilclient_change_component_state(decodeComponent, OMX_StateIdle); if (err < 0) { fprintf(stderr, "Couldn't change state to Idle\n"); exit(1); } ilclient_disable_port(decodeComponent, 131); ilclient_disable_port_buffers(decodeComponent, 131, NULL, NULL, NULL); if (do_deinterlace) { // set up the tunnel between decode and fx ports err = OMX_SetupTunnel(ilclient_get_handle(decodeComponent), 131, ilclient_get_handle(fxComponent), 190); if (err != OMX_ErrorNone) { fprintf(stderr, "Error setting up tunnel 1 %X\n", err); exit(1); } else { printf("Tunnel 1 set up ok\n"); } // set up the tunnel between fx and render ports err = OMX_SetupTunnel(ilclient_get_handle(fxComponent), 191, ilclient_get_handle(renderComponent), 90); if (err != OMX_ErrorNone) { fprintf(stderr, "Error setting up tunnel 2 %X\n", err); exit(1); } else { printf("Tunnel 2 set up ok\n"); } } else { // set up the tunnel between decode and render ports err = OMX_SetupTunnel(ilclient_get_handle(decodeComponent), 131, ilclient_get_handle(renderComponent), 90); if (err != OMX_ErrorNone) { fprintf(stderr, "Error setting up tunnel %X\n", err); exit(1); } else { printf("Tunnel set up ok\n"); } } // Okay to go back to processing data // enable the decode output ports //UNNECESSARY?? PGB OMX_SendCommand(ilclient_get_handle(decodeComponent), //UNNECESSARY?? PGB OMX_CommandPortEnable, 131, NULL); ilclient_enable_port(decodeComponent, 131); if (do_deinterlace) { setup_shared_buffer_format(decodeComponent, 131, fxComponent, 191); // enable fx ports ilclient_enable_port(fxComponent, 190); ilclient_enable_port(fxComponent, 191); //UNNECESSARY?? PGB OMX_SendCommand(ilclient_get_handle(renderComponent), //UNNECESSARY?? PGB OMX_CommandPortEnable, 90, NULL); // setup_shared_buffer_format(fxComponent, renderComponent); } // enable the render output ports ilclient_enable_port(renderComponent, 90); // set all components to executing state err = ilclient_change_component_state(decodeComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change decode to Executing\n"); exit(1); } if (do_deinterlace) { err = ilclient_change_component_state(fxComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change fx to Executing\n"); exit(1); } } err = ilclient_change_component_state(renderComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change render to Executing\n"); exit(1); } print_port_info(ilclient_get_handle(decodeComponent), 131); if (do_deinterlace) { print_port_info(ilclient_get_handle(fxComponent), 190); print_port_info(ilclient_get_handle(fxComponent), 191); } print_port_info(ilclient_get_handle(renderComponent), 90); // now work through the file while (toread > 0) { OMX_ERRORTYPE r; // do we have a decode input buffer we can fill and empty? buff_header = ilclient_get_input_buffer(decodeComponent, 130, 1 /* block */); if (buff_header != NULL) { read_into_buffer_and_empty(fp, decodeComponent, buff_header, &toread); } usleep(100000); // print_port_info(ilclient_get_handle(renderComponent), 90); } ilclient_wait_for_event(renderComponent, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, ILCLIENT_BUFFER_FLAG_EOS, 10000); printf("EOS on render\n"); sleep(100); exit(0); }
OMX_ERRORTYPE NonTextureEngine::onCameraEventParamOrConfigChanged() { ofLogVerbose(__func__) << "START"; OMX_ERRORTYPE error = OMX_SendCommand(camera, OMX_CommandStateSet, OMX_StateIdle, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera OMX_SendCommand OMX_StateIdle FAIL error: 0x%08x", error); } //Enable Camera Output Port OMX_CONFIG_PORTBOOLEANTYPE cameraport; OMX_INIT_STRUCTURE(cameraport); cameraport.nPortIndex = CAMERA_OUTPUT_PORT; cameraport.bEnabled = OMX_TRUE; error =OMX_SetParameter(camera, OMX_IndexConfigPortCapturing, &cameraport); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera enable Output Port FAIL error: 0x%08x", error); } if (omxCameraSettings.doRecording) { if (omxCameraSettings.doRecordingPreview) { //Set up renderer setupRenderer(); } //set up encoder OMX_CALLBACKTYPE encoderCallbacks; encoderCallbacks.EventHandler = &BaseEngine::encoderEventHandlerCallback; encoderCallbacks.EmptyBufferDone = &BaseEngine::encoderEmptyBufferDone; encoderCallbacks.FillBufferDone = &NonTextureEngine::encoderFillBufferDone; string encoderComponentName = "OMX.broadcom.video_encode"; error =OMX_GetHandle(&encoder, (OMX_STRING)encoderComponentName.c_str(), this , &encoderCallbacks); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_GetHandle FAIL error: 0x%08x", error); } configureEncoder(); if (omxCameraSettings.doRecordingPreview) { //Create camera->video_render Tunnel error = OMX_SetupTunnel(camera, CAMERA_PREVIEW_PORT, render, VIDEO_RENDER_INPUT_PORT); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera->video_render OMX_SetupTunnel FAIL error: 0x%08x", error); } } // Tunnel camera video output port and encoder input port error = OMX_SetupTunnel(camera, CAMERA_OUTPUT_PORT, encoder, VIDEO_ENCODE_INPUT_PORT); if(error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "CAMERA_OUTPUT_PORT->VIDEO_ENCODE_INPUT_PORT OMX_SetupTunnel FAIL error: 0x%08x", error); } //Set encoder to Idle error = OMX_SendCommand(encoder, OMX_CommandStateSet, OMX_StateIdle, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_SendCommand OMX_StateIdle FAIL error: 0x%08x", error); } //Set camera to Idle error = OMX_SendCommand(camera, OMX_CommandStateSet, OMX_StateIdle, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera OMX_SendCommand OMX_StateIdle FAIL error: 0x%08x", error); } if (omxCameraSettings.doRecordingPreview) { //Enable camera preview port error = OMX_SendCommand(camera, OMX_CommandPortEnable, CAMERA_PREVIEW_PORT, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera OMX_CommandPortEnable CAMERA_PREVIEW_PORT FAIL error: 0x%08x", error); } } //Enable camera output port error = OMX_SendCommand(camera, OMX_CommandPortEnable, CAMERA_OUTPUT_PORT, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera OMX_CommandPortEnable CAMERA_OUTPUT_PORT FAIL error: 0x%08x", error); } //Enable encoder input port error = OMX_SendCommand(encoder, OMX_CommandPortEnable, VIDEO_ENCODE_INPUT_PORT, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_CommandPortEnable VIDEO_ENCODE_INPUT_PORT FAIL error: 0x%08x", error); } //Enable encoder output port error = OMX_SendCommand(encoder, OMX_CommandPortEnable, VIDEO_ENCODE_OUTPUT_PORT, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_CommandPortEnable VIDEO_ENCODE_OUTPUT_PORT FAIL error: 0x%08x", error); } if (omxCameraSettings.doRecordingPreview) { //Enable render input port error = OMX_SendCommand(render, OMX_CommandPortEnable, VIDEO_RENDER_INPUT_PORT, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "render enable output port FAIL error: 0x%08x", error); } } OMX_PARAM_PORTDEFINITIONTYPE encoderOutputPortDefinition; OMX_INIT_STRUCTURE(encoderOutputPortDefinition); encoderOutputPortDefinition.nPortIndex = VIDEO_ENCODE_OUTPUT_PORT; error =OMX_GetParameter(encoder, OMX_IndexParamPortDefinition, &encoderOutputPortDefinition); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_GetParameter OMX_IndexParamPortDefinition FAIL error: 0x%08x", error); }else { ofLogVerbose(__func__) << "VIDEO_ENCODE_OUTPUT_PORT eColorFormat: " << OMX_Maps::getInstance().colorFormatTypes[encoderOutputPortDefinition.format.video.eColorFormat]; } error = OMX_AllocateBuffer(encoder, &encoderOutputBuffer, VIDEO_ENCODE_OUTPUT_PORT, NULL, encoderOutputPortDefinition.nBufferSize); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_AllocateBuffer VIDEO_ENCODE_OUTPUT_PORT FAIL error: 0x%08x", error); } //Start camera error = OMX_SendCommand(camera, OMX_CommandStateSet, OMX_StateExecuting, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera OMX_StateExecuting FAIL error: 0x%08x", error); } //Start encoder error = OMX_SendCommand(encoder, OMX_CommandStateSet, OMX_StateExecuting, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_StateExecuting FAIL error: 0x%08x", error); } if (omxCameraSettings.doRecordingPreview) { //Start renderer error = OMX_SendCommand(render, OMX_CommandStateSet, OMX_StateExecuting, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "render OMX_StateExecuting FAIL error: 0x%08x", error); } setupDisplay(); } error = OMX_FillThisBuffer(encoder, encoderOutputBuffer); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "encoder OMX_FillThisBuffer FAIL error: 0x%08x", error); } bool doThreadBlocking = true; startThread(doThreadBlocking); }else { setupRenderer(); //Create camera->video_render Tunnel error = OMX_SetupTunnel(camera, CAMERA_OUTPUT_PORT, render, VIDEO_RENDER_INPUT_PORT); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera->video_render OMX_SetupTunnel FAIL error: 0x%08x", error); } //Enable camera output port error = OMX_SendCommand(camera, OMX_CommandPortEnable, CAMERA_OUTPUT_PORT, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera enable output port FAIL error: 0x%08x", error); } //Enable render input port error = OMX_SendCommand(render, OMX_CommandPortEnable, VIDEO_RENDER_INPUT_PORT, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "render enable output port FAIL error: 0x%08x", error); } //Start renderer error = OMX_SendCommand(render, OMX_CommandStateSet, OMX_StateExecuting, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "render OMX_StateExecuting FAIL error: 0x%08x", error); } //Start camera error = OMX_SendCommand(camera, OMX_CommandStateSet, OMX_StateExecuting, NULL); if (error != OMX_ErrorNone) { ofLog(OF_LOG_ERROR, "camera OMX_StateExecuting FAIL error: 0x%08x", error); } setupDisplay(); } isOpen = true; return error; }
int main(int argc, char *argv[]) { AVFormatContext *ic; char *iname; char *oname; char *size; int err; int vidindex; int i, j; OMX_ERRORTYPE oerr; OMX_HANDLETYPE m2 = NULL, m4 = NULL, resize = NULL; OMX_VIDEO_PARAM_PORTFORMATTYPE *pfmt; OMX_PORT_PARAM_TYPE *porttype; OMX_PARAM_PORTDEFINITIONTYPE *portdef; OMX_BUFFERHEADERTYPE *decbufs; OMX_VIDEO_PORTDEFINITIONTYPE *viddef; OMX_VIDEO_PARAM_PROFILELEVELTYPE *level; int decportidx = 200; int resizeportidx = 60; int encportidx = 130; int fd; time_t start, end; int offset; AVPacket *p, *rp; int ish264; int filtertest; int opt; ILCLIENT_T *client; if (argc < 3) usage(argv[0]); ctx.bitrate = 2*1024*1024; ctx.verbose = 0; ctx.width = 0; ctx.height = 0; while ((opt = getopt(argc, argv, ":b:vs:")) != -1) { switch (opt) { case 'b': //bitrate ctx.bitrate = atoi(optarg); printf("bitrate = %d\n", ctx.bitrate); break; case 'v': //verbose` ctx.verbose = 1; break; case 's': //WxH ctx.width = atoi(optarg); if ((atoi(optarg) % 16) != 0) { printf("W = %d is not a multiple of 16\n", ctx.width); usage(argv[0]); } if (ctx.width <16 || ctx.width > 1080) { printf("W = %d should be between 16 and 1080\n", ctx.width); usage(argv[0]); } printf("W = %d\n", ctx.width); if ((size = strchr(optarg, 'x')) == NULL) { printf("wrong size parameter (no 'x') exiting\n"); usage(argv[0]); } ctx.height = atoi(size+1); if ((atoi(size+1) % 16) != 0) { printf("H = %d is not a multiple of 16\n", ctx.height); usage(argv[0]); } if (ctx.height <16 || ctx.height > 1080) { printf("H = %d should be between 16 and 1080\n", ctx.height); usage(argv[0]); } printf("H = %d\n", ctx.height); break; case '?': usage(argv[0]); } } if ((client = ilclient_init()) == NULL) return -2; iname = argv[optind++]; oname = argv[optind++]; MAKEME(porttype, OMX_PORT_PARAM_TYPE); MAKEME(portdef, OMX_PARAM_PORTDEFINITIONTYPE); MAKEME(pfmt, OMX_VIDEO_PARAM_PORTFORMATTYPE); av_register_all(); ic = NULL; ish264 = 0; pthread_mutex_init(&ctx.lock, NULL); #if 0 fmt = av_oformat_next(fmt); while (fmt) { printf("Found '%s'\t\t'%s'\n", fmt->name, fmt->long_name); fmt = av_oformat_next(fmt); } #endif /* Input init: */ if ((err = avformat_open_input(&ic, iname, NULL, NULL) != 0)) { fprintf(stderr, "Failed to open '%s': %s\n", iname, strerror(err)); exit(1); } ctx.ic = ic; if (avformat_find_stream_info(ic, NULL) < 0) { fprintf(stderr, "Failed to find streams in '%s'\n", iname); exit(1); } av_dump_format(ic, 0, iname, 0); vidindex = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (vidindex < 0) { fprintf(stderr, "Failed to find a video stream in '%s'\n", iname); exit(1); } printf("Found a video at index %d\n", vidindex); printf("Frame size: %dx%d\n", ic->streams[vidindex]->codec->width, ic->streams[vidindex]->codec->height); ish264 = (ic->streams[vidindex]->codec->codec_id == CODEC_ID_H264); /* Output init: */ ctx.fd = fd = open(oname, O_CREAT | O_LARGEFILE | O_WRONLY | O_TRUNC, 0666); printf("File descriptor %d\n", fd); #if 0 avformat_alloc_output_context(&oc, NULL, /*NULL,*/ oname); if (!oc) { printf("Couldn't determine output from '%s'; using MPEG.\n", oname); avformat_alloc_output_context(&oc, NULL, /*"matroska",*/ oname); } #endif // if (!oc) // exit(1); // fmt = oc->oformat; for (i = 0; i < ic->nb_streams; i++) { printf("Found stream %d, context %p\n", ic->streams[i]->index, ic->streams[i]->codec); } bcm_host_init(); OERR(OMX_Init(), ctx.verbose); OERR(OMX_GetHandle(&m2, DECNAME, &ctx, &decevents), ctx.verbose); OERR(OMX_GetHandle(&m4, ENCNAME, &ctx, &encevents), ctx.verbose); OERR(OMX_GetHandle(&resize, RESIZENAME, &ctx, &resizeevents), ctx.verbose); ctx.m2 = m2; ctx.m4 = m4; ctx.resize = resize; if (ctx.verbose) printf("Obtained handles. %p decode, %p resize, %p encode\n", m2, resize, m4); OERR(OMX_GetParameter(m2, OMX_IndexParamVideoInit, porttype), ctx.verbose); if (ctx.verbose) printf("Found %d ports, starting at %d (%x) on decoder\n", porttype->nPorts, porttype->nStartPortNumber, porttype->nStartPortNumber); ctx.decportidx = decportidx = porttype->nStartPortNumber; OERR(OMX_GetParameter(resize, OMX_IndexParamImageInit, porttype), ctx.verbose); if (ctx.verbose) printf("Found %d ports, starting at %d (%x) on resizer\n", porttype->nPorts, porttype->nStartPortNumber, porttype->nStartPortNumber); ctx.resizeportidx = resizeportidx = porttype->nStartPortNumber; OERR(OMX_GetParameter(m4, OMX_IndexParamVideoInit, porttype), ctx.verbose); if (ctx.verbose) printf("Found %d ports, starting at %d (%x) on encoder\n", porttype->nPorts, porttype->nStartPortNumber, porttype->nStartPortNumber); ctx.encportidx = encportidx = porttype->nStartPortNumber; free(porttype); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx+1, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx+1, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx+1, NULL), ctx.verbose); portdef->nPortIndex = decportidx; OERR(OMX_GetParameter(m2, OMX_IndexParamPortDefinition, portdef), ctx.verbose); viddef = &portdef->format.video; viddef->nFrameWidth = ic->streams[vidindex]->codec->width; viddef->nFrameHeight = ic->streams[vidindex]->codec->height; printf("Mapping codec %d to %d\n", ic->streams[vidindex]->codec->codec_id, mapcodec(ic->streams[vidindex]->codec->codec_id)); viddef->eCompressionFormat = mapcodec(ic->streams[vidindex]->codec->codec_id); viddef->bFlagErrorConcealment = 0; // viddef->xFramerate = 25<<16; OERR(OMX_SetParameter(m2, OMX_IndexParamPortDefinition, portdef), ctx.verbose); free(portdef); #if 0 /* It appears these have limited effect: */ dataunit->nPortIndex = decportidx; dataunit->eUnitType = OMX_DataUnitCodedPicture; dataunit->eEncapsulationType = OMX_DataEncapsulationGenericPayload; OERR(OMX_SetParameter(m2, OMX_IndexParamBrcmDataUnit, dataunit), ctx.verbose); if (ish264) { naltype->nPortIndex = decportidx; naltype->eNaluFormat = OMX_NaluFormatStartCodes; OERR(OMX_SetParameter(m2, OMX_IndexParamNalStreamFormatSelect, naltype), ctx.verbose); } #endif MAKEME(level, OMX_VIDEO_PARAM_PROFILELEVELTYPE); level->nPortIndex = encportidx+1; /* Dump what the encoder is capable of: */ if (ctx.verbose) print_codecs(); if (ctx.verbose) { for (oerr = OMX_ErrorNone, i = 0; oerr == OMX_ErrorNone; i++) { pfmt->nIndex = i; oerr = OMX_GetParameter(m4, OMX_IndexParamVideoPortFormat, pfmt); if (oerr == OMX_ErrorNoMore) break; printf("Codecs supported:\n" "\tIndex:\t\t%d\n" "\tCodec:\t\t%d (%x)\n" "\tColour:\t\t%d\n" "\tFramerate:\t%x (%f)\n", pfmt->nIndex, pfmt->eCompressionFormat, pfmt->eCompressionFormat, pfmt->eColorFormat, pfmt->xFramerate, ((float)pfmt->xFramerate/(float)65536)); } for (oerr = OMX_ErrorNone, i = 0; oerr == OMX_ErrorNone; i++) { level->nProfileIndex = i; oerr = OMX_GetParameter(m4, OMX_IndexParamVideoProfileLevelQuerySupported, level); if (oerr == OMX_ErrorNoMore) break; printf("Levels supported:\n" "\tIndex:\t\t%d\n" "\tProfile:\t%d\n" "\tLevel:\t\t%d\n", level->nProfileIndex, level->eProfile, level->eLevel); } } free(pfmt); free(level); /* Dump current port states: */ if (ctx.verbose) { dumpport(m2, decportidx); dumpport(m2, decportidx+1); dumpport(resize, resizeportidx); dumpport(resize, resizeportidx+1); dumpport(m4, encportidx); dumpport(m4, encportidx+1); } OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); decbufs = allocbufs(m2, decportidx, 1); /* Start the initial loop. Process until we have a state change on port 131 */ ctx.decstate = DECINIT; ctx.encstate = ENCPREINIT; OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateExecuting, NULL), ctx.verbose); rp = calloc(sizeof(AVPacket), 1); filtertest = ish264; for (offset = i = j = 0; ctx.decstate != DECFAILED; i++, j++) { int rc; int k; int size, nsize; OMX_BUFFERHEADERTYPE *spare; if (offset == 0 && ctx.decstate != DECFLUSH) { rc = av_read_frame(ic, rp); if (rc != 0) { if (ic->pb->eof_reached) ctx.decstate = DECFLUSH; break; } if (rp->stream_index != vidindex) { i--; av_free_packet(rp); continue; } size = rp->size; ctx.fps++; ctx.framecount++; if (ish264 && filtertest) { filtertest = 0; ctx.bsfc = dofiltertest(rp); } if (ctx.bsfc) { p = filter(&ctx, rp); } else { p = rp; } } switch (ctx.decstate) { case DECTUNNELSETUP: start = time(NULL); //printf("NOW to CONFIGURE !!!!!!!!!!!!!!\n\n"); configure(&ctx); ctx.decstate = DECRUNNING; break; case DECFLUSH: size = 0; /* Add the flush code here */ printf("IN FLUSH NOW\n\n"); break; case DECINIT: if (i < 120) /* Bail; decoder doesn't like it */ break; ctx.decstate = DECFAILED; /* Drop through */ case DECFAILED: fprintf(stderr, "Failed to set the parameters after " "%d video frames. Giving up.\n", i); dumpport(m2, decportidx); dumpport(m2, decportidx+1); dumpport(resize, resizeportidx); dumpport(resize, resizeportidx+1); dumpport(m4, encportidx); dumpport(m4, encportidx+1); exit(1); break; default: break; /* Shuts the compiler up */ } for (spare = NULL; !spare; usleep(10)) { pthread_mutex_lock(&ctx.lock); spare = ctx.bufhead; ctx.bufhead = NULL; ctx.flags &= ~FLAGS_DECEMPTIEDBUF; pthread_mutex_unlock(&ctx.lock); while (spare) { write(fd, &spare->pBuffer[spare->nOffset], spare->nFilledLen); spare->nFilledLen = 0; spare->nOffset = 0; OERRq(OMX_FillThisBuffer(m4, spare)); spare = spare->pAppPrivate; } spare = decbufs; for (k = 0; spare && spare->nFilledLen != 0; k++) spare = spare->pAppPrivate; } if (size > spare->nAllocLen) { nsize = spare->nAllocLen; } else { nsize = size; } if (ctx.decstate != DECFLUSH) { memcpy(spare->pBuffer, &(p->data[offset]), nsize); spare->nFlags = i == 0 ? OMX_BUFFERFLAG_STARTTIME : 0; spare->nFlags |= size == nsize ? OMX_BUFFERFLAG_ENDOFFRAME : 0; } else { spare->nFlags = OMX_BUFFERFLAG_STARTTIME | OMX_BUFFERFLAG_EOS; } spare->nFilledLen = nsize; spare->nOffset = 0; OERRq(OMX_EmptyThisBuffer(m2, spare)); size -= nsize; if (size) { offset += nsize; } else { offset = 0; av_free_packet(p); } } close(fd); end = time(NULL); printf("Processed %d frames in %d seconds; %df/s\n", ctx.framecount, end-start, (ctx.framecount/(end-start))); // flush the encoder // OERR(OMX_SendCommand(m4, OMX_CommandFlush, encportidx, NULL), ctx.verbose); // OERR(OMX_SendCommand(m4, OMX_CommandFlush, encportidx+ctx.verbose, NULL), ctx.verbose); // tear down the tunnels OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateLoaded, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandStateSet, OMX_StateLoaded, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandStateSet, OMX_StateLoaded, NULL), ctx.verbose); // free buffers vcos_free(decbufs); vcos_free(ctx.encbufs); // Apparantly the teardwon function is not implemented. Use setup function instead //OERR(OMX_TeardownTunnel(m2, decportidx+ctx.verbose, resize, resizeportidx), ctx.verbose); //OERR(OMX_TeardownTunnel(resize, resizeportidx+ctx.verbose, m4, encportidx), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx+ctx.verbose, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx+ctx.verbose, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx+ctx.verbose, NULL), ctx.verbose); // ilclient_disable_port_buffers(m2, decportidx, NULL, NULL, NULL); // ilclient_disable_port_buffers(m4, encportidx, NULL, NULL, NULL); OERR(OMX_SetupTunnel(m2, decportidx+ctx.verbose, NULL, 0), ctx.verbose); OERR(OMX_SetupTunnel(resize, resizeportidx, NULL, 0), ctx.verbose); OERR(OMX_SetupTunnel(resize, resizeportidx+ctx.verbose, NULL, 0), ctx.verbose); OERR(OMX_SetupTunnel(m4, encportidx, NULL, 0), ctx.verbose); OERR(OMX_FreeHandle(m2), ctx.verbose); OERR(OMX_FreeHandle(resize), ctx.verbose); OERR(OMX_FreeHandle(m4), ctx.verbose); // free(porttype); // free(portdef); // free(pfmt); // free(level); return 0; }
int portSettingsChanged(OPENMAX_JPEG_DECODER * decoder) { OMX_PARAM_PORTDEFINITIONTYPE portdef; // need to setup the input for the resizer with the output of the // decoder portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portdef.nVersion.nVersion = OMX_VERSION; portdef.nPortIndex = decoder->imageDecoder->outPort; OMX_GetParameter(decoder->imageDecoder->handle, OMX_IndexParamPortDefinition, &portdef); unsigned int uWidth = (unsigned int) portdef.format.image.nFrameWidth; unsigned int uHeight = (unsigned int) portdef.format.image.nFrameHeight; // tell resizer input what the decoder output will be providing portdef.nPortIndex = decoder->imageResizer->inPort; OMX_SetParameter(decoder->imageResizer->handle, OMX_IndexParamPortDefinition, &portdef); // establish tunnel between decoder output and resizer input OMX_SetupTunnel(decoder->imageDecoder->handle, decoder->imageDecoder->outPort, decoder->imageResizer->handle, decoder->imageResizer->inPort); // enable ports OMX_SendCommand(decoder->imageDecoder->handle, OMX_CommandPortEnable, decoder->imageDecoder->outPort, NULL); OMX_SendCommand(decoder->imageResizer->handle, OMX_CommandPortEnable, decoder->imageResizer->inPort, NULL); // put resizer in idle state (this allows the outport of the decoder // to become enabled) OMX_SendCommand(decoder->imageResizer->handle, OMX_CommandStateSet, OMX_StateIdle, NULL); // wait for state change complete ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandStateSet, 1, OMX_StateIdle, 1, 0, TIMEOUT_MS); // once the state changes, both ports should become enabled and the // resizer // output should generate a settings changed event ilclient_wait_for_event(decoder->imageDecoder->component, OMX_EventCmdComplete, OMX_CommandPortEnable, 1, decoder->imageDecoder->outPort, 1, 0, TIMEOUT_MS); ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandPortEnable, 1, decoder->imageResizer->inPort, 1, 0, TIMEOUT_MS); ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventPortSettingsChanged, decoder->imageResizer->outPort, 1, 0, 1, 0, TIMEOUT_MS); ilclient_disable_port(decoder->imageResizer->component, decoder->imageResizer->outPort); // query output buffer requirements for resizer portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portdef.nVersion.nVersion = OMX_VERSION; portdef.nPortIndex = decoder->imageResizer->outPort; OMX_GetParameter(decoder->imageResizer->handle, OMX_IndexParamPortDefinition, &portdef); // change output color format and dimensions to match input portdef.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused; portdef.format.image.eColorFormat = OMX_COLOR_Format32bitABGR8888; portdef.format.image.nFrameWidth = uWidth; portdef.format.image.nFrameHeight = uHeight; portdef.format.image.nStride = 0; portdef.format.image.nSliceHeight = 0; portdef.format.image.bFlagErrorConcealment = OMX_FALSE; OMX_SetParameter(decoder->imageResizer->handle, OMX_IndexParamPortDefinition, &portdef); // grab output requirements again to get actual buffer size // requirement (and buffer count requirement!) OMX_GetParameter(decoder->imageResizer->handle, OMX_IndexParamPortDefinition, &portdef); // move resizer into executing state ilclient_change_component_state(decoder->imageResizer->component, OMX_StateExecuting); // show some logging so user knows it's working printf ("Width: %u Height: %u Output Color Format: 0x%x Buffer Size: %u\n", (unsigned int) portdef.format.image.nFrameWidth, (unsigned int) portdef.format.image.nFrameHeight, (unsigned int) portdef.format.image.eColorFormat, (unsigned int) portdef.nBufferSize); fflush(stdout); // enable output port of resizer OMX_SendCommand(decoder->imageResizer->handle, OMX_CommandPortEnable, decoder->imageResizer->outPort, NULL); // allocate the buffer // void* outputBuffer = 0; // if (posix_memalign(&outputBuffer, portdef.nBufferAlignment, // portdef.nBufferSize) != 0) // { // perror("Allocating output buffer"); // return OMXJPEG_ERROR_MEMORY; // } // set the buffer // int ret = OMX_UseBuffer(decoder->imageResizer->handle, // &decoder->pOutputBufferHeader, // decoder->imageResizer->outPort, NULL, // portdef.nBufferSize, // (OMX_U8 *) outputBuffer); int ret = OMX_AllocateBuffer(decoder->imageResizer->handle, &decoder->pOutputBufferHeader, decoder->imageResizer-> outPort, NULL, portdef.nBufferSize); if (ret != OMX_ErrorNone) { perror("Eror allocating buffer"); fprintf(stderr, "OMX_AllocateBuffer returned 0x%x allocating buffer size 0x%x\n", ret, portdef.nBufferSize); return OMXJPEG_ERROR_MEMORY; } ilclient_wait_for_event(decoder->imageResizer->component, OMX_EventCmdComplete, OMX_CommandPortEnable, 1, decoder->imageResizer->outPort, 1, 0, TIMEOUT_MS); return OMXJPEG_OK; }
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; }
OMX_ERRORTYPE omx_setup_camera_pipeline(struct omx_pipeline_t* pipe) { // Create component. omx_init_component(pipe, &pipe->camera, "OMX.broadcom.camera"); // Use OMX_IndexConfigRequestCallback to request callbacks on OMX_IndexParamCameraDeviceNumber. OMX_CONFIG_REQUESTCALLBACKTYPE cbtype; OMX_INIT_STRUCTURE(cbtype); cbtype.nPortIndex=OMX_ALL; cbtype.nIndex=OMX_IndexParamCameraDeviceNumber; cbtype.bEnable = OMX_TRUE; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigRequestCallback, &cbtype)); // Set OMX_IndexParamISPTunerName. // Set OMX_IndexParamCameraFlashType. // Set OMX_IndexParamCameraDeviceNumber. OMX_PARAM_U32TYPE device; OMX_INIT_STRUCTURE(device); device.nPortIndex = OMX_ALL; device.nU32 = 0; OERR(OMX_SetParameter(pipe->camera.h, OMX_IndexParamCameraDeviceNumber, &device)); dumpport(pipe->camera.h, 71); /* Set the resolution */ OMX_PARAM_PORTDEFINITIONTYPE portdef; OMX_INIT_STRUCTURE(portdef); portdef.nPortIndex = 71; OERR(OMX_GetParameter(pipe->camera.h, OMX_IndexParamPortDefinition, &portdef)); portdef.format.image.nFrameWidth = 640; portdef.format.image.nFrameHeight = 360; portdef.format.image.nStride = 640; OERR(OMX_SetParameter(pipe->camera.h, OMX_IndexParamPortDefinition, &portdef)); /* Set the framerate */ OMX_CONFIG_FRAMERATETYPE framerate; OMX_INIT_STRUCTURE(framerate); framerate.nPortIndex = 71; framerate.xEncodeFramerate = 25 << 16; // Q16 format - 25fps OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigVideoFramerate, &framerate)); /* Set the sharpness */ OMX_CONFIG_SHARPNESSTYPE sharpness; OMX_INIT_STRUCTURE(sharpness); sharpness.nPortIndex = OMX_ALL; sharpness.nSharpness = -50; /* -100 to 100 */ OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonSharpness, &sharpness)); /* Set the contrast */ OMX_CONFIG_CONTRASTTYPE contrast; OMX_INIT_STRUCTURE(contrast); contrast.nPortIndex = OMX_ALL; contrast.nContrast = -10; /* -100 to 100 */ OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonContrast, &contrast)); /* Set the brightness */ OMX_CONFIG_BRIGHTNESSTYPE brightness; OMX_INIT_STRUCTURE(brightness); brightness.nPortIndex = OMX_ALL; brightness.nBrightness = 50; /* 0 to 100 */ OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonBrightness, &brightness)); /* Set the saturation */ OMX_CONFIG_SATURATIONTYPE saturation; OMX_INIT_STRUCTURE(saturation); saturation.nPortIndex = OMX_ALL; saturation.nSaturation = 0; /* -100 to 100 */ OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonSaturation, &saturation)); /* Video stabilisation */ OMX_CONFIG_FRAMESTABTYPE framestab; OMX_INIT_STRUCTURE(framestab); framestab.nPortIndex = OMX_ALL; framestab.bStab = OMX_FALSE; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonFrameStabilisation, &framestab)); /* Set EV compensation, ISO and metering mode */ OMX_CONFIG_EXPOSUREVALUETYPE exposurevalue; OMX_INIT_STRUCTURE(exposurevalue); exposurevalue.nPortIndex = OMX_ALL; OERR(OMX_GetConfig(pipe->camera.h, OMX_IndexConfigCommonExposureValue, &exposurevalue)); fprintf(stderr,"nSensitivity=%d\n",exposurevalue.nSensitivity); exposurevalue.xEVCompensation = 0; /* Fixed point value stored as Q16 */ exposurevalue.nSensitivity = 100; /**< e.g. nSensitivity = 100 implies "ISO 100" */ exposurevalue.bAutoSensitivity = OMX_FALSE; exposurevalue.eMetering = OMX_MeteringModeAverage; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonExposureValue, &exposurevalue)); /* Set exposure mode */ OMX_CONFIG_EXPOSURECONTROLTYPE exposure; OMX_INIT_STRUCTURE(exposure); exposure.nPortIndex = OMX_ALL; exposure.eExposureControl = OMX_ExposureControlAuto; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonExposure, &exposure)); /* Set AWB mode */ OMX_CONFIG_WHITEBALCONTROLTYPE awb; OMX_INIT_STRUCTURE(awb); awb.nPortIndex = OMX_ALL; awb.eWhiteBalControl = OMX_WhiteBalControlAuto; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonWhiteBalance, &awb)); /* Set image effect */ OMX_CONFIG_IMAGEFILTERTYPE imagefilter; OMX_INIT_STRUCTURE(imagefilter); imagefilter.nPortIndex = OMX_ALL; imagefilter.eImageFilter = OMX_ImageFilterNone; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonImageFilter, &imagefilter)); /* Set colour effect */ OMX_CONFIG_COLORENHANCEMENTTYPE colour; OMX_INIT_STRUCTURE(colour); colour.nPortIndex = OMX_ALL; colour.bColorEnhancement = OMX_FALSE; colour.nCustomizedU = 128; colour.nCustomizedV = 128; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigCommonColorEnhancement, &colour)); /* Turn off the LED - doesn't work! */ OMX_CONFIG_PRIVACYINDICATORTYPE privacy; OMX_INIT_STRUCTURE(privacy); privacy.ePrivacyIndicatorMode = OMX_PrivacyIndicatorOff; OERR(OMX_SetConfig(pipe->camera.h, OMX_IndexConfigPrivacyIndicator, &privacy)); // Wait for the callback that OMX_IndexParamCameraDeviceNumber has // changed. At this point, all the drivers have been loaded. Other // settings can be applied whilst waiting for this event. fprintf(stderr,"Waiting for camera config to change\n"); while (!pipe->camera.config_changed); /* TODO: Use a condition variable */ fprintf(stderr,"Config changed\n"); // Query for OMX_IndexConfigCameraSensorModes as required. // Change state to IDLE, and proceed as required. omx_send_command_and_wait(&pipe->camera, OMX_CommandStateSet, OMX_StateIdle, NULL); OMX_CONFIG_PORTBOOLEANTYPE cameraport; OMX_INIT_STRUCTURE(cameraport); cameraport.nPortIndex = 71; cameraport.bEnabled = OMX_TRUE; OERR(OMX_SetParameter(pipe->camera.h, OMX_IndexConfigPortCapturing, &cameraport)); omx_init_component(pipe, &pipe->video_render, "OMX.broadcom.video_render"); omx_send_command_and_wait(&pipe->video_render, OMX_CommandStateSet, OMX_StateIdle, NULL); OERR(OMX_SetupTunnel(pipe->camera.h, 71, pipe->video_render.h, 90)); /* Camera capture port to video render */ omx_send_command_and_wait(&pipe->camera, OMX_CommandPortEnable, 71, NULL); omx_send_command_and_wait(&pipe->video_render, OMX_CommandPortEnable, 90, NULL); omx_send_command_and_wait(&pipe->video_render, OMX_CommandStateSet, OMX_StateExecuting, NULL); omx_send_command_and_wait(&pipe->camera, OMX_CommandStateSet, OMX_StateExecuting, NULL); omx_set_display_region(pipe, 1200, 180, 640, 360); OMX_CONFIG_DISPLAYREGIONTYPE region; OMX_INIT_STRUCTURE(region); region.nPortIndex = 90; /* Video render input port */ region.set = OMX_DISPLAY_SET_LAYER; region.layer = 10; OERR(OMX_SetParameter(pipe->video_render.h, OMX_IndexConfigDisplayRegion, ®ion)); fprintf(stderr,"Camera pipeline configured\n"); dumpport(pipe->camera.h, 71); }