Example #1
0
static void upipe_rtp_h264_output_nalu(struct upipe *upipe,
                                       uint8_t nalu,
                                       struct uref *uref,
                                       struct upump **upump_p)
{
    size_t size = 0;
    if (unlikely(!ubase_check(uref_block_size(uref, &size)))) {
        upipe_err(upipe, "fail to get block size");
        return;
    }

    bool split = size > RTP_SPLIT_SIZE;
    uint32_t fragment = 0;

    while (size) {
        bool last_fragment = size <= RTP_SPLIT_SIZE;
        size_t split_size = last_fragment ? size : RTP_SPLIT_SIZE;
        uint8_t hdr[2] = { nalu, 0 };
        size_t hdr_size = 1;

        if (split) {
            if (!fragment)
                hdr[1] = FU_START;
            else if (last_fragment)
                hdr[1] = FU_END;
            hdr[1] |= NALU_TYPE(hdr[0]);

            hdr[0] = NALU_F(hdr[0]) | NALU_NRI(hdr[0]) | FU_A;
            hdr_size++;
        }

        struct uref *next = NULL;
        if (!last_fragment) {
            next = uref_block_split(uref, split_size);
            if (unlikely(next == NULL)) {
                upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
                return;
            }
        }

        /* FIXME should require a ubuf_mgr */
        struct ubuf *header =
                ubuf_block_alloc(uref->ubuf->mgr, hdr_size * sizeof (hdr[0]));
        if (unlikely(header == NULL)) {
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
            uref_free(uref);
            uref_free(next);
            return;
        }

        uint8_t *buf = NULL;
        int buf_size = hdr_size;
        ubuf_block_write(header, 0, &buf_size, &buf);
        memcpy(buf, hdr, hdr_size * sizeof (hdr[0]));
        ubuf_block_unmap(header, 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);
            uref_free(uref);
            uref_free(next);
            return;
        }
        uref_attach_ubuf(uref, header);
        uref_clock_set_cr_dts_delay(uref, 0);
        upipe_rtp_h264_output(upipe, uref, upump_p);
        size -= split_size;
        fragment++;
        uref = next;
    }
}
Example #2
0
/** @internal @This handles data from sound allocator.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to pump that generated the buffer
 */
static void upipe_tblk_handle_sound(struct upipe *upipe, struct uref *uref,
                                    struct upump **upump_p)
{
    struct upipe_tblk *upipe_tblk = upipe_tblk_from_upipe(upipe);

    /* Always operate on the first channel plane. */
    const char *channel = NULL;
    if (unlikely(uref->ubuf == NULL ||
                 !ubase_check(ubuf_sound_plane_iterate(uref->ubuf, &channel)) ||
                 channel == NULL)) {
        uref_free(uref);
        upipe_throw_error(upipe, UBASE_ERR_INVALID);
        return;
    }

    /* First try the ubuf_mem_shared method. */
    struct ubuf *ubuf = ubuf_block_mem_alloc_from_sound(upipe_tblk->ubuf_mgr,
                                                        uref->ubuf, channel);
    if (unlikely(ubuf == NULL)) {
        /* We have to memcpy the thing. */
        size_t samples;
        uint8_t sample_size;
        if (unlikely(!ubase_check(uref_sound_size(uref, &samples,
                                                  &sample_size)))) {
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_INVALID);
            return;
        }

