/** @internal @This checks a flow definition validity. * * @param upipe description structure of the pipe * @param flow_def flow definition to check * @return an error code */ static int upipe_vblk_check_flow_def(struct upipe *upipe, struct uref *flow_def) { uint64_t hsize, vsize; UBASE_RETURN(uref_flow_match_def(flow_def, UREF_PIC_FLOW_DEF)); UBASE_RETURN(uref_pic_flow_get_hsize(flow_def, &hsize)); UBASE_RETURN(uref_pic_flow_get_vsize(flow_def, &vsize)); return UBASE_ERR_NONE; }
/** @internal @This provides a ubuf_mgr request. * * @param upipe description structure of the pipe * @param flow_format amended flow format * @return an error code */ static int upipe_audiobar_check_ubuf_mgr(struct upipe *upipe, struct uref *flow_format) { struct upipe_audiobar *upipe_audiobar = upipe_audiobar_from_upipe(upipe); if (flow_format == NULL) return UBASE_ERR_NONE; upipe_audiobar_store_flow_def(upipe, flow_format); UBASE_RETURN(uref_pic_flow_get_hsize(flow_format, &upipe_audiobar->hsize)) UBASE_RETURN(uref_pic_flow_get_vsize(flow_format, &upipe_audiobar->vsize)) upipe_audiobar->chan_width = upipe_audiobar->hsize / upipe_audiobar->channels; upipe_audiobar->chan_width -= upipe_audiobar->chan_width % 2; if (unlikely(upipe_audiobar->chan_width < 16)) { upipe_warn_va(upipe, "channel width is too small to have a separation (%"PRIu64")", upipe_audiobar->chan_width); } upipe_audiobar->sep_width = upipe_audiobar->chan_width / 4; upipe_audiobar->sep_width -= upipe_audiobar->sep_width % 4; upipe_audiobar->pad_width = upipe_audiobar->hsize - upipe_audiobar->chan_width * upipe_audiobar->channels; upipe_notice_va(upipe, "setting up chan %"PRIu64" sep %"PRIu64" pad %"PRIu64, upipe_audiobar->chan_width, upipe_audiobar->sep_width, upipe_audiobar->pad_width); bool was_buffered = !upipe_audiobar_check_input(upipe); upipe_audiobar_output_input(upipe); upipe_audiobar_unblock_input(upipe); if (was_buffered && upipe_audiobar_check_input(upipe)) { /* All packets have been output, release again the pipe that has been * used in @ref upipe_audiobar_input. */ upipe_release(upipe); } return UBASE_ERR_NONE; }
/** 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 sets the input flow def. * * @param upipe description structure of the pipe * @param flow_def the flow format to set * @return an error code */ static int upipe_vblk_set_flow_def(struct upipe *upipe, struct uref *flow_def) { struct upipe_vblk *upipe_vblk = upipe_vblk_from_upipe(upipe); if (!ubase_check(uref_flow_match_def(flow_def, UREF_VOID_FLOW_DEF)) && !ubase_check(upipe_vblk_check_flow_def(upipe, flow_def))) return UBASE_ERR_INVALID; struct uref *input_flow_def = uref_dup(flow_def); if (unlikely(!input_flow_def)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } upipe_vblk_store_flow_def_input(upipe, input_flow_def); if (ubase_check(uref_flow_match_def(flow_def, UREF_VOID_FLOW_DEF))) return UBASE_ERR_NONE; uint64_t hsize = 0, vsize = 0; UBASE_RETURN(uref_pic_flow_get_hsize(flow_def, &hsize)); UBASE_RETURN(uref_pic_flow_get_vsize(flow_def, &vsize)); struct uref *flow_def_dup = uref_dup(flow_def); if (unlikely(!flow_def_dup)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } struct urational sar; uref_pic_flow_clear_format(flow_def_dup); uref_pic_flow_copy_format(flow_def_dup, flow_def); uref_pic_flow_set_hsize(flow_def_dup, hsize); uref_pic_flow_set_vsize(flow_def_dup, vsize); if (likely(ubase_check(uref_pic_flow_get_sar(flow_def, &sar)))) { uref_pic_flow_set_sar(flow_def_dup, sar); } else { uref_pic_flow_delete_sar(flow_def_dup); } bool overscan; if (likely(ubase_check(uref_pic_flow_get_overscan(flow_def, &overscan)))) { uref_pic_flow_set_overscan(flow_def_dup, overscan); } else { uref_pic_flow_delete_overscan(flow_def_dup); } if (likely(ubase_check(uref_pic_get_progressive(flow_def)))) { uref_pic_set_progressive(flow_def_dup); } else { uref_pic_delete_progressive(flow_def_dup); } upipe_vblk_store_flow_def(upipe, flow_def_dup); if (upipe_vblk->ubuf) { ubuf_free(upipe_vblk->ubuf); upipe_vblk->ubuf = NULL; } if (upipe_vblk->ubuf_mgr && !ubase_check(ubuf_mgr_check(upipe_vblk->ubuf_mgr, flow_def_dup))) { ubuf_mgr_release(upipe_vblk->ubuf_mgr); upipe_vblk->ubuf_mgr = NULL; } return UBASE_ERR_NONE; }
/** @internal @This handles the input uref. * * @param upipe description structure of the pipe * @param uref input uref * @param upump_p reference to pump that generated the buffer */ static void upipe_vblk_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_vblk *upipe_vblk = upipe_vblk_from_upipe(upipe); struct uref *flow_def = upipe_vblk->flow_def; struct uref *input_flow_def = upipe_vblk->input_flow_def; if (uref->ubuf) { upipe_vblk_output(upipe, uref, upump_p); return; } if (unlikely(!input_flow_def)) { upipe_warn(upipe, "no input flow definition"); uref_free(uref); return; } if (unlikely(!flow_def)) { upipe_warn(upipe, "no output flow definition"); uref_free(uref); return; } if (unlikely(!upipe_vblk->ubuf_mgr)) { upipe_warn(upipe, "no ubuf manager set"); uref_free(uref); return; } if (unlikely(!upipe_vblk->ubuf)) { upipe_verbose(upipe, "allocate blank picture"); uint64_t hsize, vsize; ubase_assert(uref_pic_flow_get_hsize(upipe_vblk->flow_def, &hsize)); ubase_assert(uref_pic_flow_get_vsize(upipe_vblk->flow_def, &vsize)); upipe_vblk->ubuf = ubuf_pic_alloc(upipe_vblk->ubuf_mgr, hsize, vsize); if (unlikely(!upipe_vblk->ubuf)) { upipe_err(upipe, "fail to allocate picture"); uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } ubuf_pic_clear(upipe_vblk->ubuf, 0, 0, -1, -1, 1); } struct ubuf *ubuf = ubuf_dup(upipe_vblk->ubuf); if (unlikely(!ubuf)) { upipe_err(upipe, "fail to duplicate blank picture"); uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } uref_attach_ubuf(uref, ubuf); if (ubase_check(uref_pic_get_progressive(flow_def))) uref_pic_set_progressive(uref); upipe_vblk_output(upipe, uref, upump_p); }