TS流packet header 分析
TS流packet header 分析
TS流 188字节
每个包中 4字节的header 和184字节的data
-
sync_byte 8bits 的同步字节 ;____(sync_byte = 01000111 十六进制固定为0x47)
-
tport_error_indicator 1bits 的错误指示信息;____ ( 设置为1 表示该TS 包存在错误)
-
payload_unit_start_indicator 1bits 的负载单元开始标志(packet不满188字节时需填充) ;_____* 当传输流包有效荷载包含PSI分段首字节时 值必须为1,不包含设置为0, 空包必须设置为0*当传输流包有效载荷包含 PES 包数据时, payload_unit_start_indicator 具有以下意义:‘ 1 ’指示此传输
流包的有效载荷应随着 PES 包的首字节开始,‘ 0 ’指示在此传输流包中无任何 PES 包将开始。若
payload_unit_start_indicator 设置为‘ 1 ’,则一个且仅有一个 PES 包在此传输流包中起始。这也适用于
stream_type 6 的专用流
当传输流包有效载荷包含 PSI 数据时, payload_unit_start_indicator 具有以下意义:若传输流包承载 PSI
分段的首字节,则 payload_unit_start_indicator 值必为 1 ,指示此传输流包的有效载荷的首字节承载
pointer_field 。若传输流包不承载 PSI 分段的首字节,则 payload_unit_start_indicator 值必为‘ 0 ’,指示在此
有效载荷中不存在 pointer_field 。这也适用于 stream_type 5 的专用流
对空包而言, payload_unit_start_indicator 必须设置为‘ 0 ’。
仅承载专用数据的传输流包的此比特含义在本规范中未定义。 (不看其上 意义其实就是当一段数据超过一个包的大小必须分成几个包,第一个包的这个标志为1,其他包为0. ) -
transport_priority 1bits 的传输优先级标志
-
PID 13bits Packet ID号码,唯一的号码对应不同的包;_____PID决定packet data的内容 见下图1-1
-
transport_scrambling_control 2bits 的加密标志____(00表示未加密,其他加密)
-
adaptation_field_control 2bits 的附加区域控制____(*用来指示传输流首部是否跟随有调整字段或有效净荷。为00时表示保留;为01时表示没有调整字段,有效净荷长度为184B;为10时表示没有有效净荷,仅仅含有183B长度的调整字段;为11时表示有调整字段和有效净荷。)continuity_counter — continuity_counter 为 4 比特字段,随着具有相同 PID 的每个传输流包而增加。
continuity_counter 在取其最大值之后循环返回到 0 值。当包的 adaptation_field_control 为‘ 00 ’或‘ 10 ’时,
continuity_counter 不增加。
传输流中,复制包可以作为 2 个并且仅只作为 2 个具有相同 PID 的连续传输流包。该复制包必须有
与原始包相同的 continuity_counter 赋值并且 adaptation_field_control 字段必须等于‘ 01 ’或‘ 11 ’。复制
包中,原始包的每个字节都必须复制,有一种情况除外,即节目时钟参考字段中的内容若存在,该有效值必须编码。特定传输流包中 continuity_counter 是连续的,只要它与具有相同 PID 的先前的传输流包中的continuity_counter 赋值的差为正值 1 ,或者任意一个非增量条件( adaptation_field_control 设置为‘ 00 ’或
‘ 10 ’,或如上所述的复制包)被满足时。 discontinuity_indicator 设置为‘ 1 ’时,连续性计数器可以中断,在空包的情况中, continuity_counter 值未确定。
** 目前只用到0x3 和 0x1,分别表示有和没有自适应区域 -
continuity_counter 4bits 的包递增计数器_____(它随着PID相同的TS包的增加而增加,到达最大值后从0重新计数,但是当适应域控制位为“00”或者“10”时,连续计数器是不增加的。)
PAT 表分析
PAT表定义
typedef struct TS_PAT_Program
{
unsigned program_number :16; //节目号
unsigned program_map_PID :13; //节目映射表的PID,节目号大于0时对应的PID,每个节目对应一个
}TS_PAT_Program;
PAT 实例
PAT结构表
PAT段的数据结构:
Program_association_section()
{
Table_id 8bits PAT固定为0x00
Section_syntax_indicator 1bits 段语法标志位固定为1
‘0’ 1bits 值为0
Reserved 2bits 保留位 值为11
Section_length 12bits 段长度,头两位为00,值不超过1021,表示这个字节后面有用的字节数,包括CRC32;节目套数:(section length -9)/4
Transport_stream_id 16bits 传输流的ID ,TS的识别号,区别与同一个网络中的其他多路复用流
Reserved 2bits 保留位 ,值为11
Version_number 5bits PAT的版本号 范围0-31 见下图1
Current_next_indicator 1bits 若为1当前传送的PAT表可以使用,若为0则要等待下一个表
section_number 8bits 分段的号码。PAT可能分为多段传输,第一段为0x00,以后每个分段加1,最多可能有256个分段
Last_section_number 8bits 最后一个分段的号码
For(i=0;i<N;i++)
{
Program_number 16bits 节目号,16位,指定了Program_map_PID可用的节目。若其值为0x0000,则接下来的13bits的PID是network_PID,否则为program_map_PID
Reserved 3bits 保留位 值为111
If(program_number== ‘0’)
{
Network_id 13bits 指定了包含NIT的TS包的PID,其值由用户定义见:https://www.onelib.biz/doc/stb/appendix/ts.html#part5_1
}
Else
{
Program_map_PID 13bits 指定了TS包的PID,这些TS包包含由program_number指定的program_map_section,其值由用户定义
}
}
CRC_32 32
}
PAT表代码分析
HRESULT CTS_Stream_Parse::adjust_PAT_table( TS_PAT * packet, unsigned char * buffer)
{
packet->table_id = buffer[0];
packet->section_syntax_indicator = buffer[1] >> 7;
packet->zero = buffer[1] >> 6 & 0x1;
packet->reserved_1 = buffer[1] >> 4 & 0x3;
packet->section_length = (buffer[1] & 0x0F) << 8 | buffer[2];
packet->transport_stream_id = 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];
int len = 0;
len = 3 + packet->section_length;
packet->CRC_32 = (buffer[len-4] & 0x000000FF) << 24
| (buffer[len-3] & 0x000000FF) << 16
| (buffer[len-2] & 0x000000FF) << 8
| (buffer[len-1] & 0x000000FF);
int n = 0;
for ( n = 0; n < packet->section_length - 12; n += 4 )
{
unsigned program_num = buffer[8 + n ] << 8 | buffer[9 + n ];
packet->reserved_3 = buffer[10 + n ] >> 5;
packet->network_PID = 0x00;
if ( program_num == 0x00)
{
packet->network_PID = (buffer[10 + n ] & 0x1F) << 8 | buffer[11 + n ];
TS_network_Pid = packet->network_PID; //记录该TS流的网络PID
TRACE(" packet->network_PID %0x /n/n", packet->network_PID );
}
else
{
TS_PAT_Program PAT_program;
PAT_program.program_map_PID = (buffer[10 + n] & 0x1F) << 8 | buffer[11 + n];
PAT_program.program_number = program_num;
packet->program.push_back( PAT_program );
TS_program.push_back( PAT_program );//向全局PAT节目数组中添加PAT节目信息
}
}
return 0;
}
47 40 00 10 00 00 B0 0D 00 01 C1 00 00 00 01 F0 00 2A B1 04 B2 FF FF FF
过滤PAT 表信息的伪代码
int Video_PIO = 0x07e5,Audio_PIO = 0x07e6;
void Process_Packet(unsigned char *buff)
{
int i;
int PID = GETPID(buff);
if(PID == 0x0000)
{
Process_PAT(buff+4); // 如果PID为0x0000,则该Packet Data为PAT信息,因此调用处理PAT表的函数 .
} // 这里buff+4 意味着从Packet Header之后进行解析(包头占4个字节)
else
{
.......
}
}
PMT
参考:
https://www.zhiting.me/2018/03/ts流格式解析/
https://www.onelib.biz/doc/stb/appendix/ts.html#part5_1
https://www.onelib.biz/doc/stb/appendix/psisitable.html#pat
https://www.cnblogs.com/jiayayao/p/6832614.html
上一篇: 矢量量化算法
下一篇: MacOS 校验iso sha256值