/** @internal @This catches events of the dec queue source. * * @param uprobe pointer to probe * @param upipe pointer to pipe throwing the event * @param event event thrown * @param args optional event-specific parameters * @return an error code */ static int upipe_glxplayer_catch_dec_qsrc(struct uprobe *uprobe, struct upipe *upipe, int event, va_list args) { switch (event) { case UPROBE_SOURCE_END: { struct upipe_glxplayer *glxplayer = container_of(uprobe, struct upipe_glxplayer, uprobe_dec_qsrc_s); upipe_flush(glxplayer->upipe_glx_qsink); upipe_release(glxplayer->upipe_glx_qsink); return UBASE_ERR_NONE; } case UPROBE_NEED_OUTPUT: { struct upipe_glxplayer *glxplayer = container_of(uprobe, struct upipe_glxplayer, uprobe_dec_qsrc_s); struct upipe *avcdec = upipe_void_alloc_output(upipe, glxplayer->upipe_avcdec_mgr, uprobe_pfx_alloc_va( uprobe_use(&glxplayer->uprobe_avcdec_s), glxplayer->loglevel, "avcdec")); if (unlikely(avcdec == NULL)) return UBASE_ERR_ALLOC; upipe_set_option(avcdec, "threads", "2"); upipe_release(avcdec); return UBASE_ERR_NONE; } default: return uprobe_throw_next(uprobe, upipe, event, args); } }
/** @internal @This catches events of the avcdec. * * @param uprobe pointer to probe * @param upipe pointer to pipe throwing the event * @param event event thrown * @param args optional event-specific parameters * @return an error code */ static int upipe_glxplayer_catch_avcdec(struct uprobe *uprobe, struct upipe *upipe, int event, va_list args) { switch (event) { case UPROBE_NEED_OUTPUT: { struct upipe_glxplayer *glxplayer = container_of(uprobe, struct upipe_glxplayer, uprobe_avcdec_s); struct uref *flow_def = va_arg(args, struct uref *); struct upipe *deint = upipe_void_alloc_output(upipe, glxplayer->upipe_filter_blend_mgr, uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger), glxplayer->loglevel, "deint")); if (unlikely(deint == NULL)) return UBASE_ERR_ALLOC; struct uref *output_flow = uref_dup(flow_def); if (unlikely(output_flow == NULL)) return UBASE_ERR_ALLOC; uref_pic_flow_clear_format(output_flow); if (unlikely(!ubase_check(uref_pic_flow_set_macropixel(output_flow, 1)) || !ubase_check(uref_pic_flow_set_planes(output_flow, 0)) || !ubase_check(uref_pic_flow_add_plane(output_flow, 1, 1, 3, "r8g8b8")))) { uref_free(output_flow); return UBASE_ERR_ALLOC; } struct upipe *yuvrgb = upipe_flow_alloc_output(deint, glxplayer->upipe_sws_mgr, uprobe_pfx_alloc_va(uprobe_use(glxplayer->uprobe_logger), glxplayer->loglevel, "rgb"), output_flow); assert(yuvrgb != NULL); uref_free(output_flow); upipe_release(deint); glxplayer->upipe_glx_qsink = upipe_qsink_alloc(glxplayer->upipe_qsink_mgr, uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger), glxplayer->loglevel, "glx qsink"), glxplayer->upipe_glx_qsrc); if (unlikely(glxplayer->upipe_glx_qsink == NULL)) return UBASE_ERR_ALLOC; upipe_set_output(yuvrgb, glxplayer->upipe_glx_qsink); upipe_release(yuvrgb); return UBASE_ERR_NONE; } default: return uprobe_throw_next(uprobe, upipe, event, args); } }
/** split callback */ static int split_catch(struct uprobe *uprobe, struct upipe *upipe, int event, va_list args) { if (event != UPROBE_NEED_OUTPUT) return uprobe_throw_next(uprobe, upipe, event, args); upipe_release(upipe_split_output); upipe_split_output = upipe_use(upipe); struct upipe *avcdec = upipe_void_alloc_output(upipe, upipe_avcdec_mgr, uprobe_pfx_alloc_va(uprobe_use(&uprobe_avcdec), loglevel, "avcdec")); if (avcdec == NULL) { upipe_err_va(upipe, "incompatible flow def"); upipe_release(upipe_source); return UBASE_ERR_UNHANDLED; } upipe_release(avcdec); return UBASE_ERR_NONE; }
int main(int argc, char **argv) { struct uprobe *uprobe2 = uprobe_stdio_alloc(NULL, stdout, UPROBE_LOG_DEBUG); assert(uprobe2 != NULL); struct uprobe *uprobe1 = uprobe_pfx_alloc(uprobe2, UPROBE_LOG_DEBUG, "pfx"); assert(uprobe1 != NULL); uprobe_err(uprobe1, NULL, "This is an error"); uprobe_warn_va(uprobe1, NULL, "This is a %s warning with %d", "composite", 0x42); uprobe_notice(uprobe1, NULL, "This is a notice"); uprobe_dbg(uprobe1, NULL, "This is a debug"); uprobe_pfx_free(uprobe1); uprobe1 = uprobe_pfx_alloc_va(uprobe2, UPROBE_LOG_ERROR, "pfx[%d]", 2); assert(uprobe1 != NULL); uprobe_err_va(uprobe1, NULL, "This is another error with %d", 0x43); uprobe_warn(uprobe1, NULL, "This is a warning that you shouldn't see"); uprobe_pfx_free(uprobe1); uprobe_stdio_free(uprobe2); return 0; }
/** avcdec callback */ static int avcdec_catch(struct uprobe *uprobe, struct upipe *upipe, int event, va_list args) { if (event != UPROBE_NEED_OUTPUT) return uprobe_throw_next(uprobe, upipe, event, args); struct uref *flow_def = va_arg(args, struct uref *); uint64_t hsize, vsize, wanted_hsize; struct urational sar; bool progressive; if (unlikely(!ubase_check(uref_pic_flow_get_hsize(flow_def, &hsize)) || !ubase_check(uref_pic_flow_get_vsize(flow_def, &vsize)) || !ubase_check(uref_pic_flow_get_sar(flow_def, &sar)))) { upipe_err_va(upipe, "incompatible flow def"); upipe_release(upipe_source); return UBASE_ERR_UNHANDLED; } wanted_hsize = (hsize * sar.num / sar.den / 2) * 2; progressive = ubase_check(uref_pic_get_progressive(flow_def)); struct uref *flow_def2 = uref_dup(flow_def); upipe_use(upipe); if (!progressive) { uref_pic_set_progressive(flow_def2); struct upipe *deint = upipe_void_alloc_output(upipe, upipe_filter_blend_mgr, uprobe_pfx_alloc(uprobe_use(logger), loglevel, "deint")); assert(deint != NULL); upipe_release(upipe); upipe = deint; } if (wanted_hsize != hsize) { uref_pic_flow_set_hsize(flow_def2, wanted_hsize); struct upipe *sws = upipe_flow_alloc_output(upipe, upipe_sws_mgr, uprobe_pfx_alloc_va(uprobe_use(logger), loglevel, "sws"), flow_def2); assert(sws != NULL); upipe_release(upipe); upipe = sws; } uref_pic_flow_clear_format(flow_def2); uref_flow_set_def(flow_def2, "block.mjpeg.pic."); struct upipe *jpegenc = upipe_flow_alloc_output(upipe, upipe_avcenc_mgr, uprobe_pfx_alloc_va(uprobe_use(logger), loglevel, "jpeg"), flow_def2); assert(jpegenc != NULL); upipe_release(upipe); upipe_set_option(jpegenc, "qmax", "2"); upipe = jpegenc; struct upipe *urefprobe = upipe_void_alloc_output(upipe, upipe_probe_uref_mgr, uprobe_pfx_alloc_va(uprobe_use(&uprobe_uref), loglevel, "urefprobe")); assert(urefprobe != NULL); upipe_release(upipe); upipe = urefprobe; struct upipe *fsink = upipe_void_alloc_output(upipe, upipe_fsink_mgr, uprobe_pfx_alloc_va(uprobe_use(logger), ((loglevel > UPROBE_LOG_DEBUG) ? UPROBE_LOG_WARNING : loglevel), "jpegsink")); assert(fsink != NULL); upipe_release(upipe); upipe_fsink_set_path(fsink, dstpath, UPIPE_FSINK_OVERWRITE); upipe = fsink; uref_free(flow_def2); upipe_release(upipe); return UBASE_ERR_NONE; }
/** @internal @This catches events of the video output of the demux. * * @param uprobe pointer to probe * @param upipe pointer to pipe throwing the event * @param event event thrown * @param args optional event-specific parameters * @return an error code */ static int upipe_glxplayer_catch_demux_output(struct uprobe *uprobe, struct upipe *upipe, int event, va_list args) { struct upipe_glxplayer *glxplayer = container_of(uprobe, struct upipe_glxplayer, uprobe_demux_output_s); switch (event) { case UPROBE_NEED_OUTPUT: { struct uref *flow_def = va_arg(args, struct uref *); const char *def = "(none)"; if (!ubase_check(uref_flow_get_def(flow_def, &def)) || ubase_ncmp(def, "block.")) { upipe_warn_va(upipe, "flow def %s is not supported", def); return UBASE_ERR_UNHANDLED; } upipe_dbg_va(upipe, "add flow %s", def); /* prepare a queue to deport avcodec to a new thread */ uprobe_throw(glxplayer->uprobe_logger, NULL, UPROBE_FREEZE_UPUMP_MGR); struct upipe *upipe_dec_qsrc = upipe_qsrc_alloc(glxplayer->upipe_qsrc_mgr, uprobe_pfx_alloc_va(uprobe_use(&glxplayer->uprobe_dec_qsrc_s), glxplayer->loglevel, "dec qsrc"), DEC_QUEUE_LENGTH); if (unlikely(upipe_dec_qsrc == NULL)) { return UBASE_ERR_ALLOC; } uprobe_throw(glxplayer->uprobe_logger, NULL, UPROBE_THAW_UPUMP_MGR); glxplayer->upipe_dec_qsink = upipe_qsink_alloc(glxplayer->upipe_qsink_mgr, uprobe_pfx_alloc_va( uprobe_use(glxplayer->uprobe_logger), glxplayer->loglevel, "dec qsink"), upipe_dec_qsrc); if (unlikely(glxplayer->upipe_dec_qsink == NULL)) { upipe_release(upipe_dec_qsrc); return UBASE_ERR_ALLOC; } upipe_set_output(upipe, glxplayer->upipe_dec_qsink); /* prepare to transfer the queue source */ glxplayer->dec_xfer = upipe_xfer_mgr_alloc(XFER_QUEUE, XFER_POOL); if (unlikely(glxplayer->dec_xfer == NULL)) { upipe_release(upipe_dec_qsrc); return UBASE_ERR_ALLOC; } /* spawn a thread for the decoder */ if (pthread_create(&glxplayer->dec_thread_id, NULL, upipe_glxplayer_dec_thread, glxplayer)) { upipe_mgr_release(glxplayer->dec_xfer); upipe_release(upipe_dec_qsrc); return UBASE_ERR_ALLOC; } glxplayer->upipe_dec_qsrc_handle = upipe_xfer_alloc(glxplayer->dec_xfer, uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger), glxplayer->loglevel, "dec qsrc xfer"), upipe_dec_qsrc); if (unlikely(glxplayer->upipe_dec_qsrc_handle == NULL)) { upipe_mgr_release(glxplayer->dec_xfer); upipe_release(upipe_dec_qsrc); return UBASE_ERR_ALLOC; } upipe_attach_upump_mgr(glxplayer->upipe_dec_qsrc_handle); upipe_set_output(glxplayer->upipe_dec_qsink, glxplayer->upipe_dec_qsrc_handle); return UBASE_ERR_NONE; } case UPROBE_SOURCE_END: { upipe_flush(glxplayer->upipe_dec_qsink); upipe_release(glxplayer->upipe_dec_qsink); glxplayer->upipe_dec_qsink = NULL; /* set dec_qsrc output to null */ struct upipe *null = upipe_void_alloc(glxplayer->upipe_null_mgr, uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger), glxplayer->loglevel, "dec qsrc null")); if (likely(null != NULL)) { upipe_set_output(glxplayer->upipe_dec_qsrc_handle, null); upipe_release(null); } upipe_release(glxplayer->upipe_dec_qsrc_handle); return UBASE_ERR_NONE; } default: return uprobe_throw_next(uprobe, upipe, event, args); } }