Пример #1
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_telxf_input(struct upipe *upipe, struct uref *uref,
                              struct upump **upump_p)
{
    struct upipe_telxf *upipe_telxf = upipe_telxf_from_upipe(upipe);
    size_t uref_size;
    if (!ubase_check(uref_block_size(uref, &uref_size)) || !uref_size) {
        uref_free(uref);
        return;
    }
    bool end = ubase_check(uref_block_get_end(uref));

    if (ubase_check(uref_block_get_start(uref))) {
        if (upipe_telxf->next_uref != NULL)
            upipe_telxf_work(upipe, upump_p);

        upipe_telxf->next_uref = uref;
        upipe_telxf->next_uref_size = uref_size;
    } else if (likely(upipe_telxf->next_uref != NULL)) {
        struct ubuf *ubuf = uref_detach_ubuf(uref);
        uref_free(uref);
        if (unlikely(!ubase_check(uref_block_append(upipe_telxf->next_uref,
                                                    ubuf)))) {
            ubuf_free(ubuf);
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
            return;
        }
        upipe_telxf->next_uref_size += uref_size;
    } else {
        uref_free(uref);
        return;
    }

    if (end)
        upipe_telxf_work(upipe, upump_p);
}
Пример #2
0
/** @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_s337_encaps_set_flow_def(struct upipe *upipe,
                                          struct uref *flow_def)
{
    if (flow_def == NULL)
        return UBASE_ERR_INVALID;

    const char *def;
    UBASE_RETURN(uref_flow_get_def(flow_def, &def))

    uint64_t rate;
    UBASE_RETURN(uref_sound_flow_get_rate(flow_def, &rate))

    if (ubase_ncmp(def, EXPECTED_FLOW_DEF))
        return UBASE_ERR_INVALID;

    struct uref *flow_def_dup = uref_dup(flow_def);
    if (flow_def_dup == NULL)
        return UBASE_ERR_ALLOC;

    uref_flow_set_def(flow_def_dup, "sound.s32.s337.a52.");
    uref_sound_flow_set_channels(flow_def_dup, 2);
    uref_sound_flow_set_sample_size(flow_def_dup, 2*4);

    if (!ubase_check(uref_sound_flow_add_plane(flow_def_dup, "lr")) ||
        !ubase_check(uref_sound_flow_set_rate(flow_def_dup, rate))) {
        uref_free(flow_def_dup);
        return UBASE_ERR_ALLOC;
    }

    upipe_s337_encaps_require_ubuf_mgr(upipe, flow_def_dup);
    return UBASE_ERR_NONE;
}
Пример #3
0
/** @internal @This is called when there is new data.
 *
 * @param upipe description structure of the pipe
 * @param uref uref carrying the data
 * @param upump_p reference to pump that generated the buffer
 */
static void upipe_m3u_reader_input(struct upipe *upipe, struct uref *uref,
                                   struct upump **upump_p)
{
    struct upipe_m3u_reader *upipe_m3u_reader =
        upipe_m3u_reader_from_upipe(upipe);

    if (ubase_check(uref_block_get_start(uref)))
        upipe_m3u_reader->restart = true;
    if (upipe_m3u_reader->restart) {
        upipe_m3u_reader_flush(upipe);
        upipe_m3u_reader->restart = false;
    }

    bool end = false;
    if (unlikely(ubase_check(uref_block_get_end(uref))))
        end = true;

    upipe_m3u_reader_append_uref_stream(upipe, uref);
    upipe_m3u_reader_process(upipe);

