/* * This routine creates the catacomb-like tunnels by removing extra rock. * Note that this routine is only called on "even" squares - so it gives * a natural checkerboard pattern. */ static void create_cata_tunnel(int x, int y) { int x1, y1; /* Build tunnel */ x1 = x - 1; y1 = y; set_tunnel(&x1, &y1, FALSE); x1 = x + 1; y1 = y; set_tunnel(&x1, &y1, FALSE); x1 = x; y1 = y - 1; set_tunnel(&x1, &y1, FALSE); x1 = x; y1 = y + 1; set_tunnel(&x1, &y1, FALSE); }
// Modified function prototype to work with pthreads void *video_decode_test(void* arg) { const char* filename = "/opt/vc/src/hello_pi/hello_video/test.h264"; eglImage = arg; if (eglImage == 0) { printf("eglImage is null.\n"); exit(1); } OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *clock = NULL; COMPONENT_T *list[5]; TUNNEL_T tunnel[4]; ILCLIENT_T *client; FILE *in; int status = 0; unsigned int data_len = 0; int packet_size = 80<<10; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((in = fopen(filename, "rb")) == NULL) return (void *)-2; if((client = ilclient_init()) == NULL) { fclose(in); return (void *)-3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(in); return (void *)-4; } // callback ilclient_set_fill_buffer_done_callback(client, my_fill_buffer_done, 0); // 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) if(status == 0 && ilclient_create_component(client, &video_render, "egl_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 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)); 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+1, video_scheduler, 11, video_render, 220); 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; 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; // loop if at end if (feof(in)) rewind(in); data_len += fread(dest, 1, packet_size-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; } // Set egl_render to idle ilclient_change_component_state(video_render, OMX_StateIdle); // Enable the output port and tell egl_render to use the texture as a buffer //ilclient_enable_port(video_render, 221); THIS BLOCKS SO CANT BE USED if (OMX_SendCommand(ILC_GET_HANDLE(video_render), OMX_CommandPortEnable, 221, NULL) != OMX_ErrorNone) { printf("OMX_CommandPortEnable failed.\n"); exit(1); } if (OMX_UseEGLImage(ILC_GET_HANDLE(video_render), &eglBuffer, 221, NULL, eglImage) != OMX_ErrorNone) { printf("OMX_UseEGLImage failed.\n"); exit(1); } // Set egl_render to executing ilclient_change_component_state(video_render, OMX_StateExecuting); // Request egl_render to write data to the texture buffer if(OMX_FillThisBuffer(ILC_GET_HANDLE(video_render), eglBuffer) != OMX_ErrorNone) { printf("OMX_FillThisBuffer failed.\n"); exit(1); } } 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); ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); } fclose(in); ilclient_disable_tunnel(tunnel); ilclient_disable_tunnel(tunnel+1); ilclient_disable_tunnel(tunnel+2); 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); return (void *)status; }
static int video_decode_test(char *filename) { 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; int status = 0; 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; } // 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)); 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; 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; } 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); 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); return status; }
/* * This routine does the bulk of the work in creating the new types of tunnels. * It is designed to use very simple algorithms to go from (x1,y1) to (x2,y2) * It doesn't need to add any complexity - straight lines are fine. * The SOLID walls are avoided by a recursive algorithm which tries random ways * around the obstical until it works. The number of itterations is counted, and it * this gets too large the routine exits. This should stop any crashes - but may leave * small gaps in the tunnel where there are too many SOLID walls. * * Type 1 tunnels are extremely simple - straight line from A to B. This is only used * as a part of the dodge SOLID walls algorithm. * * Type 2 tunnels are made of two straight lines at right angles. When this is used with * short line segments it gives the "cavelike" tunnels seen deeper in the dungeon. * * Type 3 tunnels are made of two straight lines like type 2, but with extra rock removed. * This, when used with longer line segments gives the "catacomb-like" tunnels seen near * the surface. */ static void short_seg_hack(int x1, int y1, int x2, int y2, int type, int count, bool *fail) { int i, x, y; int length; /* Check for early exit */ if (!(*fail)) return; length = distance(x1, y1, x2, y2); count++; if ((type == 1) && (length != 0)) { for (i = 0; i <= length; i++) { x = x1 + i * (x2 - x1) / length; y = y1 + i * (y2 - y1) / length; if (!set_tunnel(&x, &y, TRUE)) { if (count > 50) { /* This isn't working - probably have an infinite loop */ *fail = FALSE; return; } /* solid wall - so try to go around */ short_seg_hack(x, y, x1 + (i - 1) * (x2 - x1) / length, y1 + (i - 1) * (y2 - y1) / length, 1, count, fail); short_seg_hack(x, y, x1 + (i + 1) * (x2 - x1) / length, y1 + (i + 1) * (y2 - y1) / length, 1, count, fail); } } } else if ((type == 2) || (type == 3)) { if (x1 < x2) { for (i = x1; i <= x2; i++) { x = i; y = y1; if (!set_tunnel(&x, &y, TRUE)) { /* solid wall - so try to go around */ short_seg_hack(x, y, i - 1, y1, 1, count, fail); short_seg_hack(x, y, i + 1, y1, 1, count, fail); } if ((type == 3) && ((x + y) % 2)) { create_cata_tunnel(i, y1); } } } else { for (i = x2; i <= x1; i++) { x = i; y = y1; if (!set_tunnel(&x, &y, TRUE)) { /* solid wall - so try to go around */ short_seg_hack(x, y, i - 1, y1, 1, count, fail); short_seg_hack(x, y, i + 1, y1, 1, count, fail); } if ((type == 3) && ((x + y) % 2)) { create_cata_tunnel(i, y1); } } } if (y1 < y2) { for (i = y1; i <= y2; i++) { x = x2; y = i; if (!set_tunnel(&x, &y, TRUE)) { /* solid wall - so try to go around */ short_seg_hack(x, y, x2, i - 1, 1, count, fail); short_seg_hack(x, y, x2, i + 1, 1, count, fail); } if ((type == 3) && ((x + y) % 2)) { create_cata_tunnel(x2, i); } } } else { for (i = y2; i <= y1; i++) { x = x2; y = i; if (!set_tunnel(&x, &y, TRUE)) { /* solid wall - so try to go around */ short_seg_hack(x, y, x2, i - 1, 1, count, fail); short_seg_hack(x, y, x2, i + 1, 1, count, fail); } if ((type == 3) && ((x + y) % 2)) { create_cata_tunnel(x2, i); } } } } }
/* * This routine maps a path from (x1, y1) to (x2, y2) avoiding SOLID walls. * Permanent rock is ignored in this path finding- sometimes there is no * path around anyway -so there will be a crash if we try to find one. * This routine is much like the river creation routine in Zangband. * It works by dividing a line segment into two. The segments are divided * until they are less than "cutoff" - when the corresponding routine from * "short_seg_hack" is called. * Note it is VERY important that the "stop if hit another passage" logic * stays as is. Without this the dungeon turns into Swiss Cheese... */ bool build_tunnel2(int x1, int y1, int x2, int y2, int type, int cutoff) { int x3, y3, dx, dy; int changex, changey; int length; int i; bool retval, firstsuccede; cave_type *c_ptr; length = distance(x1, y1, x2, y2); if (length > cutoff) { /* * Divide path in half and call routine twice. */ dx = (x2 - x1) / 2; dy = (y2 - y1) / 2; /* perturbation perpendicular to path */ changex = (randint0(abs(dy) + 2) * 2 - abs(dy) - 1) / 2; /* perturbation perpendicular to path */ changey = (randint0(abs(dx) + 2) * 2 - abs(dx) - 1) / 2; /* Work out "mid" ponit */ x3 = x1 + dx + changex; y3 = y1 + dy + changey; /* See if in bounds - if not - do not perturb point */ if (!in_bounds(y3, x3)) { x3 = (x1 + x2) / 2; y3 = (y1 + y2) / 2; } /* cache c_ptr */ c_ptr = &cave[y3][x3]; if (is_solid_grid(c_ptr)) { /* move midpoint a bit to avoid problem. */ i = 50; dy = 0; dx = 0; while ((i > 0) && is_solid_bold(y3 + dy, x3 + dx)) { dy = randint0(3) - 1; dx = randint0(3) - 1; if (!in_bounds(y3 + dy, x3 + dx)) { dx = 0; dy = 0; } i--; } if (i == 0) { /* Failed for some reason: hack - ignore the solidness */ place_outer_bold(y3, x3); dx = 0; dy = 0; } y3 += dy; x3 += dx; c_ptr = &cave[y3][x3]; } if (is_floor_grid(c_ptr)) { if (build_tunnel2(x1, y1, x3, y3, type, cutoff)) { if ((cave[y3][x3].info & CAVE_ROOM) || (randint1(100) > 95)) { /* do second half only if works + if have hit a room */ retval = build_tunnel2(x3, y3, x2, y2, type, cutoff); } else { /* have hit another tunnel - make a set of doors here */ retval = FALSE; /* Save the door location */ if (dun->door_n < DOOR_MAX) { dun->door[dun->door_n].y = y3; dun->door[dun->door_n].x = x3; dun->door_n++; } else return FALSE; } firstsuccede = TRUE; } else { /* false- didn't work all the way */ retval = FALSE; firstsuccede = FALSE; } } else { /* tunnel through walls */ if (build_tunnel2(x1, y1, x3, y3, type, cutoff)) { retval = build_tunnel2(x3, y3, x2, y2, type, cutoff); firstsuccede = TRUE; } else { /* false- didn't work all the way */ retval = FALSE; firstsuccede = FALSE; } } if (firstsuccede) { /* only do this if the first half has worked */ set_tunnel(&x3, &y3, TRUE); } /* return value calculated above */ return retval; } else { /* Do a short segment */ retval = TRUE; short_seg_hack(x1, y1, x2, y2, type, 0, &retval); /* Hack - ignore return value so avoid infinite loops */ return TRUE; } }
static int image_decode_test(char *filename) { OMX_BUFFERHEADERTYPE *pIbuf; int bytes_read; int status = 0, ret; int port_settings_changed = 0; OMX_IMAGE_PARAM_PORTFORMATTYPE imagePortFormat; COMPONENT_T *image_decode = NULL; COMPONENT_T *video_render = NULL; COMPONENT_T *list[3]; TUNNEL_T tunnel[2]; ILCLIENT_T *client; FILE *fin; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((fin = fopen(filename, "rb")) == NULL ) { perror(filename); return -1; } if((client = ilclient_init()) == NULL) { return -3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(fin); return -4; } #if 0 //this was an attempt to use the image_read component COMPONENT_T *image_read; // create image_read if(ilclient_create_component(client, &image_read, "image_read", ILCLIENT_DISABLE_ALL_PORTS ) != 0) status = -14; //set URI OMX_PARAM_CONTENTURITYPE *pUri; sz = sizeof(pUri)+strlen(filename); pUri = (OMX_PARAM_CONTENTURITYPE*)calloc(1, sz); pUri->nSize = sz; pUri->nVersion.nVersion = OMX_VERSION; strcpy(pUri->contentURI, filename); if(image_read != NULL && OMX_SetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamContentURI, pUri) != 0) status = -17; //enable port ilclient_enable_port(image_read, 310); //get OMX_IndexParamPortDefinition { OMX_PARAM_PORTDEFINITIONTYPE portDef; portDef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portDef.nVersion.nVersion = OMX_VERSION; portDef.nPortIndex = 310; ret = OMX_GetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamPortDefinition, &portDef); } //get OMX_IndexParamImagePortFormat i=0; while(ret == 0) { OMX_IMAGE_PARAM_PORTFORMATTYPE portFormat; portFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); portFormat.nVersion.nVersion = OMX_VERSION; portFormat.nPortIndex = 310; portFormat.nIndex = i; ret = OMX_GetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamImagePortFormat, &portFormat); i++; } { OMX_IMAGE_PARAM_PORTFORMATTYPE portFormat; portFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); portFormat.nVersion.nVersion = OMX_VERSION; portFormat.nPortIndex = 310; portFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG; ret = OMX_SetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamImagePortFormat, &portFormat); } if((ret = ilclient_change_component_state(image_read, OMX_StateIdle) < 0)) //this fails printf("Cannot change image_read component state to OMX_StateIdle\n"); #endif //image_read attempt // create image_decode ret = ilclient_create_component(client, &image_decode, "image_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS ); if (ret != 0) status = -15; list[0] = image_decode; // create video_render ret = ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS); if (ret != 0) status = -14; list[1] = video_render; list[2] = NULL; ret = ilclient_change_component_state(image_decode, OMX_StateIdle); set_tunnel(tunnel, image_decode, 321, video_render, 90); #if 0 //not necessary { //get OMX_IndexParamPortDefinition OMX_PARAM_PORTDEFINITIONTYPE portDef; portDef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portDef.nVersion.nVersion = OMX_VERSION; portDef.nPortIndex = 320; ret = OMX_GetParameter(ILC_GET_HANDLE(image_decode), OMX_IndexParamPortDefinition, &portDef); } #endif { // OMX_IndexParamImagePortFormat imagePortFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); imagePortFormat.nVersion.nVersion = OMX_VERSION; imagePortFormat.nPortIndex = 320; imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG; // imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingPNG; //does not seem to work // imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingAutoDetect; //does not seem to work. ret = OMX_SetParameter(ILC_GET_HANDLE(image_decode), OMX_IndexParamImagePortFormat, &imagePortFormat); } ret = ilclient_enable_port_buffers(image_decode, 320, NULL, NULL, NULL); ret = ilclient_change_component_state(image_decode, OMX_StateExecuting); while( (pIbuf = ilclient_get_input_buffer(image_decode, 320, 1)) != NULL ) { bytes_read = fread(pIbuf->pBuffer, 1, pIbuf->nAllocLen, fin); if( port_settings_changed == 0 && (( bytes_read > 0 && ilclient_remove_event(image_decode, OMX_EventPortSettingsChanged, 321, 0, 0, 1) == 0) || ( bytes_read == 0 && ilclient_wait_for_event(image_decode, OMX_EventPortSettingsChanged, 321, 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_render, OMX_StateExecuting); } if(!bytes_read) break; pIbuf->nFilledLen = bytes_read; pIbuf->nOffset = 0; pIbuf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(image_decode), pIbuf) != OMX_ErrorNone) { status = -6; break; } } pIbuf->nFilledLen = 0; pIbuf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(image_decode), pIbuf) != 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); printf("Press ENTER to continue...\n"); fflush(stdout); getchar(); // need to flush the renderer to allow video_decode to disable its input port // ilclient_flush_tunnels(tunnel, 0); ilclient_disable_port_buffers(image_decode, 320, NULL, NULL, NULL); fclose(fin); ilclient_disable_tunnel(tunnel); ilclient_teardown_tunnels(tunnel); ret = ilclient_change_component_state(image_decode, OMX_StateIdle); ret = ilclient_change_component_state(image_decode, OMX_StateLoaded); ilclient_cleanup_components(list); OMX_Deinit(); ilclient_destroy(client); return status; }
// Modified function prototype to work with pthreads void *video_decode_test(void* arg) { pthread_mutex_init(&m_lock, NULL); printf("OMX version : %d.%d.%d-%d\n",OMX_VERSION_MAJOR, OMX_VERSION_MINOR, OMX_VERSION_REVISION, OMX_VERSION_STEP); printf("file to read : %s\n", filename); eglImage = arg; if (eglImage == 0) { printf("eglImage is null.\n"); exit(1); } int status = 0; unsigned int data_len = 0; int packet_size = 80<<10; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((in = fopen(filename, "rb")) == NULL) return (void *)-2; if((client = ilclient_init()) == NULL) { fclose(in); return (void *)-3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(in); return (void *)-4; } // callback ilclient_set_fill_buffer_done_callback(client, my_fill_buffer_done, 0); // 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) if(status == 0 && ilclient_create_component(client, &video_render, "egl_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 0) status = -14; list[1] = video_render; // create clock if(status == 0 && ilclient_create_component(client, &omx_clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[2] = omx_clock; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; if(omx_clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone) status = -13; // set the clock refenrece to "none" memset(&cref,0,sizeof(cref)); cref.nSize = sizeof(cref); cref.nVersion.nVersion = OMX_VERSION; cref.eClock = OMX_TIME_RefClockNone; if(omx_clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeActiveRefClock, &cref) != OMX_ErrorNone){ status = -13; printf("error setting refclock\n"); } // 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+1, video_scheduler, 11, video_render, 220); set_tunnel(tunnel+2, omx_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(omx_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; 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 && stop_flag==0 ) { // feed data and wait until we get port settings changed unsigned char *dest = buf->pBuffer; // loop if at end if (feof(in)) rewind(in); data_len += fread(dest, 1, packet_size-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; } // Set egl_render to idle ilclient_change_component_state(video_render, OMX_StateIdle); // Enable the output port and tell egl_render to use the texture as a buffer //ilclient_enable_port(video_render, 221); THIS BLOCKS SO CANT BE USED if (OMX_SendCommand(ILC_GET_HANDLE(video_render), OMX_CommandPortEnable, 221, NULL) != OMX_ErrorNone) { printf("OMX_CommandPortEnable failed.\n"); exit(1); } if (OMX_UseEGLImage(ILC_GET_HANDLE(video_render), &eglBuffer, 221, NULL, eglImage) != OMX_ErrorNone) { printf("OMX_UseEGLImage failed.\n"); exit(1); } // Set egl_render to executing ilclient_change_component_state(video_render, OMX_StateExecuting); // Request egl_render to write data to the texture buffer if(OMX_FillThisBuffer(ILC_GET_HANDLE(video_render), eglBuffer) != OMX_ErrorNone) { printf("OMX_FillThisBuffer failed.\n"); //~ exit(1); } } 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; } } printf("loop ends, now flush the buffer\n"); OMX_SendCommand(ILC_GET_HANDLE(video_decode),OMX_CommandFlush,130,NULL); OMX_SendCommand(ILC_GET_HANDLE(video_decode),OMX_CommandFlush,131,NULL); ilclient_wait_for_event(video_decode, OMX_EventCmdComplete, OMX_CommandFlush, 0, 130, 0, ILCLIENT_PORT_FLUSH, -1); ilclient_wait_for_event(video_decode, OMX_EventCmdComplete, OMX_CommandFlush, 0, 131, 0, ILCLIENT_PORT_FLUSH, -1); data_len=0; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateStopped; cstate.nWaitMask = 1; OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeClockState, &cstate); memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeClockState, &cstate); //~ scheduler should be stopped... 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 //~ printf("wait for EOS from render\n"); //~ ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, //~ ILCLIENT_BUFFER_FLAG_EOS, 10000); while ((ilclient_remove_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0) <0 ) && !stop_flag){ } printf("flush the render\n"); // need to flush the renderer to allow video_decode to disable its input port ilclient_flush_tunnels(tunnel, 0); ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); } printf("close file\n"); fclose(in); ilclient_disable_tunnel(tunnel); ilclient_disable_tunnel(tunnel+1); ilclient_disable_tunnel(tunnel+2); 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); printf("thread will return...\n"); pthread_mutex_destroy(&m_lock); return (void *)status; }
/* ------------------------------------------------- / audioplay_create() / Create audio decoder & render & other hardware component /---------------------------------------------------*/ static INT32 audioplay_create( AUDIOPLAY_STATE_T **handle, UINT32 sample_rate, UINT32 num_channels, UINT32 bit_depth, UINT32 num_buffers, ///< 100 UINT32 buffer_size ///< 480*(16/8)*2 = 1920 ){ OMX_AUDIO_PARAM_PCMMODETYPE pcm; UINT32 bytes_per_sample = (bit_depth * num_channels) >> 3; INT32 ret = -1; int rv; *handle = NULL; /* TODO basic sanity check on arguments */ if(sample_rate >= 8000 && sample_rate <= 96000 && (num_channels == 1 || num_channels == 2 || num_channels == 4 || num_channels == 8) && (bit_depth == 16 || bit_depth == 32) && (num_buffers > 0) && (buffer_size >= bytes_per_sample)){ /* TODO buffer length must be 16 bytes aligned for VCHI */ int size = (buffer_size + 15) & ~15; /* TODO buffer length must be 16 bytes aligned for VCHI */ st = calloc(1, sizeof(AUDIOPLAY_STATE_T)); assert(st != NULL); OMX_ERRORTYPE error; OMX_PARAM_PORTDEFINITIONTYPE param; INT32 s; ret = 0; /* TODO combine with st = calloc()?*/ *handle = st; /* create and start up audio codec hardware component */ /* TODO semaphore */ s = sem_init(&st->sema, 0 ,1); assert(s == 0); st->bytes_per_sample = bytes_per_sample; st->num_buffers = num_buffers; st->client = ilclient_init(); assert(st->client != NULL); /*TODO input_buffer_callback*/ ilclient_set_empty_buffer_done_callback(st->client, input_buffer_callback, st); error = OMX_Init(); assert(error == OMX_ErrorNone); /* Create audio render */ ilclient_create_component(st->client, &(st->audio_render), "audio_render", ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_DISABLE_ALL_PORTS); assert(st->audio_render != NULL); st->list[0] = st->audio_render; /* Create clock component */ ilclient_create_component(st->client, &(st->clock), "clock", ILCLIENT_DISABLE_ALL_PORTS); assert(st->clock != NULL); st->list[1] = st->clock; /* Configure clock */ OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; //TODO error = OMX_SetParameter(ILC_GET_HANDLE(st->clock), OMX_IndexConfigTimeClockState, &cstate); assert(error == 0); /* Setup tunnel to connect clock and audio render */ set_tunnel(&st->tunnel, st->clock, 80, st->audio_render, 101); rv = ilclient_setup_tunnel(&st->tunnel, 0, 0); assert(rv == 0); /* kick off clock */ ilclient_change_component_state(st->clock, OMX_StateExecuting); /* Set audio render port definition */ /* Set up the number/size of buffers */ memset(¶m, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); param.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); param.nVersion.nVersion = OMX_VERSION; param.nPortIndex = 100; error = OMX_GetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m); assert(error == OMX_ErrorNone); param.nBufferSize = size; param.nBufferCountActual = num_buffers; error = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m); assert(error == OMX_ErrorNone); /* Set audio render PCM definition */ memset(&pcm, 0, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); pcm.nSize = sizeof(OMX_AUDIO_PARAM_PCMMODETYPE); pcm.nVersion.nVersion = OMX_VERSION; pcm.nPortIndex = 100; pcm.nChannels = num_channels; pcm.eNumData = OMX_NumericalDataSigned; //TODO pcm.eEndian = OMX_EndianLittle; pcm.nSamplingRate = sample_rate; pcm.bInterleaved = OMX_TRUE; pcm.nBitPerSample = bit_depth; pcm.ePCMMode = OMX_AUDIO_PCMModeLinear; switch(num_channels){ case 1: { pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF; break; } case 8: { /*TODO*/ pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF; pcm.eChannelMapping[3] = OMX_AUDIO_ChannelLFE; pcm.eChannelMapping[4] = OMX_AUDIO_ChannelLR; pcm.eChannelMapping[5] = OMX_AUDIO_ChannelRR; pcm.eChannelMapping[6] = OMX_AUDIO_ChannelLS; pcm.eChannelMapping[7] = OMX_AUDIO_ChannelRS; break; } case 4: { pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[2] = OMX_AUDIO_ChannelLR; pcm.eChannelMapping[3] = OMX_AUDIO_ChannelRR; break; } case 2: { pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; break; } } error = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamAudioPcm, &pcm); assert(error == OMX_ErrorNone); /* Set audio reference clock */ OMX_CONFIG_BOOLEANTYPE ref_clock; memset(&ref_clock, 0, sizeof(OMX_CONFIG_BOOLEANTYPE)); param.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); param.nVersion.nVersion = OMX_VERSION; param.bEnabled = OMX_FALSE; error = OMX_SetConfig(ILC_GET_HANDLE(st->audio_render), OMX_IndexConfigBrcmClockReferenceSource, &ref_clock); assert(error == OMX_ErrorNone); /* Enable audio render */ ilclient_change_component_state(st->audio_render, OMX_StateIdle); if(ilclient_enable_port_buffers(st->audio_render, 100, NULL, NULL, NULL) < 0){ /* Error situation */ ilclient_change_component_state(st->audio_render, OMX_StateLoaded); ilclient_cleanup_components(st->list); error = OMX_Deinit(); assert(error == OMX_ErrorNone); ilclient_destroy(st->client); sem_destroy(&st->sema); free(st); *handle = NULL; return -1; } ilclient_change_component_state(st->audio_render, OMX_StateExecuting); } return ret; }
/* ------------------------------------------------- / sx_video_sink_init() / /---------------------------------------------------*/ void sx_video_sink_init(void){ OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; int rc; /* Init compoent & tunnel */ memset(comp_list, 0, sizeof(comp_list)); memset(tunnel, 0, sizeof(tunnel)); /* Init Broadcom host */ bcm_host_init(); /* Init il client */ client = ilclient_init(); assert(client != NULL); /* Init OpenMax */ rc = OMX_Init(); assert(rc == OMX_ErrorNone); /* Create Decoder Component,beacuse enable input buffers,so in the end need to OMX_EmptyThisBuffer */ rc = ilclient_create_component( client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS); assert(rc == 0); comp_list[0] = video_decode; /* Create video render */ rc = ilclient_create_component( client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS); assert(rc == 0); comp_list[1] = video_render; /* Create clock */ rc = ilclient_create_component( client, &video_clock, "clock", ILCLIENT_DISABLE_ALL_PORTS); assert(rc == 0); comp_list[2] = video_clock; /* Configure clock */ memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; rc = OMX_SetParameter(ILC_GET_HANDLE(video_clock), OMX_IndexConfigTimeClockState, &cstate); assert(rc == 0); /* Create video scheduler */ rc = ilclient_create_component( client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS); assert(rc == 0); comp_list[3] = video_scheduler; /* Set tunnels */ /* Connect decode to scheduler */ set_tunnel(tunnel, video_decode, 131, video_scheduler, 10); /* Connect scheduler to render */ set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90); /* Connect clock to scheduler */ set_tunnel(tunnel+2, video_clock, 80, video_scheduler, 12); /* Setup clock tunnel first */ rc = ilclient_setup_tunnel(tunnel+2, 0, 0); assert(rc == 0); /* Kick start the clock */ ilclient_change_component_state(video_clock, OMX_StateExecuting); #define AUTO_FULLSCREEN #if 1 OMX_CONFIG_DISPLAYREGIONTYPE drt; memset(&drt, 0, sizeof(drt)); drt.nVersion.nVersion = OMX_VERSION; drt.nSize = sizeof(drt); drt.nPortIndex = 90; /* if not defined AUTO_FULLSCREEN it means that set other display region type */ #if 0 #if !defined(AUTO_FULLSCREEN) /*TODO*/ drt.src_rect.x_offset = 0; drt.src_rect.y_offset = 0; drt.src_rect.width = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_WIDTH); drt.src_rect.height = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_HEIGHT); drt.dest_rect.x_offset = -56; drt.dest_rect.y_offset = 0; drt.dest_rect.width = 1792; drt.dest_rect.height = 1050; #endif #endif #if !defined(AUTO_FULLSCREEN) drt.fullscreen = OMX_FALSE; #else /* define AUTO_FULLSCREEN */ drt.fullscreen = OMX_TRUE; #endif drt.noaspect = OMX_TRUE; drt.mode = OMX_DISPLAY_MODE_FILL; #if !defined(AUTO_FULLSCREEN) /*TODO*/ drt.set = (OMX_DISPLAYSETTYPE) ( OMX_DISPLAY_SET_SRC_RECT | OMX_DISPLAY_SET_DEST_RECT | OMX_DISPLAY_SET_FULLSCREEN | OMX_DISPLAY_SET_NOASPECT); #else drt.set = (OMX_DISPLAYSETTYPE) (OMX_DISPLAY_SET_FULLSCREEN | OMX_DISPLAY_SET_NOASPECT); #endif rc = OMX_SetConfig(ILC_GET_HANDLE(video_render), OMX_IndexConfigDisplayRegion, &drt); assert(rc==0); #endif /* Kick start video decoder */ ilclient_change_component_state(video_decode, OMX_StateIdle); /*TODO Configure decoder */ 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; rc = OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format); assert(rc == 0); /* Enable video decode */ rc = ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL); assert(rc ==0); /* Kick start video decode */ ilclient_change_component_state(video_decode, OMX_StateExecuting); printf("decoder_hw: initialized"); }
void *initLocalCamera(void *VoidPtrArgs) { struct cameraControl *currentArgs = VoidPtrArgs; pthread_mutex_lock(¤tArgs->mutexPtr); ILCLIENT_T *client = currentArgs->client; pthread_mutex_unlock(¤tArgs->mutexPtr); ////////////////// //VARIABLES COMPONENT_T *camera = NULL, *video_render = NULL, *image_encode = NULL; COMPONENT_T *component_list[3] = {camera, video_render, image_encode}; COMPONENT_T *image_encode_list[1] = {image_encode}; //needed to destroy component? OMX_ERRORTYPE OMXstatus; TUNNEL_T tunnel_camera_to_render, tunnel_camera_to_encode; memset(&tunnel_camera_to_render, 0, sizeof(tunnel_camera_to_render)); memset(&tunnel_camera_to_encode, 0, sizeof(tunnel_camera_to_encode)); ////////////////// // STARTUP ////////////////// // Initalize Components ////////////////// ////initialise camera ilclient_create_component(client, &camera, "camera", ILCLIENT_DISABLE_ALL_PORTS); OMXstatus = ilclient_change_component_state(camera, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move camera component to Idle (1)"); exit(EXIT_FAILURE); } //change the capture resolution setCaptureRes(camera, currentArgs->photoWidth, currentArgs->photoHeight); //change the preview resolution setPreviewRes(camera, currentArgs->previewWidth, currentArgs->previewHeight, currentArgs->previewFramerate); ////////////////// ////Initialise video render ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS ); OMXstatus = ilclient_change_component_state(video_render, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move render component to Idle (1)\n"); exit(EXIT_FAILURE); } setRenderConfig(video_render, currentArgs->displayType); //////////////////// ////Initalise Image Encoder ilclient_create_component(client, &image_encode, "image_encode", ILCLIENT_DISABLE_ALL_PORTS /*| ILCLIENT_ENABLE_INPUT_BUFFERS*/ | ILCLIENT_ENABLE_OUTPUT_BUFFERS); OMXstatus = ilclient_change_component_state(image_encode, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move image encode component to Idle (1)\n"); exit(EXIT_FAILURE); } //image format Param set setParamImageFormat(image_encode, JPEG_HIGH_FORMAT); //////////////////// // enable components and tunnels //setup tunnel of camera preview to renderer set_tunnel(&tunnel_camera_to_render, camera, 70, video_render, 90); ilclient_setup_tunnel(&tunnel_camera_to_render, 0, 0); // change camera component to executing OMXstatus = ilclient_change_component_state(camera, OMX_StateExecuting); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move camera component to Executing (1)\n"); exit(EXIT_FAILURE); } //change preview render to executing OMXstatus = ilclient_change_component_state(video_render, OMX_StateExecuting); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move video render component to Executing (1)\n"); exit(EXIT_FAILURE); } //enable port and buffers for output port of image encode ilclient_enable_port_buffers(image_encode, 341, NULL, NULL, NULL); ilclient_enable_port(image_encode, 341); //setup tunnel from camera image port too image encode set_tunnel(&tunnel_camera_to_encode, camera, 72, image_encode, 340); ilclient_setup_tunnel(&tunnel_camera_to_encode, 0, 0); //change image_encode to executing OMXstatus = ilclient_change_component_state(image_encode, OMX_StateExecuting); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move image_encode component to Executing (1) Error = %s\n", err2str(OMXstatus)); exit(EXIT_FAILURE); } ///////////////// // Main initLocalCamera() Loop while(1) { pthread_mutex_lock(¤tArgs->mutexPtr); if (currentArgs->previewChanged == true) { //working ilclient_disable_tunnel(&tunnel_camera_to_render); OMXstatus = ilclient_change_component_state(camera, OMX_StatePause); setPreviewRes(camera, currentArgs->previewWidth, currentArgs->previewHeight, currentArgs->previewFramerate); OMXstatus = ilclient_change_component_state(camera, OMX_StateExecuting); ilclient_enable_tunnel(&tunnel_camera_to_render); currentArgs->previewChanged = false; } else if (currentArgs->photoChanged == true) { //NOT WORKING? CANT GET WORKING!! //TUNNEL_T *tunnel_ptr = &tunnel_camera_to_encode; ilclient_disable_tunnel(&tunnel_camera_to_encode); ilclient_flush_tunnels(&tunnel_camera_to_encode, 30); //ilclient_teardown_tunnels(&tunnel_camera_to_encode); //printf("teardown done"); setCaptureRes(camera, currentArgs->photoWidth, currentArgs->photoHeight); // DESTROY image encode and recreate (appears to be the only way) //destory OMXstatus = ilclient_change_component_state(image_encode, OMX_StateIdle); OMXstatus = ilclient_change_component_state(image_encode, OMX_StateLoaded); //OMX_FreeHandle(ilclient_get_handle(image_encode)); ilclient_cleanup_components(image_encode_list); printf("managed to free the image_encode handle"); image_encode = NULL; //recreate ilclient_create_component(client, &image_encode, "image_encode", ILCLIENT_DISABLE_ALL_PORTS /*| ILCLIENT_ENABLE_INPUT_BUFFERS*/ | ILCLIENT_ENABLE_OUTPUT_BUFFERS); OMXstatus = ilclient_change_component_state(image_encode, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move image encode component to Idle (1)\n"); exit(EXIT_FAILURE); } //image format Param set setParamImageFormat(image_encode, JPEG_HIGH_FORMAT); //OMXstatus = ilclient_change_component_state(camera, OMX_StateExecuting); ilclient_enable_tunnel(&tunnel_camera_to_encode); currentArgs->photoChanged = false; } else if (currentArgs->displayChanged == true) { //working setRenderConfig(video_render, currentArgs->displayType); currentArgs->displayChanged = false; } else if (currentArgs->takePhoto == true) { //working savePhoto(camera, image_encode, "/home/pi/Desktop/photo_", "_L.jpg"); currentArgs->takePhoto = false; } //loop termination else if (currentArgs->rcamDeInit == true) { //working printf("~~~~~ End local camera ~~~~~\n"); break; } pthread_mutex_unlock(¤tArgs->mutexPtr); usleep(500); } /////////////// //CLEANUP // Teardown tunnels ilclient_disable_tunnel(&tunnel_camera_to_render); ilclient_disable_tunnel(&tunnel_camera_to_encode); ilclient_teardown_tunnels(&tunnel_camera_to_render); ilclient_teardown_tunnels(&tunnel_camera_to_encode); // Disable components ilclient_cleanup_components(component_list); //Destroy ilclient // dont do for local as its done in main program //ilclient_destroy(currentArgs->client) //unlock mutex before teminating pthread_mutex_unlock(¤tArgs->mutexPtr); //call pthread_exit so caller can join pthread_exit(NULL); }