obs-studio/deps/libcaption/examples/ts.c

118 lines
5.0 KiB
C

/**********************************************************************************************/
/* The MIT License */
/* */
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
/* of this software and associated documentation files (the "Software"), to deal */
/* in the Software without restriction, including without limitation the rights */
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
/* copies of the Software, and to permit persons to whom the Software is */
/* furnished to do so, subject to the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be included in */
/* all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
/* THE SOFTWARE. */
/**********************************************************************************************/
#include "ts.h"
#include <string.h>
void ts_init (ts_t* ts)
{
memset (ts,0,sizeof (ts_t));
}
static int64_t ts_parse_pts (const uint8_t* data)
{
// 0000 1110 1111 1111 1111 1110 1111 1111 1111 1110
uint64_t pts = 0;
pts |= (uint64_t) (data[0] & 0x0E) << 29;
pts |= (uint64_t) (data[1] & 0xFF) << 22;
pts |= (uint64_t) (data[2] & 0xFE) << 14;
pts |= (uint64_t) (data[3] & 0xFF) << 7;
pts |= (uint64_t) (data[4] & 0xFE) >> 1;
return pts;
}
int ts_parse_packet (ts_t* ts, const uint8_t* data)
{
size_t i = 0;
int pusi = !! (data[i + 1] & 0x40); // Payload Unit Start Indicator
int16_t pid = ( (data[i + 1] & 0x1F) << 8) | data[i + 2]; // PID
int adaption_present = !! (data[i + 3] & 0x20); // Adaptation field exist
int payload_present = !! (data[i + 3] & 0x10); // Contains payload
i += 4;
ts->data = 0;
ts->size = 0;
if (adaption_present) {
uint8_t adaption_length = data[i + 0]; // adaption field length
i += 1 + adaption_length;
}
if (pid == 0) {
if (payload_present) {
// Skip the payload.
i += data[i] + 1;
}
ts->pmtpid = ( (data[i + 10] & 0x1F) << 8) | data[i + 11];
} else if (pid == ts->pmtpid) {
// PMT
if (payload_present) {
// Skip the payload.
i += data[i] + 1;
}
uint16_t section_length = ( (data[i + 1] & 0x0F) << 8) | data[i + 2];
int current = data[i + 5] & 0x01;
int16_t program_info_length = ( (data[i + 10] & 0x0F) << 8) | data[i + 11];
int16_t descriptor_loop_length = section_length - (9 + program_info_length + 4); // 4 for the crc
i += 12 + program_info_length;
if (current) {
while (descriptor_loop_length >= 5) {
uint8_t stream_type = data[i];
int16_t elementary_pid = ( (data[i + 1] & 0x1F) << 8) | data[i + 2];
int16_t esinfo_length = ( (data[i + 3] & 0x0F) << 8) | data[i + 4];
if (0x1B == stream_type) {
ts->avcpid = elementary_pid;
}
i += 5 + esinfo_length;
descriptor_loop_length -= 5 + esinfo_length;
}
}
} else if (payload_present && pid == ts->avcpid) {
if (pusi) {
// int data_alignment = !! (data[i + 6] & 0x04);
int has_pts = !! (data[i + 7] & 0x80);
int has_dts = !! (data[i + 7] & 0x40);
uint8_t header_length = data[i + 8];
if (has_pts) {
ts->pts = ts_parse_pts (&data[i + 9]);
ts->dts = has_dts ? ts_parse_pts (&data[i + 14]) : ts->pts;
}
i += 9 + header_length;
}
ts->data = &data[i];
ts->size = TS_PACKET_SIZE-i;
return LIBCAPTION_READY;
}
return LIBCAPTION_OK;
}