    if (unlikely(end)) {
        upipe_m3u_reader_output_all(upipe, upump_p);
        upipe_m3u_reader->restart = true;
    }
}
Пример #4
0
/** @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_s337d_set_flow_def(struct upipe *upipe, struct uref *flow_def)
{
    if (flow_def == NULL)
        return UBASE_ERR_INVALID;
    const char *def;
    uint64_t rate;
    if (unlikely(!ubase_check(uref_flow_get_def(flow_def, &def)) ||
                 (ubase_ncmp(def, "block.s337.") &&
                  strcmp(def, "block.")) ||
                 !ubase_check(uref_sound_flow_get_rate(flow_def, &rate))))
        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;
    }

    struct upipe_s337d *upipe_s337d = upipe_s337d_from_upipe(upipe);
    upipe_s337d->sample_rate = rate;
    flow_def = upipe_s337d_store_flow_def_input(upipe, flow_def_dup);
    if (flow_def != NULL)
        upipe_s337d_store_flow_def(upipe, flow_def);
    return UBASE_ERR_NONE;
}
Пример #5
0
/** @internal @This parses and outputs a m3u file.
 *
 * @param upipe description structure of the pipe
 * @return an error code
 */
static void upipe_m3u_reader_process(struct upipe *upipe)
{
    struct upipe_m3u_reader *upipe_m3u_reader =
        upipe_m3u_reader_from_upipe(upipe);

    if (unlikely(upipe_m3u_reader->current_flow_def == NULL)) {
        upipe_m3u_reader->current_flow_def =
            uref_dup(upipe_m3u_reader->flow_def);
        if (unlikely(upipe_m3u_reader->current_flow_def == NULL)) {
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
            return;
        }
    }

    /* parse m3u */
    int ret = UBASE_ERR_NONE;
    struct uref *uref = upipe_m3u_reader->next_uref;
    for (size_t offset = 0;
         uref &&
         ubase_check(ret) &&
         ubase_check(uref_block_scan(uref, &offset, '\n'));
         offset = 0, uref = upipe_m3u_reader->next_uref) {
        struct uref *line =
            upipe_m3u_reader_extract_uref_stream(upipe, offset + 1);
        ret = upipe_m3u_reader_process_line(
            upipe, upipe_m3u_reader->current_flow_def, line);
        uref_free(line);
    }

    if (!ubase_check(ret))
        upipe_err(upipe, "invalid m3u");
}
Пример #6
0
/** @internal @This checks if a sync word begins just after the end of the
 * next frame.
 *
 * @param upipe description structure of the pipe
 * @param ready_p filled with true if a sync word was found
 * @param false if no sync word was found and resync is needed
 */
