/* Function based on ilclient_create_component() */ static void omx_disable_all_ports(struct omx_component_t* component) { OMX_PORT_PARAM_TYPE ports; OMX_INDEXTYPE types[] = {OMX_IndexParamAudioInit, OMX_IndexParamVideoInit, OMX_IndexParamImageInit, OMX_IndexParamOtherInit}; int i; ports.nSize = sizeof(OMX_PORT_PARAM_TYPE); ports.nVersion.nVersion = OMX_VERSION; for(i=0; i<4; i++) { OMX_ERRORTYPE error = OMX_GetParameter(component->h, types[i], &ports); if(error == OMX_ErrorNone) { uint32_t j; for(j=0; j<ports.nPorts; j++) { //fprintf(stderr,"Disabling port %lu\n",ports.nStartPortNumber+j); omx_send_command_and_wait(component, OMX_CommandPortDisable, ports.nStartPortNumber+j, NULL); } } } }
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"); }
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; }
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); }
OMX_ERRORTYPE omx_flush_tunnel(struct omx_component_t* source, int source_port, struct omx_component_t* sink, int sink_port) { omx_send_command_and_wait(source,OMX_CommandFlush,source_port,NULL); omx_send_command_and_wait(sink,OMX_CommandFlush,sink_port,NULL); }
/* 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); }