您的位置:首页 > 产品设计 > 产品经理

TS协议解析第二部分(PMT)

2016-06-05 17:07 585 查看
1. PMT:

PMT(Program Map Table):节目映射表,该表的PID是由PAT提供给出的。通过该表可以得到一路节目中包含的信息,例如,该路节目由哪些流构成和这些流的类型(视频,音频,数据),指定节目中各流对应的PID,以及该节目的PCR所对应的PID。

PMT表中包含的数据如下:

(1) 当前频道中包含的所有Video数据的PID
(2) 当前频道中包含的所有Audio数据的PID
(3) 和当前频道关联在一起的其他数据的PID(如数字广播,数据通讯等使用的PID)

2. 分析MPT包:
2.1 PMT包数据:




2.2 包头:

TS包头只有4个字节(47 60 81 10),除掉第一个字节0x47,剩下就3个,重新分组如下:

0    1    1  0000010000001    00    01    0000

sync_byte

同步字节

0x47:

transport_error_indicator

传输错误标识

0:

payload_unit_start_indicator

负载单元开始标识

1:

transport_priority

传输优先级

1:

pid

PID

0x81:因为在PAT中查找到program_map_PID为0x81,因此就查找到PMT。

transport_scrambling_control

传输扰乱控制

00:

adaptation_field_control

自适应区域控制

01:

00:是保留值。
01:负载中只有有效载荷。
10:负载中只有自适应字段。
11:先有自适应字段,再有有效载荷。

continuity_counter

连续计数器

0x0:

2.3 TS包:


1) 在payload_unit_start_indicator为1时,在前4个字节后会有一个调整字节。所以实际数据应该为去除第一个字节00后的数据。(47 60 81 10 00 02
B0 17 00 01 C1 00 00 E8 10 F0 00 1B E8 10 F0 00 03 E8 14 F0 00 66 74 A4 2D)




2) 02 B0 17:0000 0010 1011 0000 0001 0111

section_length:23 (47
60 81 10 00 02 B0 17 00 01 C1 00 00 E8 10
F0 00 1B E8 10 F0 00 03 E8 14 F0 00 66 74 A4 2D)


3)

00 01:0000 0000 0000 0001

C1:1100 0001

00 00:0000 0000 0000 0000

E8 10:1110 1000 0001 0000

F0 00:1111 0000 0000 0000

1B E8 10 F0 00:0001 1011 1110 1000 0001 0000 1111 0000 0000 0000

03 E8 14 F0 00:0000 0011 1110 1000 0001 0100 1111 0000 0000 0000

[align=center]
[/align]

table_id
0x02:对于PMT,该字段置为0x02
section_syntax_indicator
1:对于PMT,该字段置为1
0
0:
reserved
11:
section_length
0000 0001 0111:前两位置为00,该字段指示分段的字节数,由分段长度字段开始,包括CRC,其值不超过1021。
Program_number
0x 00 01:对应于PAT中的Program_nmuber。
reserved
11:
version_number
00000:该字段指出了TS中program_map_section的版本号。
current_next_indicator
1:当该字段置为1时,表示当前传送的program_map_section可用;当该字段置0时,表示当前传送的program_map_section不可用,下一个TS的program_map_section有效。
section_number
0x00:section_number:该字段值总是置0x00
last_section_number
0x00:该字段值总是置0x00
reserved
111:
PCR_PID
0x810:该字段指示TS包的PID值。该TS包含有PCR字段,而PCR值对应于有节目好指定的节目。
reserved
1111:
Program_info_length
0x000:
stream_type
1B:表示这个流时h264格式的,通俗点就是视频
reserved
111:
Elementary_pid
0x810:表示PID时810的TS包就是用来装h264数据的
reserved
1111:
es_info_length
0x000:
Stream_type:
0x03:
reserved:
111:
Elementary_pid
0x814
reserved
1111:
Es_info_lenth
0x000:
Crc_32
0x 03 E8 14 F0 00:
PMT

table_id
8
1个字节
section_syntax_indicator
1
 
2个字节
‘0’
1
reserved
2
section_length
12
program_number
16
2个字节
reserved
2
 
1个字节
version_number
5
current_next_indicator
1
section_number
8
1个字节
last_section_number
8
1个字节
reserved
3
 
2个字节
PCR_PID
13
reserved
4
2个字节
program_info_length
12
循环:descriptor()(0-N)
循环开始(0-N1)
stream_type
8
1个字节
reserved
3
2个字节
elementary_PID
13
reserved
4
2个字节
ES_info_length
12
循环:descriptor()(0-N2)
循环结束
CRC_32
32
4个字节
[align=center]
[/align]
3. 实现:
3.1 PMT表格定义如下:
typedef struct TS_PMT_Stream
{
unsigned stream_type : 8; //指示特定PID的节目元素包的类型。该处PID由elementary PID指定
unsigned elementary_PID : 13; //该域指示TS包的PID值。这些TS包含有相关的节目元素
unsigned ES_info_length : 12; //前两位bit为00。该域指示跟随其后的描述相关节目元素的byte数
unsigned descriptor;
}TS_PMT_Stream;



3.2 PMT表结构体:
typedef struct TS_PMT
{
unsigned table_id                   : 8; //固定为0x02, 表示PMT表
unsigned section_syntax_indicator    : 1; //固定为0x01
unsigned zero                       : 1; //0x01
unsigned reserved_1                 : 2; //0x03
unsigned section_length : 12;//首先两位bit置为00,它指示段的byte数,由段长度域开始,包含CRC
unsigned program_number             : 16;// 指出该节目对应于可应用的Program map PID
unsigned reserved_2                 : 2; //0x03
unsigned version_number             : 5; //指出TS流中Program map section的版本号
unsigned current_next_indicator  : 1; //当该位置1时,当前传送的Program map section可用
//当该位置0时,指示当前传送的Program map section不可用,下一个TS流的Program map section有效
unsigned section_number            : 8; //固定为0x00
unsigned last_section_number      : 8; //固定为0x00
unsigned reserved_3               : 3; //0x07
nsigned PCR_PID                   : 13; //指明TS包的PID值,该TS包含有PCR域,
//该PCR值对应于由节目号指定的对应节目,如果对于私有数据流的节目定义与PCR无关,这个域的值将为0x1FFF。
unsigned reserved_4            : 4;  //预留为0x0F
unsigned program_info_length  : 12; //前两位bit为00。该域指出跟随其后对节目信息的描述的byte数。

std::vector<TS_PMT_Stream> PMT_Stream;  //每个元素包含8位, 指示特定PID的节目元素包的类型。该处PID由elementary PID指定
unsigned reserved_5                : 3; //0x07
unsigned reserved_6                : 4; //0x0F
unsigned CRC_32                    : 32;
} TS_PMT;


3.3 解析代码:
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ts pmt