static bool upipe_a52f_check_frame(struct upipe *upipe, bool *ready_p)
{
    struct upipe_a52f *upipe_a52f = upipe_a52f_from_upipe(upipe);
    size_t size;
    *ready_p = false;
    if (!ubase_check(uref_block_size(upipe_a52f->next_uref, &size)))
        return false;
    if (size < upipe_a52f->next_frame_size)
        return true;

    uint8_t words[2];
    if (!ubase_check(uref_block_extract(upipe_a52f->next_uref,
                            upipe_a52f->next_frame_size, 2, words))) {
        /* not enough data */
        if (upipe_a52f->acquired) {/* avoid delaying packets unnecessarily */
            *ready_p = true;
        }
        return true;
    }
    if (words[0] != 0xb || words[1] != 0x77) {
        return false;
    }
    *ready_p = true;
    return true;
}
Пример #7
0
/** @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_a52f_set_flow_def(struct upipe *upipe, struct uref *flow_def)
{
    if (flow_def == NULL)
        return UBASE_ERR_INVALID;
    const char *def;
    if (unlikely(!ubase_check(uref_flow_get_def(flow_def, &def)) ||
                 (ubase_ncmp(def, "block.ac3.") &&
                  ubase_ncmp(def, "block.eac3.") &&
                  strcmp(def, "block."))))
        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;
    }

    struct upipe_a52f *upipe_a52f = upipe_a52f_from_upipe(upipe);
    upipe_a52f->input_latency = 0;
    uref_clock_get_latency(flow_def, &upipe_a52f->input_latency);

    if (unlikely(upipe_a52f->samplerate &&
                 !ubase_check(uref_clock_set_latency(flow_def_dup,
                                    upipe_a52f->input_latency +
                                    UCLOCK_FREQ * A52_FRAME_SAMPLES /
                                    upipe_a52f->samplerate))))
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
    flow_def = upipe_a52f_store_flow_def_input(upipe, flow_def_dup);
    if (flow_def != NULL)
        upipe_a52f_store_flow_def(upipe, flow_def);
    return UBASE_ERR_NONE;
}
Пример #8
0
/** @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;
}
Пример #9
0
/* iterate in es configuration options */
static bool es_conf_iterate(struct es_conf *conf, const char **key,
                            const char **value, enum udict_type *type)
{
    if (!ubase_check(udict_iterate(conf->options, key, type)) ||
        *type == UDICT_TYPE_END) {
        return false;
    }
    return ubase_check(udict_get_string(conf->options, value, *type, *key));
}
Пример #10
0
static bool upipe_dveo_asi_sink_write(struct upipe *upipe, struct uref *uref,
        bool *reset_first_timestamp)
{
    struct upipe_dveo_asi_sink *upipe_dveo_asi_sink = upipe_dveo_asi_sink_from_upipe(upipe);
    for (;;) {
        int iovec_count = uref_block_iovec_count(uref, 0, -1);
        if (unlikely(iovec_count == -1)) {
            upipe_warn(upipe, "cannot read ubuf buffer");
            break;
        }
        if (unlikely(iovec_count == 0)) {
            break;
        }

        struct iovec iovecs[iovec_count];
        if (unlikely(!ubase_check(uref_block_iovec_read(uref, 0, -1,
                                                        iovecs)))) {
            upipe_warn(upipe, "cannot read ubuf buffer");
            break;
        }

        ssize_t ret = writev(upipe_dveo_asi_sink->fd, iovecs, iovec_count);
        uref_block_iovec_unmap(uref, 0, -1, iovecs);

        if (unlikely(ret == -1)) {
            switch (errno) {
                case EINTR:
                    continue;
                case EAGAIN:
#if EAGAIN != EWOULDBLOCK
                case EWOULDBLOCK:
#endif
                    //upipe_notice_va(upipe, "polling");
                    upipe_dveo_asi_sink_poll(upipe);
                    return false;
                default:
                    break;
            }
            upipe_warn_va(upipe, "write error to device %d (%m)", upipe_dveo_asi_sink->card_idx);
            upipe_dveo_asi_sink_set_upump(upipe, NULL);
            upipe_throw_sink_end(upipe);
            break;
        }

        size_t uref_size;
        if (ubase_check(uref_block_size(uref, &uref_size)) &&
            uref_size == ret) {
            /* wrote succeeded */
            *reset_first_timestamp = false;
            break;
        }
        uref_block_resize(uref, ret, -1);
    }

    return true;
}
Пример #11
0
static bool upipe_dveo_asi_sink_add_header(struct upipe *upipe, struct uref *uref,
    uint64_t pts)
{
    struct upipe_dveo_asi_sink *upipe_dveo_asi_sink = upipe_dveo_asi_sink_from_upipe(upipe);

    uint64_t hdr_size;
    if (!ubase_check(uref_block_get_header_size(uref, &hdr_size)))
        hdr_size = 0;

    if (hdr_size != 0)
        return false;

    /* alloc header */
    struct ubuf *header = ubuf_block_alloc(uref->ubuf->mgr, 8);
    if (unlikely(!header)) {
        return true;
    }

    /* 63-bits timestamp */
    union {
        uint8_t timestamp[8];
        uint64_t pts;
    } timestamp;

    timestamp.pts = pts;
    if (upipe_dveo_asi_sink->first_timestamp) {
        upipe_dveo_asi_sink->first_timestamp = false;
        // FIXME: set the counter in an empty packet, and account for latency
        timestamp.pts |= 1LLU << 63; /* Set MSB = Set the counter */
    }

    /* write header, 64 bits little-endian :
     * https://github.com/kierank/dveo-linux-master/blob/450e4b9e4292c2f71acd4d3d2e0a0cd0879d473a/doc/ASI/features.txt#L62 */
    int size = 8;
    uint8_t *header_write_ptr;
    if (!ubase_check(ubuf_block_write(header, 0, &size, &header_write_ptr))) {
        upipe_err(upipe, "could not write header");
        ubuf_free(header);
        return true;
    }
    memcpy(header_write_ptr, timestamp.timestamp, 8);
    uref_block_unmap(uref, 0);

    /* append payload (current ubuf) to header to form segmented ubuf */
    struct ubuf *payload = uref_detach_ubuf(uref);
    if (unlikely(!ubase_check(ubuf_block_append(header, payload)))) {
        upipe_warn(upipe, "could not append payload to header");
        ubuf_free(header);
        ubuf_free(payload);
        return true;
    }
    uref_attach_ubuf(uref, header);
    uref_block_set_header_size(uref, 8);

    return false;
}
Пример #12
0
/** @internal @This handles input.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to pump that generated the buffer
 */
