Example #1
0
size_t mpeg_bitstream_parse(mpeg_bitstream_t* packet, caption_frame_t* frame, const uint8_t* data, size_t size, unsigned stream_type, double dts, double cts)
{
    if (MAX_NALU_SIZE <= packet->size) {
        packet->status = LIBCAPTION_ERROR;
        // fprintf(stderr, "LIBCAPTION_ERROR\n");
        return 0;
    }

    // consume upto MAX_NALU_SIZE bytes
    if (MAX_NALU_SIZE <= packet->size + size) {
        size = MAX_NALU_SIZE - packet->size;
    }

    sei_t sei;
    size_t header_size, scpos;
    packet->status = LIBCAPTION_OK;
    memcpy(&packet->data[packet->size], data, size);
    packet->size += size;

    while (packet->status == LIBCAPTION_OK && 0 < (scpos = find_start_code(&packet->data[0], packet->size))) {
        switch (mpeg_bitstream_packet_type(packet, stream_type)) {
        default:
            break;
        case H262_SEI_PACKET:
            header_size = 4;
            if (STREAM_TYPE_H262 == stream_type && scpos > header_size) {
                cea708_t* cea708 = _mpeg_bitstream_cea708_emplace_back(packet, dts + cts);
                packet->status = libcaption_status_update(packet->status, cea708_parse_h262(&packet->data[header_size], scpos - header_size, cea708));
                _mpeg_bitstream_cea708_sort_flush(packet, frame, dts);
            }
            break;
        case H264_SEI_PACKET:
        case H265_SEI_PACKET:
            header_size = STREAM_TYPE_H264 == stream_type ? 4 : STREAM_TYPE_H265 == stream_type ? 5 : 0;
            if (header_size && scpos > header_size) {
                packet->status = libcaption_status_update(packet->status, sei_parse(&sei, &packet->data[header_size], scpos - header_size, dts + cts));
                for (sei_message_t* msg = sei_message_head(&sei); msg; msg = sei_message_next(msg)) {
                    if (sei_type_user_data_registered_itu_t_t35 == sei_message_type(msg)) {
                        cea708_t* cea708 = _mpeg_bitstream_cea708_emplace_back(packet, dts + cts);
                        packet->status = libcaption_status_update(packet->status, cea708_parse_h264(sei_message_data(msg), sei_message_size(msg), cea708));
                        _mpeg_bitstream_cea708_sort_flush(packet, frame, dts);
                    }
                }
                sei_free(&sei);
            }
            break;
        }

        packet->size -= scpos;
        memmove(&packet->data[0], &packet->data[scpos], packet->size);
    }

    return size;
}
Example #2
0
void sei_cat(sei_t* to, sei_t* from, int itu_t_t35)
{
    if (!to || !from) {
        return;
    }

    sei_message_t* msg = NULL;
    for (msg = sei_message_head(from); msg; msg = sei_message_next(msg)) {
        if (itu_t_t35 || sei_type_user_data_registered_itu_t_t35 != msg->type) {
            sei_message_append(to, sei_message_copy(msg));
        }
    }
}
Example #3
0
size_t sei_render_size (sei_t* sei)
{
    size_t size = 2; // nalu_type + stop bit
    sei_message_t* msg;

    for (msg = sei_message_head (sei) ; msg ; msg = sei_message_next (msg)) {
        size += 1 + (msg->type / 255);
        size += 1 + (msg->size / 255);
        size += 1 + (msg->size * 4/3);
    }

    return size;
}
Example #4
0
// we can safely assume sei_render_size() bytes have been allocated for data
size_t sei_render(sei_t* sei, uint8_t* data)
{
    if (!sei || !sei->head) {
        return 0;
    }

    size_t escaped_size, size = 2; // nalu_type + stop bit
    sei_message_t* msg;
    (*data) = 6;
    ++data;

    for (msg = sei_message_head(sei); msg; msg = sei_message_next(msg)) {
        int payloadType = sei_message_type(msg);
        int payloadSize = (int)sei_message_size(msg);
        uint8_t* payloadData = sei_message_data(msg);

        while (255 <= payloadType) {
            (*data) = 255;
            ++data;
            ++size;
            payloadType -= 255;
        }

        (*data) = payloadType;
        ++data;
        ++size;

        while (255 <= payloadSize) {
            (*data) = 255;
            ++data;
            ++size;
            payloadSize -= 255;
        }

        (*data) = payloadSize;
        ++data;
        ++size;

        if (0 >= (escaped_size = _copy_from_rbsp(data, payloadData, payloadSize))) {
            return 0;
        }

        data += escaped_size;
        size += escaped_size;
    }

    // write stop bit and return
    (*data) = 0x80;
    return size;
}
Example #5
0
libcaption_stauts_t sei_to_caption_frame(sei_t* sei, caption_frame_t* frame)
{
    cea708_t cea708;
    sei_message_t* msg;
    libcaption_stauts_t status = LIBCAPTION_OK;

    cea708_init(&cea708, frame->timestamp);

    for (msg = sei_message_head(sei); msg; msg = sei_message_next(msg)) {
        if (sei_type_user_data_registered_itu_t_t35 == sei_message_type(msg)) {
            cea708_parse_h264(sei_message_data(msg), sei_message_size(msg), &cea708);
            status = libcaption_status_update(status, cea708_to_caption_frame(frame, &cea708));
        }
    }

    if (LIBCAPTION_READY == status) {
        frame->timestamp = sei->timestamp;
    }

    return status;
}