Older/MediaServer/libmpeg/source/mpeg-pes.c
amass 08340ad5c8
All checks were successful
Deploy / PullDocker (push) Successful in 11s
Deploy / Build (push) Successful in 1m54s
add codec.
2024-09-30 16:12:57 +00:00

324 lines
8.2 KiB
C

// ITU-T H.222.0(10/2014)
// Information technology - Generic coding of moving pictures and associated audio information: Systems
// 2.4.3.6 PES packet(p51)
#include "mpeg-pes-internal.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
/// @return 0-error, other-pes header length
int pes_read_header(struct pes_t *pes, struct mpeg_bits_t* reader)
{
uint8_t v8;
uint16_t v16;
uint32_t v32;
size_t end;
//pes->sid = mpeg_bits_read8(reader);
pes->len = mpeg_bits_read16(reader);
v8 = mpeg_bits_read8(reader);
//assert(0x02 == ((v8 >> 6) & 0x3));
pes->PES_scrambling_control = (v8 >> 4) & 0x3;
pes->PES_priority = (v8 >> 3) & 0x1;
pes->data_alignment_indicator = (v8 >> 2) & 0x1;
pes->copyright = (v8 >> 1) & 0x1;
pes->original_or_copy = v8 & 0x1;
v8 = mpeg_bits_read8(reader);
pes->PTS_DTS_flags = (v8 >> 6) & 0x3;
pes->ESCR_flag = (v8 >> 5) & 0x1;
pes->ES_rate_flag = (v8 >> 4) & 0x1;
pes->DSM_trick_mode_flag = (v8 >> 3) & 0x1;
pes->additional_copy_info_flag = (v8 >> 2) & 0x1;
pes->PES_CRC_flag = (v8 >> 1) & 0x1;
pes->PES_extension_flag = v8 & 0x1;
pes->PES_header_data_length = mpeg_bits_read8(reader);
if (pes->len > 0 && pes->len < pes->PES_header_data_length + 3)
return MPEG_ERROR_INVALID_DATA; // skip invalid packet
end = mpeg_bits_tell(reader) + pes->PES_header_data_length;
if (mpeg_bits_error(reader) || end > mpeg_bits_length(reader))
return MPEG_ERROR_NEED_MORE_DATA;
if (0x02 & pes->PTS_DTS_flags)
{
v8 = mpeg_bits_read8(reader);
//assert(0x20 == (v8 & 0x20));
pes->pts = ((((uint64_t)v8 >> 1) & 0x07) << 30) | mpeg_bits_read30(reader);
}
//else
//{
// pes->pts = PTS_NO_VALUE;
//}
if (0x01 & pes->PTS_DTS_flags)
{
v8 = mpeg_bits_read8(reader);
//assert(0x10 == (v8 & 0x10));
pes->dts = ((((uint64_t)v8 >> 1) & 0x07) << 30) | mpeg_bits_read30(reader);
}
else if(0x02 & pes->PTS_DTS_flags)
{
// has pts
pes->dts = pes->pts;
}
//else
//{
// pes->dts = PTS_NO_VALUE;
//}
if (pes->ESCR_flag)
{
v32 = mpeg_bits_read32(reader);
v16 = mpeg_bits_read16(reader);
pes->ESCR_base = (((uint64_t)((v32 >> 27) & 0x07)) << 30) | (((uint64_t)((v32 >> 11) & 0x7FFF)) << 15) | (((uint64_t)(v32 & 0x3FF)) << 5) | ((uint64_t)(v16 >> 11) & 0x1F);
pes->ESCR_extension = (v16 >> 1) & 0x1FF;
}
if (pes->ES_rate_flag)
{
pes->ES_rate = (mpeg_bits_read8(reader) & 0x7F) << 15;
pes->ES_rate |= mpeg_bits_read15(reader);
}
if (pes->DSM_trick_mode_flag)
{
// TODO:
//mpeg_bits_skip(reader, 1);
}
if (pes->additional_copy_info_flag)
{
//mpeg_bits_skip(reader, 1);
}
if (pes->PES_CRC_flag)
{
//mpeg_bits_skip(reader, 2);
}
if (pes->PES_extension_flag)
{
}
if (pes->len > 0)
{
if (pes->len < pes->PES_header_data_length + 3)
return MPEG_ERROR_INVALID_DATA; // skip invalid packet
pes->len -= pes->PES_header_data_length + 3;
}
assert(pes->len >= 0); // TS pes->len maybe 0(payload > 65535)
mpeg_bits_seek(reader, end);
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? MPEG_ERROR_INVALID_DATA : MPEG_ERROR_OK;
}
/// @return 0-error, pes header length
size_t pes_write_header(const struct pes_t *pes, uint8_t* data, size_t bytes)
{
uint8_t len = 0;
uint8_t flags = 0x00;
uint8_t *p = NULL;
if (bytes < 9) return 0; // error
// packet_start_code_prefix 0x000001
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x01;
data[3] = pes->sid;
// skip PES_packet_length
//data[4] = 0x00;
//data[5] = 0x00;
// '10'
// PES_scrambling_control '00'
// PES_priority '0'
// data_alignment_indicator '1'
// copyright '0'
// original_or_copy '0'
data[6] = 0x80;
if(pes->data_alignment_indicator)
data[6] |= 0x04;
//if (IDR | subtitle | raw data)
//data[6] |= 0x04;
// PTS_DTS_flag 'xx'
// ESCR_flag '0'
// ES_rate_flag '0'
// DSM_trick_mode_flag '0'
// additional_copy_info_flag '0'
// PES_CRC_flag '0'
// PES_extension_flag '0'
if(PTS_NO_VALUE != pes->pts)
{
flags |= 0x80; // pts
len += 5;
}
assert(PTS_NO_VALUE == pes->dts || pes->pts == pes->dts || PES_SID_VIDEO == data[3]); // audio PTS==DTS
if(PTS_NO_VALUE != pes->dts /*&& PES_SID_VIDEO==(PES_SID_VIDEO&data[3])*/ && pes->dts != pes->pts)
{
flags |= 0x40; // dts
len += 5;
}
data[7] = flags;
// PES_header_data_length : 8
data[8] = len;
if ((size_t)len + 9 > bytes)
return 0; // error
p = data + 9;
if(flags & 0x80)
{
*p++ = ((flags >> 2) & 0x30)/* 0011/0010 */ | (((pes->pts >> 30) & 0x07) << 1) /* PTS 30-32 */ | 0x01 /* marker_bit */;
*p++ = (pes->pts >> 22) & 0xFF; /* PTS 22-29 */
*p++ = ((pes->pts >> 14) & 0xFE) /* PTS 15-21 */ | 0x01 /* marker_bit */;
*p++ = (pes->pts >> 7) & 0xFF; /* PTS 7-14 */
*p++ = ((pes->pts << 1) & 0xFE) /* PTS 0-6 */ | 0x01 /* marker_bit */;
}
if(flags & 0x40)
{
*p++ = 0x10 /* 0001 */ | (((pes->dts >> 30) & 0x07) << 1) /* DTS 30-32 */ | 0x01 /* marker_bit */;
*p++ = (pes->dts >> 22) & 0xFF; /* DTS 22-29 */
*p++ = ((pes->dts >> 14) & 0xFE) /* DTS 15-21 */ | 0x01 /* marker_bit */;
*p++ = (pes->dts >> 7) & 0xFF; /* DTS 7-14 */
*p++ = ((pes->dts << 1) & 0xFE) /* DTS 0-6 */ | 0x01 /* marker_bit */;
}
return p - data;
}
// ISO/IEC 11172-1
// 2.4.3.3 Packet Layer (p20)
/*
packet() {
packet_start_code_prefix 24 bslbf
stream_id 8 uimsbf
packet_length 16 uimsbf
if (packet_start_code != private_stream_2) {
while (nextbits() == '1')
stuffing_byte 8 bslbf
if (nextbits () == '01') {
'01' 2 bslbf
STD_buffer_scale 1 bslbf
STD_buffer_size 13 uimsbf
}
if (nextbits() == '0010') {
'0010' 4 bslbf
presentation_time_stamp[32..30] 3 bslbf
marker_bit 1 bslbf
presentation_time_stamp[29..15] 15 bslbf
marker_bit 1 bslbf
presentation_time_stamp[14..0] 15 bslbf
marker_bit 1 bslbf
}
else if (nextbits() == '0011') {
'0011' 4 bslbf
presentation_time_stamp[32..30] 3 bslbf
marker_bit 1 bslbf
presentation_time_stamp[29..15] 15 bslbf
marker_bit 1 bslbf
presentation_time_stamp[14..0] 15 bslbf
marker_bit 1 bslbf
'0001' 4 bslbf
decoding_time_stamp[32..30] 3 bslbf
marker_bit 1 bslbf
decoding_time_stamp[29..15] 15 bslbf
marker_bit 1 bslbf
decoding_time_stamp[14..0] 15 bslbf
marker_bit 1 bslbf
}
else
'0000 1111' 8 bslbf
}
for (i = 0; i < N; i++) {
packet_data_byte 8 bslbf
}
}
*/
int pes_read_mpeg1_header(struct pes_t *pes, struct mpeg_bits_t* reader)
{
uint8_t v8;
size_t offset;
//pes->sid = mpeg_bits_read8(reader);
pes->len = mpeg_bits_read16(reader);
offset = mpeg_bits_tell(reader);
do
{
v8 = mpeg_bits_read8(reader);
} while (0 == mpeg_bits_error(reader) && v8 == 0xFF);
if (0x40 == (0xC0 & v8))
{
mpeg_bits_skip(reader, 2); // skip STD_buffer_scale / STD_buffer_size
v8 = mpeg_bits_read8(reader);
}
if (0x20 == (0xF0 & v8))
{
pes->pts = ((((uint64_t)v8 >> 1) & 0x07) << 30) | mpeg_bits_read30(reader);
}
else if (0x30 == (0xF0 & v8))
{
pes->pts = ((((uint64_t)v8 >> 1) & 0x07) << 30) | mpeg_bits_read30(reader);
v8 = mpeg_bits_read8(reader);
pes->dts = ((((uint64_t)v8 >> 1) & 0x07) << 30) | mpeg_bits_read30(reader);
}
else
{
assert(0x0F == v8);
}
if (mpeg_bits_error(reader))
return MPEG_ERROR_NEED_MORE_DATA;
offset = mpeg_bits_tell(reader) - offset;
if (pes->len > 0)
{
if (pes->len < offset)
return MPEG_ERROR_INVALID_DATA; // invalid data length
pes->len -= (uint32_t)offset;
}
assert(0 == mpeg_bits_error(reader));
return MPEG_ERROR_OK;
}
uint16_t mpeg_bits_read15(struct mpeg_bits_t* reader)
{
uint16_t v;
v = ((uint16_t)mpeg_bits_read8(reader)) << 7;
v |= (mpeg_bits_read8(reader) >> 1) & 0x7F;
return v;
}
uint32_t mpeg_bits_read30(struct mpeg_bits_t* reader)
{
uint32_t v;
v = ((uint32_t)mpeg_bits_read15(reader)) << 15;
v |= mpeg_bits_read15(reader);
return v;
}
uint64_t mpeg_bits_read45(struct mpeg_bits_t* reader)
{
uint64_t v;
v = ((uint64_t)mpeg_bits_read15(reader)) << 30;
v |= ((uint64_t)mpeg_bits_read15(reader)) << 15;
v |= mpeg_bits_read15(reader);
return v;
}