static void upipe_htons_input(struct upipe *upipe, struct uref *uref,
                              struct upump **upump_p)
{
    struct ubuf *ubuf;
    size_t size = 0;
    int remain, bufsize = -1, offset = 0;
    uint8_t *buf = NULL;

    /* block size */
    if (unlikely(!ubase_check(uref_block_size(uref, &size)))) {
        upipe_warn(upipe, "could not read uref block size");
        uref_free(uref);
        return;
    }
    /* copy ubuf if shared or not 16b-unaligned or segmented */
    bufsize = -1;
    if (!ubase_check(uref_block_write(uref, 0, &bufsize, &buf)) ||
        ((uintptr_t)buf & 1) || bufsize != size) {
        ubuf = ubuf_block_copy(uref->ubuf->mgr, uref->ubuf, 0, size);
        if (unlikely(!ubuf)) {
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
            uref_free(uref);
            return;
        }
        uref_attach_ubuf(uref, ubuf);
    } else {
        uref_block_unmap(uref, 0);
    }

    /* process ubuf chunks */
    while (size > 0) {
        bufsize = -1;
        if (unlikely(!ubase_check(uref_block_write(uref, offset, &bufsize,
                                  &buf)))) {
            upipe_warn(upipe, "unexpected buffer error");
            uref_free(uref);
            return;
        }
        if (unlikely((uintptr_t)buf & 1)) {
            upipe_warn_va(upipe, "unaligned buffer: %p", buf);
        }
        for (remain = bufsize; remain > 1; remain -= 2) {
            *(uint16_t *)buf = htons(*(uint16_t *)buf);
            buf += 2;
        }

        uref_block_unmap(uref, offset);
        offset += bufsize;
        size -= bufsize;
    }

    upipe_htons_output(upipe, uref, upump_p);
}
Пример #13
0
/** @internal @This catches events of the avcdec.
 *
 * @param uprobe pointer to probe
 * @param upipe pointer to pipe throwing the event
 * @param event event thrown
 * @param args optional event-specific parameters
 * @return an error code
 */