        size_t size = samples * sample_size;
        ubuf = ubuf_block_alloc(upipe_tblk->ubuf_mgr, size);
        if (unlikely(ubuf == NULL)) {
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_ALLOC);
            return;
        }

        const uint8_t *r;
        if (unlikely(!ubase_check(uref_sound_plane_read_uint8_t(uref, channel,
                                                                0, -1, &r)))) {
            ubuf_free(ubuf);
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_ALLOC);
            return;
        }

        uint8_t *w;
        int end = -1;
        if (unlikely(!ubase_check(ubuf_block_write(ubuf, 0, &end, &w)))) {
            uref_sound_plane_unmap(uref, channel, 0, -1);
            ubuf_free(ubuf);
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_ALLOC);
            return;
        }

        memcpy(w, r, size);
        ubuf_block_unmap(ubuf, 0);
        uref_sound_plane_unmap(uref, channel, 0, -1);
    }

    uref_attach_ubuf(uref, ubuf);
    upipe_tblk_output(upipe, uref, upump_p);
}
Example #3
0
/** @internal @This converts block urefs to sound 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_block_to_sound_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p)
{

    struct upipe_block_to_sound *upipe_block_to_sound = upipe_block_to_sound_from_upipe(upipe);

    /* get block size */
    size_t block_size = 0;
    uref_block_size(uref, &block_size);

    /* drop incomplete samples */
    if ((block_size % upipe_block_to_sound->sample_size) != 0) {
        upipe_warn(upipe, "Incomplete samples detected");
    }

    int samples = block_size / upipe_block_to_sound->sample_size;
    block_size = samples * upipe_block_to_sound->sample_size;

    /* alloc sound ubuf */
    struct ubuf *ubuf_block_to_sound = ubuf_sound_alloc(upipe_block_to_sound->ubuf_mgr,
                                                        samples);

    if (unlikely(ubuf_block_to_sound == NULL)) {
        uref_free(uref);
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return;
    }


    /* map sound ubuf for writing */
    int32_t *w;

    if (unlikely(!ubase_check(ubuf_sound_write_int32_t(ubuf_block_to_sound, 0, -1, &w,
                                                            upipe_block_to_sound->planes)))) {
        upipe_err(upipe, "could not write uref, dropping samples");
        ubuf_sound_unmap(ubuf_block_to_sound, 0, -1, upipe_block_to_sound->planes);
        ubuf_free(ubuf_block_to_sound);
        uref_free(uref);
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return;
    }
    /* map block ubuf for reading */
    const uint8_t *r;
    int end = -1;
    if (unlikely(!ubase_check(uref_block_read(uref, 0, &end, &r)))) {
        upipe_err(upipe, "could not read uref, dropping samples");
        ubuf_sound_unmap(ubuf_block_to_sound, 0, -1, upipe_block_to_sound->planes);
        ubuf_block_unmap(uref->ubuf, 0);
        ubuf_free(ubuf_block_to_sound);
        uref_free(uref);
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return;
    }
    /* copy block to sound */
    memcpy(w, r, block_size);
    /* unmap ubufs */
    ubuf_sound_unmap(ubuf_block_to_sound, 0, -1, upipe_block_to_sound->planes);
    ubuf_block_unmap(uref->ubuf, 0);
    /* attach sound ubuf to uref */
    uref_attach_ubuf(uref, ubuf_block_to_sound);
    /* output pipe */

    upipe_block_to_sound_output(upipe, uref, upump_p);
}
Example #4
0
/** @internal @This handles data from pic allocator.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to pump that generated the buffer
 */
static void upipe_tblk_handle_pic(struct upipe *upipe, struct uref *uref,
                                  struct upump **upump_p)
{
    struct upipe_tblk *upipe_tblk = upipe_tblk_from_upipe(upipe);

    /* Always operate on the first chroma plane. */
    const char *chroma = NULL;
    if (unlikely(uref->ubuf == NULL ||
                 !ubase_check(ubuf_pic_plane_iterate(uref->ubuf, &chroma)) ||
                 chroma == NULL)) {
        uref_free(uref);
        upipe_throw_error(upipe, UBASE_ERR_INVALID);
        return;
    }

    /* First try the ubuf_mem_shared method. */
    struct ubuf *ubuf = ubuf_block_mem_alloc_from_pic(upipe_tblk->ubuf_mgr,
                                                      uref->ubuf, chroma);
    if (unlikely(ubuf == NULL)) {
        /* We have to memcpy the thing. */
        size_t hsize, vsize, stride;
        uint8_t macropixel, hsub, vsub, macropixel_size;
        if (unlikely(!ubase_check(uref_pic_size(uref, NULL, &vsize,
                                                NULL)) ||
                     !ubase_check(uref_pic_plane_size(uref, chroma,
                             &stride, NULL, &vsub, NULL)))) {
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_INVALID);
            return;
        }

        size_t size = stride * vsize / vsub;
        ubuf = ubuf_block_alloc(upipe_tblk->ubuf_mgr, size);
        if (unlikely(ubuf == NULL)) {
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_ALLOC);
            return;
        }

        const uint8_t *r;
        if (unlikely(!ubase_check(uref_pic_plane_read(uref, chroma,
                            0, 0, -1, -1, &r)))) {
            ubuf_free(ubuf);
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_ALLOC);
            return;
        }

        uint8_t *w;
        int end = -1;
        if (unlikely(!ubase_check(ubuf_block_write(ubuf, 0, &end, &w)))) {
            uref_pic_plane_unmap(uref, chroma, 0, 0, -1, -1);
            ubuf_free(ubuf);
            uref_free(uref);
            upipe_throw_error(upipe, UBASE_ERR_ALLOC);
            return;
        }

        memcpy(w, r, size);
        ubuf_block_unmap(ubuf, 0);
        uref_pic_plane_unmap(uref, chroma, 0, 0, -1, -1);
    }

    uref_attach_ubuf(uref, ubuf);
    upipe_tblk_output(upipe, uref, upump_p);
}
Example #5
0
/** @internal @This prepends a PES header to a logical unit.
 *
 * @param upipe description structure of the pipe
 * @param upump_p reference to pump that generated the buffer
 */
