void omx_alloc_buffers(omx_component_t *oc, int port) { OMX_PARAM_PORTDEFINITIONTYPE portdef; memset(&portdef, 0, sizeof(portdef)); portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portdef.nVersion.nVersion = OMX_VERSION; portdef.nPortIndex = port; omxchk(OMX_GetParameter(oc->oc_handle, OMX_IndexParamPortDefinition, &portdef)); if(portdef.bEnabled != OMX_FALSE || portdef.nBufferCountActual == 0 || portdef.nBufferSize == 0) exit(3); omxdbg("Allocating buffers for %s:%d\n", oc->oc_name, port); omxdbg(" buffer count = %d\n", (int)portdef.nBufferCountActual); omxdbg(" buffer size = %d\n", (int)portdef.nBufferSize); omx_send_command(oc, OMX_CommandPortEnable, port, NULL, 0); int i; for(i = 0; i < portdef.nBufferCountActual; i++) { OMX_BUFFERHEADERTYPE *buf; omxchk(OMX_AllocateBuffer(oc->oc_handle, &buf, port, NULL, portdef.nBufferSize)); omxdbg("buf=%p\n", buf); buf->pAppPrivate = oc->oc_avail; oc->oc_avail = buf; oc->oc_avail_bytes += buf->nAllocLen; } omx_wait_command(oc); // Waits for the OMX_CommandPortEnable command }
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; }
static OMX_ERRORTYPE oc_event_handler(OMX_HANDLETYPE component, OMX_PTR opaque, OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2, OMX_PTR eventdata) { omx_component_t *oc = opaque; #if 1 omxdbg("%s: event 0x%x 0x%x 0x%x %p\n", oc->oc_name, event, (int)data1, (int)data2, eventdata); #endif switch(event) { case OMX_EventCmdComplete: complete: hts_mutex_lock(oc->oc_mtx); oc->oc_cmd_done = 1; hts_cond_broadcast(&oc->oc_event_cond); hts_mutex_unlock(oc->oc_mtx); break; case OMX_EventError: switch(data1) { case OMX_ErrorPortUnpopulated: break; case OMX_ErrorSameState: goto complete; case OMX_ErrorStreamCorrupt: TRACE(TRACE_INFO, "OMX", "%s: Corrupt stream", oc->oc_name); hts_mutex_lock(oc->oc_mtx); oc->oc_stream_corrupt = 1; hts_cond_signal(oc->oc_avail_cond); hts_mutex_unlock(oc->oc_mtx); break; default: TRACE(TRACE_ERROR, "OMX", "%s: ERROR 0x%x\n", oc->oc_name, (int)data1); break; } break; case OMX_EventPortSettingsChanged: if(oc->oc_port_settings_changed_cb != NULL) oc->oc_port_settings_changed_cb(oc); break; case OMX_EventMark: if(oc->oc_event_mark_cb != NULL) oc->oc_event_mark_cb(oc, eventdata); break; default: break; } return 0; }
void omx_set_state(omx_component_t *oc, OMX_STATETYPE reqstate) { OMX_STATETYPE state; int attempts = 20; omxchk(OMX_GetState(oc->oc_handle, &state)); omxdbg("Telling component '%s' to go from state %d -> to state %d\n", oc->oc_name, state, reqstate); while(1) { oc->oc_cmd_done = 0; int r = OMX_SendCommand(oc->oc_handle, OMX_CommandStateSet, reqstate, NULL); if(r == OMX_ErrorInsufficientResources && attempts) { usleep(10000); attempts--; continue; } if(r != 0) { panic("OMX Setstate %s from %d to %d error 0x%x", oc->oc_name, state, reqstate, r); } if(reqstate == OMX_StateExecuting) omx_wait_command(oc); return; } }
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); }
void omx_set_state(omx_component_t *oc, OMX_STATETYPE reqstate) { OMX_STATETYPE state; omxchk(OMX_GetState(oc->oc_handle, &state)); omxdbg("Telling component '%s' to go from state %d -> to state %d\n", oc->oc_name, state, reqstate); omx_send_command(oc, OMX_CommandStateSet, reqstate, NULL, reqstate != OMX_StateLoaded); }
void omx_send_command(omx_component_t *oc, OMX_COMMANDTYPE cmd, int v, void *p, int wait) { oc->oc_cmd_done = 0; omxdbg("%s: CMD(0x%x, 0x%x, %p)\n", oc->oc_name, cmd, v, p); omxchk(OMX_SendCommand(oc->oc_handle, cmd, v, p)); if(wait) omx_wait_command(oc); }
omx_component_t * omx_component_create(const char *name, hts_mutex_t *mtx, hts_cond_t *avail_cond) { omx_component_t *oc = calloc(1, sizeof(omx_component_t)); OMX_CALLBACKTYPE cb; const OMX_INDEXTYPE types[] = {OMX_IndexParamAudioInit, OMX_IndexParamVideoInit, OMX_IndexParamImageInit, OMX_IndexParamOtherInit}; assert(mtx != NULL); oc->oc_mtx = mtx; oc->oc_avail_cond = avail_cond; hts_cond_init(&oc->oc_event_cond, oc->oc_mtx); oc->oc_name = strdup(name); cb.EventHandler = oc_event_handler; cb.EmptyBufferDone = oc_empty_buffer_done; cb.FillBufferDone = oc_fill_buffer_done; // omxdbg("Creating %s\n", oc->oc_name); omxchk(OMX_GetHandle(&oc->oc_handle, oc->oc_name, oc, &cb)); // Initially disable ports int i; for(i = 0; i < 4; i++) { OMX_PORT_PARAM_TYPE ports; ports.nSize = sizeof(OMX_PORT_PARAM_TYPE); ports.nVersion.nVersion = OMX_VERSION; omxchk(OMX_GetParameter(oc->oc_handle, types[i], &ports)); omxdbg("%s: type:%d: ports: %d +%d\n", name, i, ports.nStartPortNumber, ports.nPorts); if(ports.nPorts > 0) { oc->oc_inport = ports.nStartPortNumber; oc->oc_outport = ports.nStartPortNumber + 1; } for(int j = 0; j < ports.nPorts; j++) omx_send_command(oc, OMX_CommandPortDisable, ports.nStartPortNumber + j, NULL, 1); } return oc; }
static OMX_ERRORTYPE oc_event_handler(OMX_HANDLETYPE component, OMX_PTR opaque, OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2, OMX_PTR eventdata) { omx_component_t *oc = opaque; omxdbg("%s: event 0x%x 0x%x 0x%x %p\n", oc->oc_name, event, (int)data1, (int)data2, eventdata); hts_mutex_lock(&oc->oc_event_mtx); switch(event) { case OMX_EventCmdComplete: oc->oc_cmd_done = 1; hts_cond_broadcast(&oc->oc_event_cond); break; case OMX_EventError: if(data1 == OMX_ErrorPortUnpopulated) { printf("Port unpopulated\n"); break; } if(data1 == OMX_ErrorSameState) { oc->oc_cmd_done = 1; hts_cond_broadcast(&oc->oc_event_cond); break; } printf("%s: ERROR 0x%x\n", oc->oc_name, (int)data1); exit(1); case OMX_EventPortSettingsChanged: oc->oc_port_settings_changed = 1; break; default: break; } hts_mutex_unlock(&oc->oc_event_mtx); return 0; }