static int upipe_glxplayer_catch_avcdec(struct uprobe *uprobe,
                                        struct upipe *upipe,
                                        int event, va_list args)
{
    switch (event) {
        case UPROBE_NEED_OUTPUT: {
            struct upipe_glxplayer *glxplayer =
                container_of(uprobe, struct upipe_glxplayer, uprobe_avcdec_s);
            struct uref *flow_def = va_arg(args, struct uref *);
            struct upipe *deint =
                upipe_void_alloc_output(upipe,
                        glxplayer->upipe_filter_blend_mgr,
                        uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger),
                                         glxplayer->loglevel, "deint"));
            if (unlikely(deint == NULL))
                return UBASE_ERR_ALLOC;

            struct uref *output_flow = uref_dup(flow_def);
            if (unlikely(output_flow == NULL))
                return UBASE_ERR_ALLOC;
            uref_pic_flow_clear_format(output_flow);
            if (unlikely(!ubase_check(uref_pic_flow_set_macropixel(output_flow, 1)) ||
                         !ubase_check(uref_pic_flow_set_planes(output_flow, 0)) ||
                         !ubase_check(uref_pic_flow_add_plane(output_flow, 1, 1, 3,
                                                  "r8g8b8")))) {
                uref_free(output_flow);
                return UBASE_ERR_ALLOC;
            }

            struct upipe *yuvrgb = upipe_flow_alloc_output(deint,
                    glxplayer->upipe_sws_mgr,
                    uprobe_pfx_alloc_va(uprobe_use(glxplayer->uprobe_logger),
                                        glxplayer->loglevel, "rgb"),
                    output_flow);
            assert(yuvrgb != NULL);
            uref_free(output_flow);
            upipe_release(deint);

            glxplayer->upipe_glx_qsink =
                upipe_qsink_alloc(glxplayer->upipe_qsink_mgr,
                    uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger),
                    glxplayer->loglevel, "glx qsink"),
                    glxplayer->upipe_glx_qsrc);
            if (unlikely(glxplayer->upipe_glx_qsink == NULL))
                return UBASE_ERR_ALLOC;
            upipe_set_output(yuvrgb, glxplayer->upipe_glx_qsink);
            upipe_release(yuvrgb);
            return UBASE_ERR_NONE;
        }
        default:
            return uprobe_throw_next(uprobe, upipe, event, args);
    }
}
Пример #14
0
/** @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;

    enum upipe_filter_ebur128_fmt fmt;
    const char *def;
    UBASE_RETURN(uref_flow_get_def(flow, &def))
    if (!ubase_ncmp(def, "sound.s16."))
        fmt = UPIPE_FILTER_EBUR128_SHORT;
    else if (!ubase_ncmp(def, "sound.s32."))
        fmt = UPIPE_FILTER_EBUR128_INT;
    else if (!ubase_ncmp(def, "sound.f32."))
        fmt = UPIPE_FILTER_EBUR128_FLOAT;
    else if (!ubase_ncmp(def, "sound.f64."))
        fmt = UPIPE_FILTER_EBUR128_DOUBLE;
    else
        return UBASE_ERR_INVALID;

    uint64_t rate;
    if (unlikely(!ubase_check(uref_sound_flow_get_rate(flow, &rate))
            || !ubase_check(uref_sound_flow_get_channels(flow,
                    &upipe_filter_ebur128->channels))
            || !ubase_check(uref_sound_flow_get_planes(flow,
                    &upipe_filter_ebur128->planes))))
        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;
    }
    upipe_filter_ebur128->fmt = fmt;

    if (unlikely(upipe_filter_ebur128->st)) {
        //ebur128_destroy(&upipe_filter_ebur128->st);
        ebur128_change_parameters(upipe_filter_ebur128->st,
                                  upipe_filter_ebur128->channels, rate);
    } else {
        upipe_filter_ebur128->st =
            ebur128_init(upipe_filter_ebur128->channels, rate,
            EBUR128_MODE_LRA | EBUR128_MODE_I | EBUR128_MODE_HISTOGRAM);
    }

    upipe_filter_ebur128_store_flow_def(upipe, flow_dup);
    return UBASE_ERR_NONE;
}
Пример #15
0
/** @internal @This scans for a sync word.
 *
 * @param upipe description structure of the pipe
 * @param dropped_p filled with the number of octets to drop before the sync
 * @return true if a sync word was found
 */
static bool upipe_a52f_scan(struct upipe *upipe, size_t *dropped_p)
{
    struct upipe_a52f *upipe_a52f = upipe_a52f_from_upipe(upipe);
    while (ubase_check(uref_block_scan(upipe_a52f->next_uref, dropped_p, 0xb))) {
        uint8_t word;
        if (!ubase_check(uref_block_extract(upipe_a52f->next_uref,
                                            *dropped_p + 1, 1, &word)))
            return false;

        if (word == 0x77)
            return true;
        (*dropped_p)++;
    }
    return false;
}
Пример #16
0
/** @internal @This allocates a video blank 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 allocated pipe
 */
