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; }
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_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 }
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); }
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 pixmap_t * rpi_pixmap_decode(pixmap_t *pm, const image_meta_t *im, char *errbuf, size_t errlen) { if(pm->pm_type != PIXMAP_JPEG) return NULL; #ifdef TIMING int64_t ts = showtime_get_ts(), ts2; #endif rpi_pixmap_decoder_t *rpd = pixmap_decoder_create(OMX_IMAGE_CodingJPEG); if(rpd == NULL) return NULL; rpd->rpd_im = im; #ifdef NOCOPY #error check rpd->rpd_decoder->oc_stream_corrupt OMX_PARAM_PORTDEFINITIONTYPE portdef; memset(&portdef, 0, sizeof(portdef)); portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portdef.nVersion.nVersion = OMX_VERSION; portdef.nPortIndex = rpd->rpd_decoder->oc_inport; omxchk(OMX_GetParameter(rpd->rpd_decoder->oc_handle, OMX_IndexParamPortDefinition, &portdef)); omx_send_command(rpd->rpd_decoder, OMX_CommandPortEnable, rpd->rpd_decoder->oc_inport, NULL, 0); OMX_BUFFERHEADERTYPE *buf; for(int i = 0; i < portdef.nBufferCountActual; i++) { omxchk(OMX_UseBuffer(rpd->rpd_decoder->oc_handle, &buf, rpd->rpd_decoder->oc_inport, NULL, pm->pm_size, pm->pm_data)); } // Waits for the OMX_CommandPortEnable command omx_wait_command(rpd->rpd_decoder); omx_set_state(rpd->rpd_decoder, OMX_StateExecuting); CHECKPOINT("Initialized"); buf->nOffset = 0; buf->nFilledLen = pm->pm_size; buf->nFlags |= OMX_BUFFERFLAG_EOS; rpd->rpd_decoder->oc_inflight_buffers++; omxchk(OMX_EmptyThisBuffer(rpd->rpd_decoder->oc_handle, buf)); hts_mutex_lock(&rpd->rpd_mtx); while(rpd->rpd_change == 0) hts_cond_wait(&rpd->rpd_cond, &rpd->rpd_mtx); hts_mutex_unlock(&rpd->rpd_mtx); CHECKPOINT("Setup tunnel"); setup_tunnel(rpd); #else const void *data = pm->pm_data; size_t len = pm->pm_size; hts_mutex_lock(&rpd->rpd_mtx); while(len > 0) { OMX_BUFFERHEADERTYPE *buf; if(rpd->rpd_decoder->oc_stream_corrupt) break; if(rpd->rpd_change == 1) { rpd->rpd_change = 2; hts_mutex_unlock(&rpd->rpd_mtx); setup_tunnel(rpd); hts_mutex_lock(&rpd->rpd_mtx); continue; } if(rpd->rpd_decoder->oc_avail == NULL) { hts_cond_wait(&rpd->rpd_cond, &rpd->rpd_mtx); continue; } buf = rpd->rpd_decoder->oc_avail; rpd->rpd_decoder->oc_avail = buf->pAppPrivate; rpd->rpd_decoder->oc_inflight_buffers++; hts_mutex_unlock(&rpd->rpd_mtx); buf->nOffset = 0; buf->nFilledLen = MIN(len, buf->nAllocLen); memcpy(buf->pBuffer, data, buf->nFilledLen); buf->nFlags = 0; if(len <= buf->nAllocLen) buf->nFlags |= OMX_BUFFERFLAG_EOS; data += buf->nFilledLen; len -= buf->nFilledLen; omxchk(OMX_EmptyThisBuffer(rpd->rpd_decoder->oc_handle, buf)); hts_mutex_lock(&rpd->rpd_mtx); } if(rpd->rpd_decoder->oc_stream_corrupt) { hts_mutex_unlock(&rpd->rpd_mtx); goto err; } if(rpd->rpd_change != 2) { while(rpd->rpd_change == 0 && !rpd->rpd_decoder->oc_stream_corrupt) hts_cond_wait(&rpd->rpd_cond, &rpd->rpd_mtx); hts_mutex_unlock(&rpd->rpd_mtx); if(rpd->rpd_decoder->oc_stream_corrupt) goto err; setup_tunnel(rpd); } else { hts_mutex_unlock(&rpd->rpd_mtx); } #endif omx_wait_fill_buffer(rpd->rpd_resizer, rpd->rpd_buf); CHECKPOINT("Got buffer"); err: omx_flush_port(rpd->rpd_decoder, rpd->rpd_decoder->oc_inport); omx_flush_port(rpd->rpd_decoder, rpd->rpd_decoder->oc_outport); omx_flush_port(rpd->rpd_resizer, rpd->rpd_resizer->oc_inport); omx_flush_port(rpd->rpd_resizer, rpd->rpd_resizer->oc_outport); if(rpd->rpd_tunnel != NULL) { omx_tunnel_destroy(rpd->rpd_tunnel); rpd->rpd_tunnel = NULL; } omx_set_state(rpd->rpd_decoder, OMX_StateIdle); omx_set_state(rpd->rpd_resizer, OMX_StateIdle); if(rpd->rpd_buf != NULL) { omxchk(OMX_FreeBuffer(rpd->rpd_resizer->oc_handle, rpd->rpd_resizer->oc_outport, rpd->rpd_buf)); } omx_release_buffers(rpd->rpd_decoder, rpd->rpd_decoder->oc_inport); omx_set_state(rpd->rpd_resizer, OMX_StateLoaded); omx_set_state(rpd->rpd_decoder, OMX_StateLoaded); omx_component_destroy(rpd->rpd_resizer); omx_component_destroy(rpd->rpd_decoder); hts_cond_destroy(&rpd->rpd_cond); hts_mutex_destroy(&rpd->rpd_mtx); pixmap_t *out = rpd->rpd_pm; if(out) { pixmap_release(pm); } else { snprintf(errbuf, errlen, "Load error"); } free(rpd); CHECKPOINT("All done"); return out; }
void omx_flush_port(omx_component_t *oc, int port) { omx_send_command(oc, OMX_CommandFlush, port, NULL, 1); }
void omx_port_enable(omx_component_t *c, int port) { omx_send_command(c, OMX_CommandPortEnable, port, NULL, 0); }
void omx_flush_port(omx_component_t *oc, int port) { printf("Flushing %s %d\n", oc->oc_name, port); omx_send_command(oc, OMX_CommandFlush, port, NULL, 1); }