/** @internal @This handles input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_osx_audioqueue_sink_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_osx_audioqueue_sink *osx_audioqueue = upipe_osx_audioqueue_sink_from_upipe(upipe); /* empty uref */ if (unlikely(!uref->ubuf)) { uref_free(uref); return; } /* check queue */ if (unlikely(!osx_audioqueue->queue)) { upipe_warn(upipe, "audioqueue not configured"); uref_free(uref); return; } upipe_osx_audioqueue_sink_input_audio(upipe, uref, upump_p); }
/** @internal @This flushes all input buffers. * * @param upipe description structure of the pipe * @param lost true if the sync was lost */ static void upipe_ts_pesd_flush(struct upipe *upipe, bool lost) { struct upipe_ts_pesd *upipe_ts_pesd = upipe_ts_pesd_from_upipe(upipe); if (upipe_ts_pesd->next_uref != NULL) { uref_free(upipe_ts_pesd->next_uref); upipe_ts_pesd->next_uref = NULL; upipe_ts_pesd->next_uref_size = 0; } if (lost) upipe_ts_pesd_sync_lost(upipe); upipe_ts_pesd->drop = true; }
/** @internal @This tries to find TS packets in the buffered input urefs. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static void upipe_ts_check_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_ts_check *upipe_ts_check = upipe_ts_check_from_upipe(upipe); size_t size; if (unlikely(!ubase_check(uref_block_size(uref, &size)))) { uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } bool first = true; while (size > upipe_ts_check->output_size) { struct uref *output = uref_block_splice(uref, 0, upipe_ts_check->output_size); if (unlikely(output == NULL)) { uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } if (!first) uref_flow_delete_discontinuity(output); first = false; if (!upipe_ts_check_check(upipe, output, upump_p)) { uref_free(uref); return; } uref_block_resize(uref, upipe_ts_check->output_size, -1); size -= upipe_ts_check->output_size; } if (!first) uref_flow_delete_discontinuity(uref); if (size == upipe_ts_check->output_size) upipe_ts_check_check(upipe, uref, upump_p); }
/** @internal @This handles input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_filter_ebur128_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_filter_ebur128 *upipe_filter_ebur128 = upipe_filter_ebur128_from_upipe(upipe); double loud = 0, lra = 0, global = 0; size_t samples; if (unlikely(!ubase_check(uref_sound_size(uref, &samples, NULL)))) { upipe_warn(upipe, "invalid sound buffer"); uref_free(uref); return; } const char *channel = NULL; const int16_t *buf = NULL; if (ubase_check(uref_sound_plane_iterate(uref, &channel)) && channel) { if (unlikely(!ubase_check(uref_sound_plane_read_int16_t(uref, channel, 0, -1, &buf)))) { upipe_warn(upipe, "error mapping sound buffer"); uref_free(uref); return; } if (unlikely((uintptr_t)buf & 1)) { upipe_warn(upipe, "unaligned buffer"); } ebur128_add_frames_short(upipe_filter_ebur128->st, buf, samples); uref_sound_plane_unmap(uref, channel, 0, -1); } ebur128_loudness_momentary(upipe_filter_ebur128->st, &loud); ebur128_loudness_range(upipe_filter_ebur128->st, &lra); ebur128_loudness_global(upipe_filter_ebur128->st, &global); uref_ebur128_set_momentary(uref, loud); uref_ebur128_set_lra(uref, lra); uref_ebur128_set_global(uref, global); upipe_verbose_va(upipe, "loud %f lra %f global %f", loud, lra, global); upipe_filter_ebur128_output(upipe, uref, upump_p); }
/** @This frees a upipe. * * @param urefcount_real pointer to urefcount_real structure */ static void upipe_fdec_free(struct urefcount *urefcount_real) { struct upipe_fdec *upipe_fdec = upipe_fdec_from_urefcount_real(urefcount_real); struct upipe *upipe = upipe_fdec_to_upipe(upipe_fdec); upipe_throw_dead(upipe); uref_free(upipe_fdec->options); upipe_fdec_clean_last_inner_probe(upipe); upipe_fdec_clean_uref_mgr(upipe); urefcount_clean(urefcount_real); upipe_fdec_clean_urefcount(upipe); upipe_fdec_free_void(upipe); }
/** @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_rtpd_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, EXPECTED_FLOW_DEF)) struct uref *flow_def_dup; if (unlikely((flow_def_dup = uref_dup(flow_def)) == NULL)) return UBASE_ERR_ALLOC; struct upipe_rtpd *upipe_rtpd = upipe_rtpd_from_upipe(upipe); uref_free(upipe_rtpd->flow_def_input); upipe_rtpd->flow_def_input = flow_def_dup; return UBASE_ERR_NONE; }
/** @This frees a upipe. * * @param upipe description structure of the pipe */ static void upipe_ts_pesd_free(struct upipe *upipe) { struct upipe_ts_pesd *upipe_ts_pesd = upipe_ts_pesd_from_upipe(upipe); upipe_throw_dead(upipe); upipe_ts_pesd_clean_output(upipe); upipe_ts_pesd_clean_sync(upipe); if (upipe_ts_pesd->next_uref != NULL) uref_free(upipe_ts_pesd->next_uref); upipe_ts_pesd_clean_urefcount(upipe); upipe_ts_pesd_free_void(upipe); }
/** @internal @This handles input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump pump that generated the buffer */ static void upipe_skip_input(struct upipe *upipe, struct uref *uref, struct upump *upump) { struct upipe_skip *upipe_skip = upipe_skip_from_upipe(upipe); const char *def; if (unlikely(uref_flow_get_def(uref, &def))) { if (unlikely(ubase_ncmp(def, EXPECTED_FLOW))) { upipe_throw_flow_def_error(upipe, uref); uref_free(uref); return; } upipe_dbg_va(upipe, "flow definition %s", def); if (unlikely(!uref_flow_set_def(uref, "block."))) upipe_throw_aerror(upipe); upipe_skip_store_flow_def(upipe, uref); return; } if (unlikely(uref_flow_get_end(uref))) { uref_free(uref); upipe_throw_need_input(upipe); return; } if (unlikely(upipe_skip->flow_def == NULL)) { upipe_throw_flow_def_error(upipe, uref); uref_free(uref); return; } if (unlikely(uref->ubuf == NULL)) { uref_free(uref); return; } upipe_skip_input_block(upipe, uref, upump); }
/** @internal @This takes the payload of a TS packet, checks if it may * contain part of a PES header, and outputs it. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static void upipe_ts_pesd_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_ts_pesd *upipe_ts_pesd = upipe_ts_pesd_from_upipe(upipe); size_t uref_size; if (unlikely(!ubase_check(uref_block_size(uref, &uref_size)))) { upipe_warn(upipe, "invalid PES chunk"); uref_free(uref); return; } if (ubase_check(uref_block_get_start(uref))) { if (unlikely(upipe_ts_pesd->next_uref != NULL)) { upipe_warn(upipe, "truncated PES header"); uref_free(upipe_ts_pesd->next_uref); } upipe_ts_pesd->next_uref = uref; upipe_ts_pesd->next_uref_size = uref_size; upipe_ts_pesd_decaps(upipe, upump_p); } else if (upipe_ts_pesd->next_uref != NULL) { struct ubuf *ubuf = uref_detach_ubuf(uref); uref_free(uref); if (unlikely(!ubase_check(uref_block_append(upipe_ts_pesd->next_uref, ubuf)))) { ubuf_free(ubuf); upipe_ts_pesd_flush(upipe); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return; } upipe_ts_pesd->next_uref_size += uref_size; upipe_ts_pesd_decaps(upipe, upump_p); } else if (likely(upipe_ts_pesd->acquired)) { upipe_ts_pesd->next_uref = uref; upipe_ts_pesd->next_uref_size += uref_size; upipe_ts_pesd_check_output(upipe, upump_p); } else uref_free(uref); }
/** @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); } }
/** @This frees a upipe. * * @param upipe description structure of the pipe */ static void upipe_audiobar_free(struct upipe *upipe) { upipe_throw_dead(upipe); struct upipe_audiobar *upipe_audiobar = upipe_audiobar_from_upipe(upipe); uref_free(upipe_audiobar->flow_def_config); upipe_audiobar_clean_flow_format(upipe); upipe_audiobar_clean_ubuf_mgr(upipe); upipe_audiobar_clean_output(upipe); upipe_audiobar_clean_input(upipe); upipe_audiobar_clean_urefcount(upipe); upipe_audiobar_free_flow(upipe); }
/** @This frees a upipe. * * @param upipe description structure of the pipe */ static void upipe_telxf_free(struct upipe *upipe) { struct upipe_telxf *upipe_telxf = upipe_telxf_from_upipe(upipe); upipe_throw_dead(upipe); uref_free(upipe_telxf->next_uref); upipe_telxf_clean_output(upipe); upipe_telxf_clean_flow_def(upipe); upipe_telxf_clean_sync(upipe); upipe_telxf_clean_urefcount(upipe); upipe_telxf_free_void(upipe); }
/** @internal @This allocates a block_to_sound 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_block_to_sound_alloc(struct upipe_mgr *mgr, struct uprobe *uprobe, uint32_t signature, va_list args) { struct uref *flow_def; struct upipe *upipe = upipe_block_to_sound_alloc_flow(mgr, uprobe, signature, args, &flow_def); if (unlikely(upipe == NULL)) return NULL; struct upipe_block_to_sound *upipe_block_to_sound = upipe_block_to_sound_from_upipe(upipe); if (unlikely(!ubase_check(uref_sound_flow_get_planes(flow_def, &upipe_block_to_sound->planes)) || upipe_block_to_sound->planes != 1 )) { upipe_err_va(upipe, "wrong number of planes: %d", upipe_block_to_sound->planes); upipe_block_to_sound_free_flow(upipe); uref_free(flow_def); return NULL; } if (unlikely(!ubase_check(uref_sound_flow_get_sample_size(flow_def, &upipe_block_to_sound->sample_size)))) { upipe_err_va(upipe, "flow def needs sample_size"); upipe_block_to_sound_free_flow(upipe); uref_free(flow_def); return NULL; } upipe_block_to_sound->flow_def_config = flow_def; upipe_block_to_sound_init_urefcount(upipe); upipe_block_to_sound_init_output(upipe); upipe_block_to_sound_init_ubuf_mgr(upipe); upipe_throw_ready(upipe); return upipe; }
/** @internal @This inputs data. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_nacl_audio_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_nacl_audio *upipe_nacl_audio = upipe_nacl_audio_from_upipe(upipe); size_t uref_size; if (unlikely(!ubase_check(uref_sound_size(uref, &uref_size, NULL)))) { upipe_warn(upipe, "unable to read uref"); uref_free(uref); return; } if (unlikely(!upipe_nacl_audio->started && !upipe_nacl_audio_open(upipe))) { upipe_warn(upipe, "unable to open device"); uref_free(uref); return; } uint64_t uref_pts; if (likely(ubase_check(uref_clock_get_pts_sys(uref, &uref_pts)))) { uref_pts += upipe_nacl_audio->latency; uref_clock_set_pts_sys(uref, uref_pts); } if (!upipe_nacl_audio_check_input(upipe)) { upipe_nacl_audio_hold_input(upipe, uref); upipe_nacl_audio_block_input(upipe, upump_p); } else if (!upipe_nacl_audio_handle(upipe, uref, upump_p)) { if (!upipe_nacl_audio_check_watcher(upipe)) { upipe_warn(upipe, "unable to spool uref"); uref_free(uref); return; } upipe_nacl_audio_hold_input(upipe, uref); upipe_nacl_audio_block_input(upipe, upump_p); upump_start(upipe_nacl_audio->upump); } }
/** @internal @This checks the presence of the sync word. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static bool upipe_ts_check_check(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { const uint8_t *buffer; int size = 1; uint8_t word; if (unlikely(!ubase_check(uref_block_read(uref, 0, &size, &buffer)))) { uref_free(uref); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } assert(size == 1); word = *buffer; uref_block_unmap(uref, 0); if (word != TS_SYNC) { uref_free(uref); upipe_warn_va(upipe, "invalid TS sync 0x%"PRIx8, word); return false; } upipe_ts_check_output(upipe, uref, upump_p); return true; }
/** @internal @This takes the payload of a TS packet and finds PSI sections * inside it. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static void upipe_ts_psim_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_ts_psim *upipe_ts_psim = upipe_ts_psim_from_upipe(upipe); if (unlikely(ubase_check(uref_flow_get_discontinuity(uref)))) upipe_ts_psim_flush(upipe); if (ubase_check(uref_block_get_start(uref))) { if (likely(upipe_ts_psim->acquired)) { /* just remove pointer_field */ if (unlikely(!ubase_check(uref_block_resize(uref, 1, -1)))) { uref_free(uref); upipe_ts_psim_flush(upipe); return; } } else { /* jump to the start of the next section */ uint8_t pointer_field; if (unlikely(!ubase_check(uref_block_extract(uref, 0, 1, &pointer_field)) || !ubase_check(uref_block_resize(uref, 1 + pointer_field, -1)))) { uref_free(uref); return; } upipe_ts_psim_sync_acquired(upipe); } uref_block_delete_start(uref); } else if (unlikely(upipe_ts_psim->next_uref == NULL)) { uref_free(uref); upipe_ts_psim_flush(upipe); return; } while (upipe_ts_psim_merge(upipe, uref, upump_p)); uref_free(uref); }
/** @This frees a upipe. * * @param upipe description structure of the pipe */ static void upipe_blksrc_free(struct upipe *upipe) { struct upipe_blksrc *upipe_blksrc = upipe_blksrc_from_upipe(upipe); upipe_throw_dead(upipe); uref_free(upipe_blksrc->flow_def); upipe_blksrc_clean_bin_output(upipe); upipe_blksrc_clean_bin_input(upipe); upipe_blksrc_clean_blk_probe(upipe); upipe_blksrc_clean_src_probe(upipe); upipe_blksrc_clean_urefcount_real(upipe); upipe_blksrc_clean_urefcount(upipe); upipe_blksrc_free_flow(upipe); }
/** @This sets the dictionary to set into urefs. * * @param upipe description structure of the pipe * @param dict dictionary to set * @return an error code */ static int _upipe_setflowdef_set_dict(struct upipe *upipe, struct uref *dict) { struct upipe_setflowdef *upipe_setflowdef = upipe_setflowdef_from_upipe(upipe); if (upipe_setflowdef->dict != NULL) uref_free(upipe_setflowdef->dict); if (dict != NULL) { upipe_setflowdef->dict = uref_dup(dict); if (upipe_setflowdef->dict == NULL) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } } else upipe_setflowdef->dict = NULL; upipe_setflowdef_build_flow_def(upipe); 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_setflowdef_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; struct uref *flow_def_dup; if ((flow_def_dup = uref_dup(flow_def)) == NULL) return UBASE_ERR_ALLOC; struct upipe_setflowdef *upipe_setflowdef = upipe_setflowdef_from_upipe(upipe); uref_free(upipe_setflowdef->flow_def_input); upipe_setflowdef->flow_def_input = flow_def_dup; upipe_setflowdef_build_flow_def(upipe); 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 frees the pipe. * * @param upipe description structure of the pipe */ static void upipe_hls_free(struct upipe *upipe) { struct upipe_hls *upipe_hls = upipe_hls_from_upipe(upipe); upipe_throw_dead(upipe); if (upipe_hls->sub_pipe_mgr) upipe_mgr_release(upipe_hls->sub_pipe_mgr); if (upipe_hls->item) uref_free(upipe_hls->item); upipe_hls_store_flow_def(upipe, NULL); upipe_hls_clean_bin_output(upipe); upipe_hls_clean_bin_input(upipe); upipe_hls_clean_probe_master(upipe); upipe_hls_clean_probe_reader(upipe); upipe_hls_clean_probe_null(upipe); upipe_hls_clean_urefcount(upipe); upipe_hls_clean_urefcount_real(upipe); upipe_hls_free_void(upipe); }
/** helper phony pipe */ static void test_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct x264_test *x264_test = x264_test_from_upipe(upipe); uint64_t pts = 0, dts = 0; if (uref->udict != NULL) { udict_dump(uref->udict, upipe->uprobe); } if (!ubase_check(uref_clock_get_pts_prog(uref, &pts))) { upipe_warn(upipe, "received packet with no pts"); } if (!ubase_check(uref_clock_get_dts_prog(uref, &dts))) { upipe_warn(upipe, "received packet with no dts"); } upipe_dbg_va(upipe, "received pic %d, pts: %"PRIu64" , dts: %"PRIu64, x264_test->counter, pts, dts); x264_test->counter++; uref_free(uref); }
/** @internal @This frees a burst pipe. * * @param urefcount pointer to real urefcount structure */ static void upipe_burst_free(struct urefcount *urefcount) { struct upipe_burst *upipe_burst = upipe_burst_from_urefcount_real(urefcount); struct upipe *upipe = upipe_burst_to_upipe(upipe_burst); upipe_throw_dead(upipe); struct uchain *uchain; while ((uchain = ulist_pop(&upipe_burst->urefs))) uref_free(uref_from_uchain(uchain)); urefcount_clean(&upipe_burst->urefcount_real); ueventfd_clean(&upipe_burst->ueventfd); upipe_burst_clean_upump(upipe); upipe_burst_clean_upump_mgr(upipe); upipe_burst_clean_output(upipe); upipe_burst_clean_urefcount(upipe); upipe_burst_free_void(upipe); }
/** @internal @This is called to consume frames out of the first buffered uref. * * @param upipe description structure of the pipe * @param frames number of frames to consume */ static void upipe_nacl_audio_consume(struct upipe *upipe, uint32_t frames) { struct upipe_nacl_audio *upipe_nacl_audio = upipe_nacl_audio_from_upipe(upipe); struct uref *uref = upipe_nacl_audio->uref; assert(uref != NULL); size_t uref_size; if (ubase_check(uref_sound_size(uref, &uref_size, NULL)) && uref_size <= frames) { upipe_nacl_audio->uref = NULL; uref_free(uref); } else { uref_sound_resize(uref, frames, -1); uint64_t pts; if (ubase_check(uref_clock_get_pts_sys(uref, &pts))) uref_clock_set_pts_sys(uref, pts + frames * UCLOCK_FREQ / SAMPLE_RATE); /* We should also change the duration but we don't use it. */ } }
/** @This frees a upipe. * * @param upipe description structure of the pipe */ static void upipe_nacl_audio_free(struct upipe *upipe) { struct upipe_nacl_audio *upipe_nacl_audio = upipe_nacl_audio_from_upipe(upipe); upipe_throw_dead(upipe); upipe_nacl_audio->audio_interface->StopPlayback(upipe_nacl_audio->audio); upipe_nacl_audio->core_interface->ReleaseResource(upipe_nacl_audio->audio); upipe_nacl_audio->core_interface->ReleaseResource(upipe_nacl_audio->audio_config); struct uref *uref; while ((uref = uqueue_pop(&upipe_nacl_audio->uqueue, struct uref *)) != NULL) uref_free(uref); upipe_nacl_audio_clean_uclock(upipe); upipe_nacl_audio_clean_upump_mgr(upipe); upipe_nacl_audio_clean_upump(upipe); uqueue_clean(&upipe_nacl_audio->uqueue); upipe_nacl_audio_clean_urefcount(upipe); free(upipe_nacl_audio); }
static void upipe_rtp_h264_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { size_t bz = 0; if (!ubase_check(uref_block_size(uref, &bz))) { upipe_err(upipe, "fail to get uref block size"); return upipe_rtp_h264_drop(upipe, uref); } uint8_t buf[bz]; int size = bz; if (unlikely(!ubase_check(uref_block_extract(uref, 0, size, buf)))) { upipe_err(upipe, "fail to read from uref"); return upipe_rtp_h264_drop(upipe, uref); } uint8_t s_len; const uint8_t *s = upipe_mpeg_scan(buf, buf + size, &s_len); if (s != buf) { upipe_err(upipe, "uref does not start with a mpeg start code"); return upipe_rtp_h264_drop(upipe, uref); } while (s < buf + size) { uint8_t e_len = 0; const uint8_t *e = upipe_mpeg_scan(s + s_len, buf + size, &e_len); if (!e) e = buf + size; struct uref *part = uref_block_splice(uref, s - buf + s_len + 1, e - (s + s_len + 1)); upipe_rtp_h264_output_nalu(upipe, *(s + s_len), part, upump_p); s = e; s_len = e_len; } uref_free(uref); }
/** @internal @This is called by avcodec when releasing a frame * @param context current avcodec context * @param frame avframe handler released by avcodec black magic box */ static void upipe_avcdec_release_buffer(struct AVCodecContext *context, AVFrame *frame) { struct upipe *upipe = context->opaque; struct uref *uref = frame->opaque; const struct upipe_av_plane *planes = NULL; int i; uint64_t framenum = 0; uref_pic_get_number(uref, &framenum); upipe_dbg_va(upipe, "Releasing frame %u (%p)", (uint64_t) framenum, uref); if (likely(uref->ubuf)) { planes = upipe_avcdec_from_upipe(upipe)->pixfmt->planes; for (i=0; i < 4 && planes[i].chroma; i++) { ubuf_pic_plane_unmap(uref->ubuf, planes[i].chroma, 0, 0, -1, -1); frame->data[i] = NULL; } } else { avcodec_default_release_buffer(context, frame); } uref_free(uref); }
/** @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); }
/** @internal @This allocates and initializes a void source pipe. * * @param mgr pointer to upipe manager * @param uprobe structure used to raise events * @param signature signature of the pipe allocator * @param args optional arguments * @return an alloocated and initialized pipe or NULL */ static struct upipe *upipe_voidsrc_alloc(struct upipe_mgr *mgr, struct uprobe *uprobe, uint32_t signature, va_list args) { struct uref *flow; struct upipe *upipe = upipe_voidsrc_alloc_flow(mgr, uprobe, signature, args, &flow); if (unlikely(!upipe)) return NULL; uint64_t duration = 0; if (unlikely(!ubase_check( uref_clock_get_duration(flow, &duration)))) { uref_free(flow); upipe_voidsrc_free_flow(upipe); return NULL; } upipe_voidsrc_init_urefcount(upipe); upipe_voidsrc_init_output(upipe); upipe_voidsrc_init_uref_mgr(upipe); upipe_voidsrc_init_uclock(upipe); upipe_voidsrc_init_upump_mgr(upipe); upipe_voidsrc_init_timer(upipe); struct upipe_voidsrc *upipe_voidsrc = upipe_voidsrc_from_upipe(upipe); upipe_voidsrc->interval = duration; upipe_voidsrc->pts = UINT64_MAX; upipe_throw_ready(upipe); upipe_voidsrc_store_flow_def(upipe, flow); return upipe; }
/** @internal @This works on a telx frame and outputs it. * * @param upipe description structure of the pipe * @param upump_p reference to pump that generated the buffer */ static void upipe_telxf_work(struct upipe *upipe, struct upump **upump_p) { struct upipe_telxf *upipe_telxf = upipe_telxf_from_upipe(upipe); uint64_t octetrate = (upipe_telxf->next_uref_size * upipe_telxf->fps.num + upipe_telxf->fps.den - 1) / upipe_telxf->fps.den; if (octetrate != upipe_telxf->octetrate) { upipe_telxf->octetrate = octetrate; struct uref *flow_def = upipe_telxf_alloc_flow_def_attr(upipe); if (unlikely(flow_def == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(upipe_telxf->next_uref); goto upipe_telxf_work_err; } UBASE_FATAL(upipe, uref_pic_flow_set_fps(flow_def, upipe_telxf->fps)) UBASE_FATAL(upipe, uref_block_flow_set_octetrate(flow_def, upipe_telxf->octetrate)) flow_def = upipe_telxf_store_flow_def_attr(upipe, flow_def); if (unlikely(flow_def == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(upipe_telxf->next_uref); goto upipe_telxf_work_err; } upipe_telxf_store_flow_def(upipe, flow_def); } upipe_telxf_sync_acquired(upipe); uint64_t duration = UCLOCK_FREQ * upipe_telxf->fps.den / upipe_telxf->fps.num; /* We work on encoded data so in the DTS domain. Rebase on DTS. */ uint64_t date; struct urational drift_rate; drift_rate.den = 0; uref_clock_get_rate(upipe_telxf->next_uref, &drift_rate); #define SET_DATE(dv) \ if (ubase_check(uref_clock_get_dts_##dv(upipe_telxf->next_uref, &date)))\ uref_clock_set_dts_##dv(&upipe_telxf->au_uref_s, date); \ if (ubase_check(uref_clock_get_dts_##dv(&upipe_telxf->au_uref_s, \ &date))) { \ uref_clock_set_dts_##dv(upipe_telxf->next_uref, date); \ uref_clock_set_dts_##dv(&upipe_telxf->au_uref_s, date + duration); \ } else if (ubase_check(uref_clock_get_cr_##dv(upipe_telxf->next_uref, \ &date))) { \ /* EN 300 472 Annex A */ \ uref_clock_set_dts_##dv(upipe_telxf->next_uref, \ date + MAX_DELAY_TELX); \ uref_clock_set_dts_##dv(&upipe_telxf->au_uref_s, date + \ MAX_DELAY_TELX + duration); \ } SET_DATE(sys) SET_DATE(prog) SET_DATE(orig) #undef SET_DATE uref_clock_set_dts_pts_delay(upipe_telxf->next_uref, 0); if (drift_rate.den) uref_clock_set_rate(upipe_telxf->next_uref, drift_rate); upipe_telxf_output(upipe, upipe_telxf->next_uref, upump_p); upipe_telxf_work_err: upipe_telxf->next_uref = NULL; upipe_telxf->next_uref_size = 0; }