static void upipe_ts_pese_work(struct upipe *upipe, struct upump **upump_p)
{
    struct upipe_ts_pese *upipe_ts_pese = upipe_ts_pese_from_upipe(upipe);
    if (ulist_empty(&upipe_ts_pese->next_pes))
        return;

    uint64_t pts = UINT64_MAX, dts = UINT64_MAX;
    struct uref *uref = uref_from_uchain(ulist_pop(&upipe_ts_pese->next_pes));

    size_t header_size;
    if (upipe_ts_pese->pes_id != PES_STREAM_ID_PRIVATE_2) {
        uref_clock_get_pts_prog(uref, &pts);
        uref_clock_get_dts_prog(uref, &dts);
        if (pts != UINT64_MAX) {
            if (dts != UINT64_MAX &&
                ((pts / CLOCK_SCALE) % POW2_33) !=
                    ((dts / CLOCK_SCALE) % POW2_33))
                header_size = PES_HEADER_SIZE_PTSDTS;
            else
                header_size = PES_HEADER_SIZE_PTS;
        } else
            header_size = PES_HEADER_SIZE_NOPTS;
    } else
        header_size = PES_HEADER_SIZE;
    if (header_size < upipe_ts_pese->pes_header_size)
        header_size = upipe_ts_pese->pes_header_size;

    struct ubuf *ubuf = ubuf_block_alloc(upipe_ts_pese->ubuf_mgr, header_size);
    if (unlikely(ubuf == NULL)) {
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        goto upipe_ts_pese_work_err;
    }

    uint8_t *buffer;
    int size = -1;
    if (unlikely(!ubase_check(ubuf_block_write(ubuf, 0, &size, &buffer)))) {
        ubuf_free(ubuf);
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        goto upipe_ts_pese_work_err;
    }

    pes_init(buffer);
    pes_set_streamid(buffer, upipe_ts_pese->pes_id);
    size_t pes_length = upipe_ts_pese->next_pes_size + header_size -
                        PES_HEADER_SIZE;
    if (pes_length > UINT16_MAX) {
        if (unlikely((upipe_ts_pese->pes_id & PES_STREAM_ID_VIDEO_MPEG) != 
                     PES_STREAM_ID_VIDEO_MPEG))
            upipe_warn(upipe, "PES length > 65535 for a non-video stream");
        pes_set_length(buffer, 0);
    } else
        pes_set_length(buffer, pes_length);

    if (upipe_ts_pese->pes_id != PES_STREAM_ID_PRIVATE_2) {
        pes_set_headerlength(buffer, header_size - PES_HEADER_SIZE_NOPTS);
        pes_set_dataalignment(buffer);
        if (pts != UINT64_MAX) {
            pes_set_pts(buffer, (pts / CLOCK_SCALE) % POW2_33);
            if (dts != UINT64_MAX &&
                ((pts / CLOCK_SCALE) % POW2_33) !=
                    ((dts / CLOCK_SCALE) % POW2_33))
                pes_set_dts(buffer, (dts / CLOCK_SCALE) % POW2_33);
        }
    }
    ubuf_block_unmap(ubuf, 0);

    struct ubuf *payload = uref_detach_ubuf(uref);
    uref_attach_ubuf(uref, ubuf);
    if (unlikely(!ubase_check(uref_block_append(uref, payload)))) {
        uref_free(uref);
        ubuf_free(payload);
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return;
    }

    /* intended pass-through */
upipe_ts_pese_work_err:
    uref_block_set_start(uref);
    upipe_ts_pese_output(upipe, uref, upump_p);

    struct uchain *uchain;
    while ((uchain = ulist_pop(&upipe_ts_pese->next_pes)) != NULL)
        upipe_ts_pese_output(upipe, uref_from_uchain(uchain), upump_p);
    upipe_ts_pese->next_pes_size = 0;
    upipe_ts_pese->next_pes_duration = 0;
}