Esempio n. 1
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;
}
Esempio n. 2
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;
    }
}