/** @internal @This interpolates the PCRs for packets without a PCR. * * @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_pcr_interpolator_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_ts_pcr_interpolator *upipe_ts_pcr_interpolator = upipe_ts_pcr_interpolator_from_upipe(upipe); bool discontinuity = ubase_check(uref_flow_get_discontinuity(uref)); if (discontinuity) { upipe_ts_pcr_interpolator->last_pcr = 0; upipe_ts_pcr_interpolator->packets = 0; upipe_ts_pcr_interpolator->pcr_packets = 0; upipe_ts_pcr_interpolator->pcr_delta = 0; upipe_ts_pcr_interpolator->discontinuity = true; upipe_notice_va(upipe, "Clearing state"); } upipe_ts_pcr_interpolator->packets++; uint64_t pcr_prog = 0; uref_clock_get_cr_prog(uref, &pcr_prog); if (pcr_prog) { uint64_t delta = pcr_prog - upipe_ts_pcr_interpolator->last_pcr; upipe_ts_pcr_interpolator->last_pcr = pcr_prog; upipe_verbose_va(upipe, "pcr_prog %"PRId64" offset %"PRId64" stored offset %"PRIu64" bitrate %"PRId64" bps", pcr_prog, delta, upipe_ts_pcr_interpolator->pcr_delta, INT64_C(27000000) * upipe_ts_pcr_interpolator->packets * 188 * 8 / delta); if (upipe_ts_pcr_interpolator->pcr_delta) upipe_ts_pcr_interpolator->pcr_packets = upipe_ts_pcr_interpolator->packets; upipe_ts_pcr_interpolator->pcr_delta = delta; upipe_ts_pcr_interpolator->packets = 0; } else if (upipe_ts_pcr_interpolator->pcr_packets) { uint64_t offset = upipe_ts_pcr_interpolator->pcr_delta * upipe_ts_pcr_interpolator->packets / upipe_ts_pcr_interpolator->pcr_packets; uint64_t prog = upipe_ts_pcr_interpolator->last_pcr + offset; uref_clock_set_date_prog(uref, prog, UREF_DATE_CR); upipe_throw_clock_ts(upipe, uref); } if (!upipe_ts_pcr_interpolator->pcr_packets) { uref_free(uref); return; } if (upipe_ts_pcr_interpolator->discontinuity) { uref_flow_set_discontinuity(uref); upipe_ts_pcr_interpolator->discontinuity = false; } upipe_ts_pcr_interpolator_output(upipe, uref, upump_p); }
/** @internal @This receives data. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer */ static void upipe_a52f_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_a52f *upipe_a52f = upipe_a52f_from_upipe(upipe); if (unlikely(uref->ubuf == NULL)) { upipe_a52f_output(upipe, uref, upump_p); return; } if (unlikely(ubase_check(uref_flow_get_discontinuity(uref)))) { /* Drop the current frame and resync. */ upipe_a52f_clean_uref_stream(upipe); upipe_a52f_init_uref_stream(upipe); upipe_a52f->got_discontinuity = true; upipe_a52f->next_frame_size = -1; upipe_a52f_sync_lost(upipe); } upipe_a52f_append_uref_stream(upipe, uref); upipe_a52f_work(upipe, upump_p); }
/** @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); }
/** @internal @This outputs data to the file sink. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to pump that generated the buffer * @return true if the uref was processed */ static bool upipe_dveo_asi_sink_output(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_dveo_asi_sink *upipe_dveo_asi_sink = upipe_dveo_asi_sink_from_upipe(upipe); const char *def; if (unlikely(ubase_check(uref_flow_get_def(uref, &def)))) { uref_free(uref); return true; } int fd = upipe_dveo_asi_sink->fd; if (unlikely(fd == -1)) { upipe_warn(upipe, "received a buffer before opening the device"); uref_free(uref); return true; } uint64_t cr_sys = 0; if (unlikely(!ubase_check(uref_clock_get_cr_sys(uref, &cr_sys))) || cr_sys == -1) { upipe_warn(upipe, "received non-dated buffer"); uref_free(uref); return true; } if (ubase_check(uref_flow_get_discontinuity(uref))) { upipe_warn_va(upipe, "DISCONTINUITY, resetting timestamp"); upipe_dveo_asi_sink->first_timestamp = true; } if (unlikely(upipe_dveo_asi_sink->first_timestamp)) { int val; if (ioctl(fd, ASI_IOC_TXGETTXD, &val) < 0) { upipe_err_va(upipe, "ioctl TXGETTXDfailed (%m)"); upipe_throw_fatal(upipe, UBASE_ERR_UNKNOWN); uref_free(uref); return true; } else if (val) { upipe_warn(upipe, "Waiting for transmission to stop"); uref_free(uref); return true; } } /* Make sure we set the counter */ bool reset_first_timestamp = upipe_dveo_asi_sink->first_timestamp; if (upipe_dveo_asi_sink_add_header(upipe, uref, cr_sys)) { uref_free(uref); return true; /* invalid uref, discarded */ } if (!upipe_dveo_asi_sink_write(upipe, uref, &reset_first_timestamp)) return false; /* would block */ uref_free(uref); if (reset_first_timestamp) upipe_dveo_asi_sink->first_timestamp = true; upipe_dveo_asi_sink_stats(upipe); return true; }