/** @internal @This checks and parses a "#EXT-X-STREAM-INF" tag. * * @param upipe description structure of the pipe * @param flow_def the current flow definition * @param line the trailing characters of the line * @return an error code */ static int upipe_m3u_reader_ext_x_stream_inf(struct upipe *upipe, struct uref *flow_def, const char *line) { if (!ubase_check(uref_flow_match_def(flow_def, M3U_FLOW_DEF)) && !ubase_check(uref_flow_match_def(flow_def, MASTER_FLOW_DEF))) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_set_def(flow_def, MASTER_FLOW_DEF)); struct uref *item; UBASE_RETURN(upipe_m3u_reader_get_item(upipe, flow_def, &item)); const char *iterator = line; struct ustring name, value; while (ubase_check(attribute_iterate(&iterator, &name, &value)) && iterator != NULL) { char value_str[value.len + 1]; int err = ustring_cpy(value, value_str, sizeof (value_str)); if (unlikely(!ubase_check(err))) { upipe_err_va(upipe, "fail to copy ustring %.*s", (int)value.len, value.at); continue; } if (!ustring_cmp_str(name, "BANDWIDTH")) { char *endptr; uint64_t bandwidth = strtoull(value_str, &endptr, 10); if (endptr == value_str) return UBASE_ERR_INVALID; err = uref_m3u_master_set_bandwidth(item, bandwidth); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set bandwidth to %s", value_str); } else if (!ustring_cmp_str(name, "CODECS")) { err = uref_m3u_master_set_codecs(item, value_str); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set codecs to %s", value_str); } else if (!ustring_cmp_str(name, "AUDIO")) { err = uref_m3u_master_set_audio(item, value_str); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set audio to %s", value_str); } else if (!ustring_cmp_str(name, "RESOLUTION")) { err = uref_m3u_master_set_resolution(item, value_str); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set resolution to %s", value_str); } else { upipe_warn_va(upipe, "ignoring attribute %.*s (%.*s)", (int)name.len, name.at, (int)value.len, value.at); } } return UBASE_ERR_NONE; }
/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow flow definition packet * @return an error code */ static int upipe_filter_ebur128_set_flow_def(struct upipe *upipe, struct uref *flow) { struct upipe_filter_ebur128 *upipe_filter_ebur128 = upipe_filter_ebur128_from_upipe(upipe); if (flow == NULL) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_match_def(flow, "sound.s16.")) uint8_t channels, planes; uint64_t rate; if (unlikely(!ubase_check(uref_sound_flow_get_rate(flow, &rate)) || !ubase_check(uref_sound_flow_get_channels(flow, &channels)) || !ubase_check(uref_sound_flow_get_planes(flow, &planes)) || planes != 1)) { return UBASE_ERR_INVALID; } struct uref *flow_dup; if (unlikely((flow_dup = uref_dup(flow)) == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } if (unlikely(upipe_filter_ebur128->st)) { //ebur128_destroy(&upipe_filter_ebur128->st); ebur128_change_parameters(upipe_filter_ebur128->st, channels, rate); } else { upipe_filter_ebur128->st = ebur128_init(channels, rate, EBUR128_MODE_LRA | EBUR128_MODE_I | EBUR128_MODE_HISTOGRAM); } upipe_filter_ebur128_store_flow_def(upipe, flow_dup); return UBASE_ERR_NONE; }
/** @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 sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_fsink_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_match_def(flow_def, UPIPE_FSINK_EXPECTED_FLOW_DEF)) flow_def = uref_dup(flow_def); UBASE_ALLOC_RETURN(flow_def) upipe_input(upipe, flow_def, NULL); return UBASE_ERR_NONE; }
/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_dveo_asi_sink_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_match_def(flow_def, "block.mpegts.")) flow_def = uref_dup(flow_def); UBASE_ALLOC_RETURN(flow_def) upipe_input(upipe, flow_def, NULL); return UBASE_ERR_NONE; }
/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_block_to_sound_set_flow_def(struct upipe *upipe, struct uref *flow_def) { struct upipe_block_to_sound *upipe_block_to_sound = upipe_block_to_sound_from_upipe(upipe); if (flow_def == NULL) return UBASE_ERR_INVALID; if (unlikely(!ubase_check(uref_flow_match_def(flow_def, "block.")))) { uref_free(flow_def); return UBASE_ERR_INVALID; } flow_def = uref_dup(upipe_block_to_sound->flow_def_config); if (unlikely(flow_def == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } if(unlikely(!ubase_check(uref_flow_match_def(flow_def, "sound.s32.")))) { uref_free(flow_def); return UBASE_ERR_INVALID; } uint8_t channels, planes, sample_size; if(unlikely(!ubase_check(uref_sound_flow_get_channels(flow_def, &channels))) || unlikely(!ubase_check(uref_sound_flow_get_planes(flow_def, &planes))) || unlikely(!ubase_check(uref_sound_flow_get_sample_size(flow_def, &sample_size)))) { uref_free(flow_def); return UBASE_ERR_INVALID; } struct uref *flow_def_dup; if (unlikely((flow_def_dup = uref_dup(flow_def)) == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } upipe_block_to_sound_store_flow_def(upipe, flow_def_dup); upipe_block_to_sound_require_ubuf_mgr(upipe, flow_def); return UBASE_ERR_NONE; }
/** @internal @This sets the output flow format. * * @param upipe description structure of the pipe * @param flow_def new flow format to set * @return an error code */ static int upipe_dvbcsa_enc_set_flow_def(struct upipe *upipe, struct uref *flow_def) { struct upipe_dvbcsa_enc *upipe_dvbcsa_enc = upipe_dvbcsa_enc_from_upipe(upipe); UBASE_RETURN(uref_flow_match_def(flow_def, EXPECTED_FLOW_DEF)); struct uref *flow_def_dup = uref_dup(flow_def); UBASE_ALLOC_RETURN(flow_def_dup); upipe_dvbcsa_enc_store_flow_def(upipe, flow_def_dup); return UBASE_ERR_NONE; }
static int upipe_dump_set_flow_def(struct upipe *upipe, struct uref *flow_def) { int ret = uref_flow_match_def(flow_def, "block."); if (!ubase_check(ret)) return ret; struct uref *flow_def_dup = uref_dup(flow_def); if (unlikely(flow_def_dup == NULL)) return UBASE_ERR_ALLOC; upipe_dump_store_flow_def(upipe, flow_def_dup); return UBASE_ERR_NONE; }
/** @internal @This handles input buffer of the blank source pipe. This buffer * is supposed to be a picture or a sound to set as source buffer of the blank * pipes (audio/video blank pipe generator). * * @param upipe description structure of the pipe * @param uref uref reference picture or sound * @param upump_p is ignored */ static void upipe_blksrc_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_blksrc *upipe_blksrc = upipe_blksrc_from_upipe(upipe); if (unlikely(!upipe_blksrc->flow_def)) { upipe_warn(upipe, "flow def is not set"); uref_free(uref); } else if (ubase_check(uref_flow_match_def(upipe_blksrc->flow_def, UREF_PIC_FLOW_DEF))) { upipe_dbg(upipe, "set picture buffer"); upipe_vblk_set_pic(upipe_blksrc->blk, uref); } else if (ubase_check(uref_flow_match_def(upipe_blksrc->flow_def, UREF_SOUND_FLOW_DEF))) upipe_ablk_set_sound(upipe_blksrc->blk, uref); else { upipe_warn(upipe, "unsupported flow definition"); uref_free(uref); } }
/** @internal @This checks the validity of a sound flow def. * * @param upipe description structure of the pipe * @param flow_def flow definition to check * @return an error code */ static int upipe_ablk_check_flow_def(struct upipe *upipe, struct uref *flow_def) { uint8_t planes, sample_size, channels; uint64_t rate, samples; UBASE_RETURN(uref_flow_match_def(flow_def, UREF_SOUND_FLOW_DEF)); UBASE_RETURN(uref_sound_flow_get_planes(flow_def, &planes)); UBASE_RETURN(uref_sound_flow_get_channels(flow_def, &channels)); UBASE_RETURN(uref_sound_flow_get_rate(flow_def, &rate)); UBASE_RETURN(uref_sound_flow_get_sample_size(flow_def, &sample_size)); UBASE_RETURN(uref_sound_flow_get_samples(flow_def, &samples)); return UBASE_ERR_NONE; }
/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_burst_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (unlikely(!ubase_check(uref_flow_match_def(flow_def, "block.")))) return UBASE_ERR_INVALID; struct uref *flow_def_dup = uref_dup(flow_def); if (unlikely(flow_def_dup == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } upipe_burst_store_flow_def(upipe, flow_def_dup); return UBASE_ERR_NONE; }
/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_filter_blend_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_match_def(flow_def, "pic.")) struct uref *flow_def_dup; if (unlikely((flow_def_dup = uref_dup(flow_def)) == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } UBASE_RETURN(uref_pic_set_progressive(flow_def_dup)) upipe_input(upipe, flow_def_dup, NULL); return UBASE_ERR_NONE; }
/** @internal @This checks and parses a "#EXT-X-VERSION" tag. * * @param upipe description structure of the pipe * @param flow_def the current flow definition * @param line the trailing characters of the line * @return an error code */ static int upipe_m3u_reader_process_version(struct upipe *upipe, struct uref *flow_def, const char *line) { UBASE_RETURN(uref_flow_match_def(flow_def, M3U_FLOW_DEF)); char *endptr; unsigned long int version = strtoul(line, &endptr, 10); if (line == endptr || *endptr != '\0' || version > UINT8_MAX) { upipe_warn_va(upipe, "invalid version %s", line); return UBASE_ERR_INVALID; } upipe_dbg_va(upipe, "version: %u", version); return uref_m3u_flow_set_version(flow_def, version); }
/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_audiobar_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; uref_dump(flow_def, upipe->uprobe); UBASE_RETURN(uref_flow_match_def(flow_def, INPUT_FLOW_DEF)) uint8_t channels; UBASE_RETURN(uref_sound_flow_get_channels(flow_def, &channels)) struct uref *flow_def_dup; if (unlikely((flow_def_dup = uref_dup(flow_def)) == NULL)) return UBASE_ERR_ALLOC; upipe_input(upipe, flow_def_dup, NULL); return UBASE_ERR_NONE; }
static int upipe_rtp_h264_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_match_def(flow_def, "block.h264.")) struct uref *flow_def_dup = uref_dup(flow_def); if (unlikely(flow_def_dup == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } upipe_rtp_h264_store_flow_def(upipe, flow_def_dup); return UBASE_ERR_NONE; }
/** @internal @This sets the input flow def of the m3u pipe. * * @param upipe description structure of the pipe * @param flow_def new input flow definition * @return an error code */ static int upipe_m3u_reader_set_flow_def(struct upipe *upipe, struct uref *flow_def) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); UBASE_RETURN(uref_flow_match_def(flow_def, EXPECTED_FLOW_DEF)); struct uref *flow_def_dup = uref_dup(flow_def); if (unlikely(flow_def_dup == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } uref_free(upipe_m3u_reader->flow_def); upipe_m3u_reader->flow_def = flow_def_dup; return UBASE_ERR_NONE; }
/** @internal @This checks an URI. * * @param upipe description structure of the pipe * @param flow_def the current flow definition * @param uri the uri * @return an error code */ static int upipe_m3u_reader_process_uri(struct upipe *upipe, struct uref *flow_def, const char *uri) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); upipe_verbose_va(upipe, "uri %s", uri); UBASE_RETURN(uref_flow_match_def(flow_def, M3U_FLOW_DEF)); struct uref *item; UBASE_RETURN(upipe_m3u_reader_get_item(upipe, flow_def, &item)); UBASE_RETURN(uref_m3u_set_uri(item, uri)); if (upipe_m3u_reader->key) UBASE_RETURN(uref_m3u_playlist_key_copy(item, upipe_m3u_reader->key)); upipe_m3u_reader->item = NULL; ulist_add(&upipe_m3u_reader->items, uref_to_uchain(item)); return UBASE_ERR_NONE; }
/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_nacl_audio_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; struct upipe_nacl_audio *upipe_nacl_audio = upipe_nacl_audio_from_upipe(upipe); UBASE_RETURN(uref_flow_match_def(flow_def, EXPECTED_FLOW_DEF)) UBASE_RETURN(uref_sound_flow_match_rate(flow_def, SAMPLE_RATE, SAMPLE_RATE)) UBASE_RETURN(uref_sound_flow_match_channels(flow_def, 2, 2)) UBASE_RETURN(uref_sound_flow_match_planes(flow_def, 1, 1)) UBASE_RETURN(uref_sound_flow_check_channel(flow_def, "lr")) upipe_nacl_audio->latency = 0; uref_clock_get_latency(flow_def, &upipe_nacl_audio->latency); return UBASE_ERR_NONE; }
/** @internal @This outputs the m3u. * * @param upipe description structure of the pipe * @param upump_p reference to source pump to block */ static void upipe_m3u_reader_output_all(struct upipe *upipe, struct upump **upump_p) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); struct uref *flow_def = upipe_m3u_reader->current_flow_def; upipe_m3u_reader->current_flow_def = NULL; if (unlikely(!ubase_check(uref_flow_match_def(flow_def, M3U_FLOW_DEF)))) { upipe_err(upipe, "invalid m3u"); uref_free(flow_def); return; } /* force new flow def */ upipe_m3u_reader_store_flow_def(upipe, NULL); /* set output flow def */ upipe_m3u_reader_store_flow_def(upipe, flow_def); /* output */ struct uchain *uchain; bool first = true; upipe_use(upipe); while ((uchain = ulist_pop(&upipe_m3u_reader->items)) != NULL) { struct uref *uref = uref_from_uchain(uchain); if (first) uref_block_set_start(uref); first = false; if (ulist_empty(&upipe_m3u_reader->items)) uref_block_set_end(uref); upipe_m3u_reader_output(upipe, uref, upump_p); } upipe_release(upipe); }
static int upipe_m3u_reader_process_media(struct upipe *upipe, struct uref *flow_def, const char *line) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); if (!ubase_check(uref_flow_match_def(flow_def, M3U_FLOW_DEF)) && !ubase_check(uref_flow_match_def(flow_def, MASTER_FLOW_DEF))) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_set_def(flow_def, MASTER_FLOW_DEF)); struct uref *item = uref_sibling_alloc_control(flow_def); if (unlikely(item == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } struct ustring name, value; while (ubase_check(attribute_iterate(&line, &name, &value)) && line) { if (!ustring_cmp_str(name, "URI")) { value = ustring_unframe(value, '"'); char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_set_uri(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set uri %s", val); continue; } } else if (!ustring_cmp_str(name, "TYPE")) { char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_master_set_media_type(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set media type %s", val); continue; } } else if (!ustring_cmp_str(name, "DEFAULT")) { if (!ustring_cmp_str(value, "YES")) { int err = uref_m3u_master_set_media_default(item); if (unlikely(!ubase_check(err))) continue; } else if (ustring_cmp_str(value, "NO")) { upipe_warn_va(upipe, "invalid DEFAULT value %.*s", (int)value.len, value.at); continue; } } else if (!ustring_cmp_str(name, "AUTOSELECT")) { if (!ustring_cmp_str(value, "YES")) { int err = uref_m3u_master_set_media_autoselect(item); if (unlikely(!ubase_check(err))) continue; } else if (ustring_cmp_str(value, "NO")) { upipe_warn_va(upipe, "invalid AUTOSELECT value %.*s", (int)value.len, value.at); continue; } } else if (!ustring_cmp_str(name, "NAME")) { value = ustring_unframe(value, '"'); char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_master_set_media_name(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set media name %s", val); continue; } } else if (!ustring_cmp_str(name, "GROUP-ID")) { value = ustring_unframe(value, '"'); char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_master_set_media_group(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set group id %s", val); continue; } } else { upipe_warn_va(upipe, "ignoring attribute %.*s (%.*s)", (int)name.len, name.at, (int)value.len, value.at); } } ulist_add(&upipe_m3u_reader->items, uref_to_uchain(item)); return UBASE_ERR_NONE; }
/** @internal @This allocates a blank source pipe. * * @param mgr common management structure * @param uprobe structure used to raise events * @param signature signature of the pipe allocator * @param args optional arguments * @return pointer to upipe or NULL in case of allocation error */ static struct upipe *upipe_blksrc_alloc(struct upipe_mgr *mgr, struct uprobe *uprobe, uint32_t signature, va_list args) { struct uref *flow_def; struct upipe *upipe = upipe_blksrc_alloc_flow(mgr, uprobe, signature, args, &flow_def); if (unlikely(!upipe)) { return NULL; } struct upipe_blksrc *upipe_blksrc = upipe_blksrc_from_upipe(upipe); upipe_blksrc_init_urefcount(upipe); upipe_blksrc_init_urefcount_real(upipe); upipe_blksrc_init_src_probe(upipe); upipe_blksrc_init_blk_probe(upipe); upipe_blksrc_init_bin_input(upipe); upipe_blksrc_init_bin_output(upipe); upipe_blksrc->flow_def = flow_def; upipe_throw_ready(upipe); uint64_t duration = 0; if (ubase_check(uref_flow_match_def(flow_def, UREF_PIC_FLOW_DEF))) { struct urational fps; if (unlikely(!ubase_check(uref_pic_flow_get_fps(flow_def, &fps)))) { upipe_release(upipe); return NULL; } duration = (uint64_t)UCLOCK_FREQ * fps.den / fps.num; } else if (ubase_check(uref_flow_match_def(flow_def, UREF_SOUND_FLOW_DEF))) { uint64_t samples, rate; if (unlikely(!ubase_check(uref_sound_flow_get_samples(flow_def, &samples))) || unlikely(!ubase_check(uref_sound_flow_get_rate(flow_def, &rate)))) { upipe_release(upipe); return NULL; } duration = samples * UCLOCK_FREQ / rate; } else { upipe_warn(upipe, "unsupported flow def"); upipe_release(upipe); return NULL; } struct uref *src_flow_def = uref_void_flow_alloc_def(flow_def->mgr); if (unlikely(!src_flow_def)) { upipe_err(upipe, "fail to allocate source pipe flow def"); upipe_release(upipe); return NULL; } if (unlikely(!ubase_check(uref_clock_set_duration(src_flow_def, duration)))) { uref_free(src_flow_def); upipe_release(upipe); return NULL; } struct upipe_mgr *upipe_voidsrc_mgr = upipe_voidsrc_mgr_alloc(); if (unlikely(!upipe_voidsrc_mgr)) { upipe_err(upipe, "fail to get void source manager"); uref_free(src_flow_def); upipe_release(upipe); return NULL; } struct upipe *src = upipe_flow_alloc(upipe_voidsrc_mgr, uprobe_pfx_alloc( uprobe_use(&upipe_blksrc->src_probe), UPROBE_LOG_VERBOSE, "src"), src_flow_def); upipe_mgr_release(upipe_voidsrc_mgr); uref_free(src_flow_def); if (unlikely(!src)) { upipe_err(upipe, "fail to allocate source pipe"); upipe_release(upipe); return NULL; } upipe_blksrc_store_bin_input(upipe, src); struct upipe_mgr *upipe_blk_mgr = NULL; if (ubase_check(uref_flow_match_def(flow_def, UREF_PIC_FLOW_DEF))) { upipe_blk_mgr = upipe_vblk_mgr_alloc(); } else if (ubase_check(uref_flow_match_def(flow_def, UREF_SOUND_FLOW_DEF))) { upipe_blk_mgr = upipe_ablk_mgr_alloc(); } if (unlikely(!upipe_blk_mgr)) { upipe_err(upipe, "fail to get blank generator manager"); upipe_release(upipe); return NULL; } struct upipe *blk = upipe_flow_alloc(upipe_blk_mgr, uprobe_pfx_alloc( uprobe_use(&upipe_blksrc->blk_probe), UPROBE_LOG_VERBOSE, "blk"), flow_def); upipe_mgr_release(upipe_blk_mgr); if (unlikely(!blk)) { upipe_err(upipe, "fail to allocate blank generator pipe"); upipe_release(upipe); return NULL; } upipe_blksrc_store_bin_output(upipe, blk); if (unlikely(!ubase_check(upipe_set_output(src, blk)))) { upipe_release(upipe); return NULL; } return upipe; }
/** @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; }
static int upipe_m3u_reader_key(struct upipe *upipe, struct uref *flow_def, const char *line) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); if (unlikely(!ubase_check(uref_flow_match_def(flow_def, M3U_FLOW_DEF))) && unlikely(!ubase_check(uref_flow_match_def(flow_def, PLAYLIST_FLOW_DEF)))) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_set_def(flow_def, PLAYLIST_FLOW_DEF)); struct uref *key = uref_sibling_alloc_control(flow_def); if (unlikely(key == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } if (upipe_m3u_reader->key) uref_free(upipe_m3u_reader->key); upipe_m3u_reader->key = key; const char *iterator = line; struct ustring name, value; while (ubase_check(attribute_iterate(&iterator, &name, &value)) && iterator != NULL) { char value_str[value.len + 1]; int err = ustring_cpy(value, value_str, sizeof (value_str)); if (unlikely(!ubase_check(err))) { upipe_err_va(upipe, "fail to copy ustring %.*s", (int)value.len, value.at); continue; } if (!ustring_cmp_str(name, "METHOD")) { err = uref_m3u_playlist_key_set_method(key, value_str); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set key method to %s", value_str); } else if (!ustring_cmp_str(name, "URI")) { err = uref_m3u_playlist_key_set_uri(key, value_str); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set uri to %s", value_str); } else if (!ustring_cmp_str(name, "IV")) { size_t len = strlen(value_str); if (unlikely(len > 32)) { upipe_warn_va(upipe, "invalid initialization vector %s", value_str); continue; } for (unsigned i = 0; i < len; i += 2) { if (unlikely(!isxdigit(value_str[i])) || unlikely(!isxdigit(value_str[i + 1]))) { upipe_warn_va(upipe, "invalid initialization vector %s", value_str); continue; } //FIXME //iv[] = value_str[i] } } else { upipe_warn_va(upipe, "ignoring attribute %.*s (%.*s)", (int)name.len, name.at, (int)value.len, value.at); } } return UBASE_ERR_NONE; }