static struct upipe *upipe_vblk_alloc(struct upipe_mgr *mgr,
                                      struct uprobe *uprobe,
                                      uint32_t signature, va_list args)
{
    struct uref *flow_def;
    struct upipe *upipe = upipe_vblk_alloc_flow(mgr, uprobe, signature, args,
                                                &flow_def);
    if (unlikely(!upipe)) {
        return NULL;
    }

    upipe_vblk_init_urefcount(upipe);
    upipe_vblk_init_output(upipe);
    upipe_vblk_init_flow_def(upipe);
    upipe_vblk_init_ubuf_mgr(upipe);

    struct upipe_vblk *upipe_vblk = upipe_vblk_from_upipe(upipe);
    upipe_vblk->ubuf = NULL;

    upipe_throw_ready(upipe);

    if (unlikely(!ubase_check(upipe_vblk_check_flow_def(upipe, flow_def)))) {
        uref_free(flow_def);
        upipe_release(upipe);
        return NULL;
    }

    upipe_vblk_store_flow_def(upipe, flow_def);

    return upipe;
}
Пример #17
0
static void pic_fill_in(struct ubuf *ubuf)
{
    size_t hsize, vsize;
    uint8_t macropixel;
    ubase_assert(ubuf_pic_size(ubuf, &hsize, &vsize, &macropixel));

    const char *chroma = NULL;
    while (ubase_check(ubuf_pic_plane_iterate(ubuf, &chroma)) &&
           chroma != NULL) {
        size_t stride;
        uint8_t hsub, vsub, macropixel_size;
        ubase_assert(ubuf_pic_plane_size(ubuf, chroma, &stride, &hsub, &vsub,
                                         &macropixel_size));
        int hoctets = hsize * macropixel_size / hsub / macropixel;
        uint8_t *buffer;
        ubase_assert(ubuf_pic_plane_write(ubuf, chroma, 0, 0, -1, -1, &buffer));

        for (int y = 0; y < vsize / vsub; y++) {
            for (int x = 0; x < hoctets; x++)
                buffer[x] = 1 + (y * hoctets) + x;
            buffer += stride;
        }
        ubase_assert(ubuf_pic_plane_unmap(ubuf, chroma, 0, 0, -1, -1));
    }
}
Пример #18
0
/* add option to es configuration */
static bool es_conf_add_option(struct es_conf *conf, const char *key,
                               const char *value)
{
    assert(conf);
    return ubase_check(udict_set_string(conf->options,
                       value, UDICT_TYPE_STRING, key));
}
Пример #19
0
static void upipe_rtp_opus_input(struct upipe *upipe, struct uref *uref,
                                  struct upump **upump_p)
{
    struct upipe_rtp_opus *upipe_rtp_opus = upipe_rtp_opus_from_upipe(upipe);

    uint64_t timestamp = 0;
    size_t block_size = 0;
    if (!ubase_check(uref_block_size(uref, &block_size))) {
        upipe_warn(upipe, "fail to get uref block size");
        return;
    }

    uref_rtp_get_timestamp(uref, &timestamp);
    uref_clock_set_pts_orig(uref, timestamp * TS_MULTIPLIER);

    uint64_t delta =
        (UINT_MAX + timestamp -
         (upipe_rtp_opus->last_rtp_timestamp % UINT_MAX)) % UINT_MAX;
    upipe_rtp_opus->last_rtp_timestamp += delta;
    uref_clock_set_pts_prog(uref, upipe_rtp_opus->last_rtp_timestamp * TS_MULTIPLIER);

    upipe_throw_clock_ref(upipe, uref, upipe_rtp_opus->last_rtp_timestamp * TS_MULTIPLIER, 0);
    upipe_throw_clock_ts(upipe, uref);

    upipe_rtp_opus_output(upipe, uref, upump_p);
}
Пример #20
0
/** @internal @This handles audio 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_audio(struct upipe *upipe,
        struct uref *uref, struct upump **upump_p)
{
    struct upipe_osx_audioqueue_sink *osx_audioqueue =
        upipe_osx_audioqueue_sink_from_upipe(upipe);
    struct AudioQueueBuffer *qbuf;
    size_t size = 0;

    if (unlikely(!ubase_check(uref_block_size(uref, &size)))) {
        upipe_warn(upipe, "could not get block size");
        uref_free(uref);
        return;
    }

    /* TODO block ? */
