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); }
int video_decode_test(char *filename,int x,int y,int w,int h) { int status = 0; #ifdef __arm__ OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *video_render = NULL, *clock = NULL; COMPONENT_T *list[5]; TUNNEL_T tunnel[4]; ILCLIENT_T *client; FILE *in; unsigned int data_len = 0; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((in = fopen(filename, "rb")) == NULL) return -2; if((client = ilclient_init()) == NULL) { fclose(in); return -3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(in); return -4; } ilclient_set_error_callback(client, error_callback, NULL); // create video_decode if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) status = -14; list[0] = video_decode; // create video_render if(status == 0 && ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[1] = video_render; // create clock if(status == 0 && ilclient_create_component(client, &clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[2] = clock; memset(&cstate, 0, sizeof(cstate)); #ifdef __arm__ cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; if(clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone) status = -13; // create video_scheduler if(status == 0 && ilclient_create_component(client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[3] = video_scheduler; set_tunnel(tunnel, video_decode, 131, video_scheduler, 10); set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90); set_tunnel(tunnel+2, clock, 80, video_scheduler, 12); // setup clock tunnel first if(status == 0 && ilclient_setup_tunnel(tunnel+2, 0, 0) != 0) status = -15; else ilclient_change_component_state(clock, OMX_StateExecuting); if(status == 0) ilclient_change_component_state(video_decode, OMX_StateIdle); memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); format.nVersion.nVersion = OMX_VERSION; format.nPortIndex = 130; format.eCompressionFormat = OMX_VIDEO_CodingAVC; #endif if(status == 0 && OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone && ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0) { OMX_BUFFERHEADERTYPE *buf; int port_settings_changed = 0; int first_packet = 1; ilclient_change_component_state(video_decode, OMX_StateExecuting); while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL) { // feed data and wait until we get port settings changed unsigned char *dest = buf->pBuffer; data_len += fread(dest, 1, buf->nAllocLen-data_len, in); if(port_settings_changed == 0 && ((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) || (data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1, ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0))) { port_settings_changed = 1; if(ilclient_setup_tunnel(tunnel, 0, 0) != 0) { status = -7; break; } ilclient_change_component_state(video_scheduler, OMX_StateExecuting); // now setup tunnel to video_render if(ilclient_setup_tunnel(tunnel+1, 0, 1000) != 0) { status = -12; break; } #ifdef __arm__ ilclient_change_component_state(video_render, OMX_StateIdle); OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; memset(&configDisplay, 0, sizeof(OMX_CONFIG_DISPLAYREGIONTYPE)); configDisplay.nSize = sizeof(OMX_CONFIG_DISPLAYREGIONTYPE); configDisplay.nVersion.nVersion = OMX_VERSION; configDisplay.nPortIndex = 90; configDisplay.fullscreen = OMX_FALSE; configDisplay.noaspect = OMX_TRUE; configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT | OMX_DISPLAY_SET_SRC_RECT | OMX_DISPLAY_SET_FULLSCREEN | OMX_DISPLAY_SET_NOASPECT); configDisplay.dest_rect.x_offset = x; configDisplay.dest_rect.y_offset = y; configDisplay.dest_rect.width = w; configDisplay.dest_rect.height = h; configDisplay.src_rect.x_offset = 0; configDisplay.src_rect.y_offset = 0; configDisplay.src_rect.width = 1280; configDisplay.src_rect.height = 720; int stat = 0; stat = OMX_SetParameter(ILC_GET_HANDLE(video_render), OMX_IndexConfigDisplayRegion, &configDisplay); printf ("stat= %#x\n", stat); #endif ilclient_change_component_state(video_render, OMX_StateExecuting); } if(!data_len) break; buf->nFilledLen = data_len; data_len = 0; buf->nOffset = 0; if(first_packet) { buf->nFlags = OMX_BUFFERFLAG_STARTTIME; first_packet = 0; } else buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) { status = -6; break; } } buf->nFilledLen = 0; buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) status = -20; // wait for EOS from render ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, ILCLIENT_BUFFER_FLAG_EOS, 10000); // need to flush the renderer to allow video_decode to disable its input port ilclient_flush_tunnels(tunnel, 0); } fclose(in); ilclient_disable_tunnel(tunnel); ilclient_disable_tunnel(tunnel+1); ilclient_disable_tunnel(tunnel+2); if (video_decode) ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); ilclient_teardown_tunnels(tunnel); ilclient_state_transition(list, OMX_StateIdle); ilclient_state_transition(list, OMX_StateLoaded); ilclient_cleanup_components(list); OMX_Deinit(); ilclient_destroy(client); #endif return status; }