PMT(Program Map Table):節目映射表,該表的PID是由PAT提供給出的。通過該表可以得到一路節目中包含的信息,例如,該路節目由哪些流構成和這些流的類型(視頻,音頻,數據),指定節目中各流對應的PID,以及該節目的PCR所對應的PID。
PMT表中包含的數據如下:
(1) 當前頻道中包含的所有Video數據的PID
(2) 當前頻道中包含的所有Audio數據的PID
(3) 和當前頻道關聯在一起的其他數據的PID(如數字廣播,數據通訊等使用的PID)
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;
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;
解析代碼:
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流的一個pachet:
包頭:47 41 00 10
數據: 00 02 b0 29 00 01 c1 00 00 f001 f0 0c 05 04 48 44 4d 56 88 04 0f ff fc fc 1b f0 11 f0 06 28 04 42 c028 bf 90 f2 00 f0 00 f8 d6 bd 6b
先分析包頭:
第一個的包頭爲47 40 00 10,比較可知只是PID不同
它的PID爲0x100,即爲256
所以第二個包的數據表示的是PMT
再分析具體數據:
同理第一個字節00是調整字節
02 b0 29 00 01 c1 00 00 f001 f0 0c 05 04 48 44 4d 56 88 04 0f ff fc fc 1b f0 11 f0 06 28 04 42 c028 bf 90 f2 00 f0 00 f8 d6 bd 6b
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個字節 |
02 b0 29 00 01 c1 00 00 f0 01 f0 0c 05 04 48 44 4d 5688 04 0f ff fc fc 1b f0 11 f0 06 28 04 42 c0 28 bf 90 f200 f0 00 f8 d6 bd 6b
table_id爲02,對於PMT必須爲0x02
b0 29二進制爲1011 0000 0010 1001
section_syntax_indicator爲1,對於PMT必須爲1
section_length爲0x029,即爲32+9=41
00 01
program_number爲0x0001
c1二進制爲1100 0001
version_number爲00000
current_next_indicator爲1,表示當前傳送的program_map_section可用
00 00
分別表示section_number和last_section_number
f0 01二進制爲1111 0000 0000 0001
PCR_PID爲0x1001,即爲2的12次方+1=4097,該字段只是TS包的PID值
f0 0c二進制爲11110000 0000 1100
program_info_length爲0x00c,即爲12