#if 0
    upump_mgr_use(upump->mgr);
    upump_mgr_sink_block(upump->mgr);
#endif

    /* allocate queue buf, extract block, enqueue
     * Audioqueue has no support for "external" buffers */
    AudioQueueAllocateBuffer(osx_audioqueue->queue, size, &qbuf);
    uref_block_extract(uref, 0, -1, qbuf->mAudioData);
    qbuf->mAudioDataByteSize = size;
    qbuf->mUserData = (*upump_p)->mgr;
    AudioQueueEnqueueBuffer(osx_audioqueue->queue, qbuf, 0, NULL);

    uref_free(uref);
}
Пример #21
0
/** @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;
    }

    while (size > upipe_ts_check->output_size) {
        struct uref *next = uref_block_split(uref, upipe_ts_check->output_size);
        if (unlikely(next == NULL)) {
            uref_free(uref);
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
            return;
        }
        if (!upipe_ts_check_check(upipe, uref, upump_p)) {
            uref_free(next);
            return;
        }

        size -= upipe_ts_check->output_size;
        uref = next;
    }
    if (size == upipe_ts_check->output_size)
        upipe_ts_check_check(upipe, uref, upump_p);
}
Пример #22
0
/** @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;
}
Пример #23
0
/** @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_fdec_set_flow_def(struct upipe *upipe, struct uref *flow_def)
{
    struct upipe_fdec_mgr *fdec_mgr = upipe_fdec_mgr_from_upipe_mgr(upipe->mgr);
    struct upipe_fdec *upipe_fdec = upipe_fdec_from_upipe(upipe);
    if (flow_def == NULL)
        return UBASE_ERR_INVALID;

    if (upipe_fdec->last_inner != NULL) {
        if (ubase_check(upipe_set_flow_def(upipe_fdec->last_inner, flow_def)))
            return UBASE_ERR_NONE;
    }
    upipe_fdec_store_bin_input(upipe, NULL);
    upipe_fdec_store_bin_output(upipe, NULL);

    struct upipe *avcdec = upipe_void_alloc(fdec_mgr->avcdec_mgr,
            uprobe_pfx_alloc(
                uprobe_use(&upipe_fdec->last_inner_probe),
                UPROBE_LOG_VERBOSE, "avcdec"));

    if (unlikely(avcdec == NULL)) {
        upipe_err_va(upipe, "couldn't allocate avcdec");
        return UBASE_ERR_UNHANDLED;
    }
    if (unlikely(!ubase_check(upipe_set_flow_def(avcdec, flow_def)))) {
        upipe_err_va(upipe, "couldn't set avcdec flow def");
        upipe_release(avcdec);
        return UBASE_ERR_UNHANDLED;
    }
    if (upipe_fdec->options != NULL && upipe_fdec->options->udict != NULL) {
        const char *key = NULL;
        enum udict_type type = UDICT_TYPE_END;
        while (ubase_check(udict_iterate(upipe_fdec->options->udict, &key,
                                         &type)) && type != UDICT_TYPE_END) {
            const char *value;
            if (key == NULL ||
                !ubase_check(udict_get_string(upipe_fdec->options->udict,
                                              &value, type, key)))
                continue;
            if (!ubase_check(upipe_set_option(avcdec, key, value)))
                upipe_warn_va(upipe, "option %s=%s invalid", key, value);
        }
    }

    upipe_fdec_store_bin_input(upipe, upipe_use(avcdec));
    upipe_fdec_store_bin_output(upipe, avcdec);
    return UBASE_ERR_NONE;
}
Пример #24
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_dejitter_sub_input(struct upipe *upipe, struct uref *uref,
                                     struct upump **upump_p)
{
    uint64_t date;
    if (ubase_check(uref_clock_get_dts_prog(uref, &date)))
        upipe_throw_clock_ts(upipe, uref);
    upipe_dejitter_output(upipe, uref, upump_p);
}
Пример #25
0
/** @internal @This scans for a sync word.
 *
 * @param upipe description structure of the pipe
 * @param dropped_p filled with the number of octets to drop before the sync
 * @return true if a sync word was found
 */
