PMT structure definition:
Typedef struct ts_pmt_stream
{
Unsigned stream_type: 8; // indicates the type of the program element package of a specific PID. The PID is specified by elementary PID.
Unsigned elementary_pid: 13; // This field indicates the PID value of the TS package. These ts contain related program elements.
Unsigned es_info_length: 12; // The first two bits are 00. This field indicates the number of bytes that follow the description of related program elements
Unsigned descriptor;
} Ts_pmt_stream;
// PMT table structure
Typedef struct ts_pmt
{
Unsigned table_id: 8; // fixed to 0x02, indicating the PMT table
Unsigned section_syntax_indicator: 1; // fixed to 0x01
Unsigned zero: 1; // 0x01
Unsigned reserved_1: 2; // 0x03
Unsigned section_length: 12; // first, the two bits are set to 00, which indicates the number of bytes of the segment, starting from the segment length field, including CRC.
Unsigned program_number: 16; // indicates that the program corresponds to the applicable Program Map PID.
Unsigned reserved_2: 2; // 0x03
Unsigned version_number: 5; // indicates the version number of the Program Map section in the TS stream.
Unsigned current_next_indicator: 1; // when this position is 1, the current program map section is available;
// When this position is 0, it indicates that the currently transmitted Program Map section is unavailable, and the Program Map section of the next TS stream is valid.
Unsigned section_number: 8; // fixed to 0x00
Unsigned last_section_number: 8; // fixed to 0x00
Unsigned reserved_3: 3; // 0x07
Unsigned pcr_pid: 13; // specify the PID value of the TS package, which contains the PCR domain,
// The PCR value corresponds to the program specified by the program number.
// If the program definition for private data streams is not related to PCR, the value of this field will be 0x1fff.
Unsigned reserved_4: 4; // reserved for 0x0f
Unsigned program_info_length: 12; // The first two bits are 00. This field specifies the number of bytes that follow the program description.
STD: vector <ts_pmt_stream> pmt_stream; // each element contains eight bits, indicating the type of the program element package of a specific PID. The PID is specified by elementary PID.
Unsigned reserved_5: 3; // 0x07
Unsigned reserved_6: 4; // 0x0f
Unsigned crc_32: 32;
} Ts_pmt;
The parsing code is:
Hresult cts_stream_parse: adjust_pmt_table (ts_pmt * packet, unsigned char * buffer)
{
Packet-> table_id = buffer [0];
Packet-> section_syntax_indicator = buffer [1]> 7;
Packet-> zero = buffer [1]> 6 & 0x01;
Packet-> reserved_1 = buffer [1]> 4 & 0x03;
Packet-> section_length = (buffer [1] & 0x0f) <8 | buffer [2];
Packet-> program_number = buffer [3] <8 | buffer [4];
Packet-> reserved_2 = buffer [5]> 6;
Packet-> version_number = buffer [5]> 1 & 0x1f;
Packet-> current_next_indicator = (buffer [5] <7)> 7;
Packet-> section_number = buffer [6];
Packet-> last_section_number = buffer [7];
Packet-> reserved_3 = buffer [8]> 5;
Packet-> pcr_pid = (buffer [8] <8) | buffer [9]) & 0x1fff;
Pcrid = packet-> pcr_pid;
Packet-> reserved_4 = buffer [10]> 4;
Packet-> program_info_length = (buffer [10] & 0x0f) <8 | buffer [11];
// Get crc_32
Int Len = 0;
Len = packet-> section_length + 3;
Packet-> crc_32 = (buffer [len-4] & 0x000000ff) <24
| (Buffer [len-3] & 0x000000ff) <16
| (Buffer [len-2] & 0x000000ff) <8
| (Buffer [len-1] & 0x000000ff );
Int Pos = 12;
// Program info Descriptor
If (packet-> program_info_length! = 0)
Pos + = packet-> program_info_length;
// Get stream type and PID
For (; POS <= (packet-> section_length + 2)-4 ;)
{
Ts_pmt_stream pmt_stream;
Pmt_stream.stream_type = buffer [POS];
Packet-> reserved_5 = buffer [POS + 1]> 5;
Pmt_stream.elementary_pid = (buffer [POS + 1] <8) | buffer [POS + 2]) & 0x1fff;
Packet-> reserved_6 = buffer [POS + 3]> 4;
Pmt_stream.es_info_length = (buffer [POS + 3] & 0x0f) <8 | buffer [POS + 4];
Pmt_stream.descriptor = 0x00;
If (pmt_stream.es_info_length! = 0)
{
Pmt_stream.descriptor = buffer [POS + 5];
For (INT Len = 2; Len <= pmt_stream.es_info_length; Len ++)
{
Pmt_stream.descriptor = pmt_stream.descriptor <8 | buffer [POS + 4 + Len];
}
Pos + = pmt_stream.es_info_length;
}
Pos + = 5;
Packet-> pmt_stream.push_back (pmt_stream );
Ts_stream_type.push_back (pmt_stream );
}
Return 0;
}
Example:
0x47 0x43 0xe8 0x12 0x00 0x02 0xb0 0x12 0x00 0x01 0xc1 0x00 0x00 0xe3 0xe9 0xf0 0x00 0x1b 0xe3 0xf0 0x00 0xf0 0xaf 0xb4 0x4f 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0000000000000000000000000000000000000xff 0xff 0xff 0x0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0000000000000000000000000000000000000xff 0xff 0xff 0x0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0000000000000000000000000000000000000xff 0xff 0xff 0x0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
TS Header
Sync_byte: 0x47
Transport_error_indicator: 0x00
Payload_unit_start_indicator: 0x01
Transport_priority: 0x00
PID: 0x03e8
Transport_scrambling_control: 0x00
Adaptation_field_control: 0x01
Continuity_counter: 0x02
PMT data
Table_id: 0x02 // 8
Section_syntax_indicator: 0x01 // 1
'0': 0x00 // 1
Reserved: 0x03 // 2
Section_length: 0x012 // 12
Program_number: 0x00 01 // 16
Reserved: 0x03 // 2
Version_number: 0x00 // 5
Current_next_indicator 0x01 // 1
Section_number: 0x00 // 8
Last_section_number: 0x00 // 8
Reserved 0x07 // 3
Pcr_pid: 0x03 E9 // PID of the TS group where the PCR (program reference clock) is located // 13
Reserved: 0x0f // 4
Program_info_length: 0x000 // 12
Stream_type: 0x1b // 8
Reserved 0x07 // 3
Elementary_pid: 0x03 E9 // 13 // PID of the TS group corresponding to the video stream and audio stream included in the program
Reserved: 0x0f // 4
Es_info_length: 0x000 // 12
CRC: 0xf0 af B4 4f