/** @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);
}
Example #2
0
/** @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);
}
Example #3
0
/** @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);
}
Example #4
0
/** @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;
}