static bool upipe_s337d_scan(struct upipe *upipe, size_t *dropped_p)
{
    struct upipe_s337d *upipe_s337d = upipe_s337d_from_upipe(upipe);
    while (ubase_check(uref_block_scan(upipe_s337d->next_uref, dropped_p,
                                       S337_PREAMBLE_A1))) {
        uint8_t preamble[3];
        if (!ubase_check(uref_block_extract(upipe_s337d->next_uref,
                        *dropped_p + 1, 3, preamble)))
            return false;

        if (preamble[0] == S337_PREAMBLE_A2 &&
            preamble[1] == S337_PREAMBLE_B1 &&
            preamble[2] == S337_PREAMBLE_B2)
            return true;
        (*dropped_p)++;
    }
    return false;
}
Пример #26
0
/** @internal @This checks if a burst is complete.
 *
 * @param upipe description structure of the pipe
 * @param true if the burst is complete
 */
static bool upipe_s337d_check_frame(struct upipe *upipe)
{
    struct upipe_s337d *upipe_s337d = upipe_s337d_from_upipe(upipe);
    size_t size;
    if (!ubase_check(uref_block_size(upipe_s337d->next_uref, &size))) {
        upipe_s337d->next_frame_discard = true;
        return true;
    }
    return size >= upipe_s337d->next_frame_size + S337_PREAMBLE_SIZE;
}
Пример #27
0
/** @internal @This merges the new access unit into a possibly existing
 * incomplete PES, and outputs the PES if possible.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to pump that generated the buffer
 * @return false if the input must be blocked
 */
static bool upipe_ts_pese_handle(struct upipe *upipe, struct uref *uref,
                                 struct upump **upump_p)
{
    struct upipe_ts_pese *upipe_ts_pese = upipe_ts_pese_from_upipe(upipe);
    const char *def;
    if (unlikely(ubase_check(uref_flow_get_def(uref, &def)))) {
        upipe_ts_pese_work(upipe, NULL);

        uref_ts_flow_get_pes_id(uref, &upipe_ts_pese->pes_id);
        upipe_ts_pese->pes_header_size = 0;
        uref_ts_flow_get_pes_header(uref, &upipe_ts_pese->pes_header_size);
        upipe_ts_pese->pes_min_duration = 0;
        uref_ts_flow_get_pes_min_duration(uref,
                                          &upipe_ts_pese->pes_min_duration);
        upipe_ts_pese->input_latency = 0;
        uref_clock_get_latency(uref, &upipe_ts_pese->input_latency);
        if (unlikely(!ubase_check(uref_clock_set_latency(uref,
                                        upipe_ts_pese->input_latency +
                                        upipe_ts_pese->pes_min_duration))))
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        upipe_ts_pese_store_flow_def(upipe, NULL);
        upipe_ts_pese_require_ubuf_mgr(upipe, uref);
        return true;
    }

    if (upipe_ts_pese->flow_def == NULL)
        return false;

    uint64_t uref_duration = upipe_ts_pese->pes_min_duration;
    uref_clock_get_duration(uref, &uref_duration);
    size_t uref_size = 0;
    uref_block_size(uref, &uref_size);
    uref_block_delete_start(uref);

    ulist_add(&upipe_ts_pese->next_pes, uref_to_uchain(uref));
    upipe_ts_pese->next_pes_duration += uref_duration;
    upipe_ts_pese->next_pes_size += uref_size;

    if (upipe_ts_pese->next_pes_duration >= upipe_ts_pese->pes_min_duration)
        upipe_ts_pese_work(upipe, upump_p);
    return true;
}
Пример #28
0
/** @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;
}
Пример #29
0
/** 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);
}
Пример #30
0
/** @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);
}