static void rvd_reset(glw_video_t *gv) { rpi_video_display_t *rvd = gv->gv_aux; omx_tunnel_destroy(rvd->rvd_tun_clock_vsched); omx_flush_port(rvd->rvd_vsched, 10); omx_flush_port(rvd->rvd_vsched, 11); omx_flush_port(rvd->rvd_vrender, 90); if(rvd->rvd_tun_vsched_vrender != NULL) omx_tunnel_destroy(rvd->rvd_tun_vsched_vrender); if(rvd->rvd_tun_vdecoder_vsched != NULL) omx_tunnel_destroy(rvd->rvd_tun_vdecoder_vsched); omx_set_state(rvd->rvd_vrender, OMX_StateIdle); omx_set_state(rvd->rvd_vsched, OMX_StateIdle); omx_set_state(rvd->rvd_vrender, OMX_StateLoaded); omx_set_state(rvd->rvd_vsched, OMX_StateLoaded); omx_component_destroy(rvd->rvd_vrender); omx_component_destroy(rvd->rvd_vsched); if(rvd->rvd_mc != NULL) media_codec_deref(rvd->rvd_mc); hts_mutex_destroy(&rvd->rvd_mutex); free(rvd); }
static int64_t rvd_newframe(glw_video_t *gv, video_decoder_t *vd, int flags) { rpi_video_display_t *rvd = gv->gv_aux; if(rvd->rvd_vsched && rvd->rvd_reconfigure) { rvd->rvd_reconfigure = 0; if(rvd->rvd_tun_vsched_vrender) omx_tunnel_destroy(rvd->rvd_tun_vsched_vrender); rvd->rvd_tun_vsched_vrender = omx_tunnel_create(rvd->rvd_vsched, 11, rvd->rvd_vrender, 90, "vsched -> vrender"); omx_set_state(rvd->rvd_vrender, OMX_StateExecuting); OMX_CONFIG_DISPLAYREGIONTYPE dr; OMX_INIT_STRUCTURE(dr); dr.nPortIndex = 90; dr.set = OMX_DISPLAY_SET_LAYER; dr.layer = 3; omxchk(OMX_SetConfig(rvd->rvd_vrender->oc_handle, OMX_IndexConfigDisplayRegion, &dr)); } return rvd->rvd_pts; }
static int rvd_set_codec(media_codec_t *mc, glw_video_t *gv, const frame_info_t *fi) { media_pipe_t *mp = gv->gv_mp; glw_video_configure(gv, &glw_video_rvd); gv->gv_width = fi->fi_width; gv->gv_height = fi->fi_height; rpi_video_display_t *rvd = gv->gv_aux; rpi_video_codec_t *rvc = mc->opaque; if(rvd->rvd_vrender == NULL) { rvd->rvd_vrender = omx_component_create("OMX.broadcom.video_render", &rvd->rvd_mutex, NULL); rvd->rvd_vsched = omx_component_create("OMX.broadcom.video_scheduler", &rvd->rvd_mutex, NULL); rvd->rvd_vsched->oc_opaque = rvd; rvd->rvd_vrender->oc_opaque = rvd; gv->gv_vd->vd_render_component = rvd->rvd_vrender; omx_enable_buffer_marks(rvd->rvd_vrender); rvd->rvd_tun_clock_vsched = omx_tunnel_create(omx_get_clock(mp), 81, rvd->rvd_vsched, 12, "clock -> vsched"); rvd->rvd_vsched->oc_port_settings_changed_cb = vsched_port_settings_changed; rvd->rvd_vrender->oc_event_mark_cb = buffer_mark; } omx_set_state(rvd->rvd_vrender, OMX_StateIdle); if(rvd->rvd_tun_vdecoder_vsched != NULL) omx_tunnel_destroy(rvd->rvd_tun_vdecoder_vsched); if(rvd->rvd_mc != NULL) media_codec_deref(rvd->rvd_mc); rvd->rvd_mc = media_codec_ref(mc); rvd->rvd_tun_vdecoder_vsched = omx_tunnel_create(rvc->rvc_decoder, 131, rvd->rvd_vsched, 10, "vdecoder -> vsched"); omx_set_state(rvd->rvd_vsched, OMX_StateExecuting); return 0; }
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; }