#MPEGTS
Name:苏荣 Data:2016/5/27 09:03:30
PSI 可以认为属于 6 个表: 1) 节目相关表(PAT) 2) TS 节目映射表(PMT) 3) 网络信息表(NIT) 4) 有条件访问表(CAT) 5) 传输流描述表 6) IPMP 控制信息表
##ES流(Elementary Stream):基本码流,不分段的音频、视频或其他信息的连续码流.
##PES流:把基本流ES分割成段,并加上相应头文件打包成形的打包基本码流
##PS流(Program Stream):节目流,将具有共同时间基准的一个或多个PES组合(复合)而成的单一数据流(用于播放或编辑系统,如m2p).
##TS流(Transport Stream):传输流,将具有共同时间基准或独立时间基准的一个或多个PES组合(复合)而成的单一数据流(用于数据传输).
##PES ES TS 视频压缩成H264码流,可以称之为ES流,将其每帧打包为PES流,然后分拆为多个188字节,称为TS流.
H264(ES) = PES1(一帧ES打包) + PES2(一帧ES打包) + PES3(一帧ES打包) + ...
PES1 = PES1 Header + PES1 Payload = PES1 Packet Start Code Prefix + Stream ID + PES1 Packet Length + Send PES1 Header(不确定大小) + PES1 Payload
PES1 Payload = TS1 Payload + TS2 Payload + TS3 Payload + ...
PES1 = TS1 + TS2 + TS3 + ....
PES1 = TS1(TS1 Header + PES1 Header + TS1 Payload) + TS2(有三种可能) + TS3(有三种可能) + ......
TS1(TS流第一个包) = TS1 Header + PES1 Header + TS1 Payload
TS2(TS流第二个包,第一种情况) = TS2 Header + 自适应字段 + TS2 Payload (出现概率 1%)
TS2(TS流第二个包,第二种情况) = TS2 Header + 自适应字段 (出现概率 0.1%)
TS2(TS流第二个包,第三种情况) = TS2 Header + TS2 Payload (出现概率 98.9%)
一段ES流 = N个PES(N帧)
同一个PES的TS的PID是相同的
##寻找第一个TS包 Header PID = 0x000 说明数据包是PAT表信息 第一个TS包 一般叫做 PAT (Program Association Table,节目相关表)
TS流 : PID=005 + PID=002 + PID=000
一般来说第一个TS包一般在第一个位置,本例举出一个特殊情况(第一个TS包在第三)
在寻找第一个TS包时,不断读取TS包,直到找到pid=000的位置,并将读取过的TS包置入缓冲区
##寻找下一个TS包 第二个TS包 一般叫做PMT(Program Map Table,节目映射表)
##解析TS包 payload_unit_start_indicator : 该字段用来表示TS包的有效净荷有PES包或者PSI数据的情况.
当TS包带有PES包数据时(出现概率99.9%).不带PES包(出现概率0.1%).
当TS包带有PES包数据时,payload_unit_start_indicator具有以下的特点: a. 置为1,标识TS包的有效净荷以PES包的第一个字节开始. b. 置为0,表示TS包的开始不是PES包.
当TS包带有PSI数据时,payload_unit_start_indicator具有以下特点: a. 置为1,表示TS包带有PSI部分的第一个字节,即第一个字节带有指针pointer_field. b. 置为0,表示TS包不带有一个PSI部分的第一个字节,即在有效净荷中没有指针point_field. c. 对于空包的包,payload_unit_start_indicator应该置为0
adaptionFieldControl: 01 -> 仅含有效负载(TS包第三种情况) 10 -> 仅含调整字段(TS包第二种情况) 11 -> 含有调整字段和有效负载(TS包第一种情况)
TS流,通过一个个的TS包来传送. TS包可以是传送PSI SI等各表的数据包,也可以是传送节目音视频数据(携带的PES包:音视频基本流包)的包;TS携带 PSI SI等表的数据时,各个表以各表对应的Section语法格式做为传输单元存放到TS包中 以便传输; TS包,有一个TS包的PID,系统就是根据这个PID来找对应的TS包;对于包含音视频数据(PES包)的TS包,系统通过TS的PID找到对应TS数据包,提取其中的数据组合成节目的音视频;对于携带PSI SI等数据的TS包,系统通过TS的PID找到对应TS数据包,提取各个PSI SI数据表格,用来指导系统;因此其中部分PID用来固定传输某些数据内容.
有了TS的PID后, 如果TS包携带的是PSI SI等表格的Section数据时,有时还不能确定该PID的TS包中携带的数据是什么,SDT BAT ST 等表传送时,都用的是PID为0X0011的TS数据包,对于这种携带PSI SI Section单元的TS包,对应的数据(表的Section语法中)还有一个 TABLE_ID字段,用来可以确定是具体的什么表
因此PID+TableID就可以确定负载带了什么,是PES还是PSI.
包头 : 47 60 00 10 0x47 : syncByte 0x6 : 0110(这里的最后一个字节,要给到下面),payload_unit_start_indicator = 1. 0x000 : 0 0000 0000 0000, pid = 0,说明是第一个TS包(PAT表) 0x10 : 0001 0000, adaptionFieldControl = 01,说明仅含有效负载(TS包第三种情况)
负载 : 00 00 B0 0D 00 00 C1 00 00 00 01 E0 81 0C 8C BE 32 FF FF......FF
指针 : 00 table id : 00 固定值 : B (1011) section_length : 0 0D(值:13) transport_stream_id : 00 00 version number & current_next_indicator : C1 section_number : 00 last_section_number : 00 program_number : 00 01 program_map_PID : E0 81(因为program_number > 0) CRC_32 : 0C 8C BE 32
if (program_number == 0)
{
network_PID
}else
{
program_map_PID
}
E0 81 = reserved3 + program_map_PID = | 1110 0000 | 1000 0001 | program_map_PID = 0x81(说明PMT的pid为081)
包头 : 47 60 81 10 0x47 : syncByte 0x6 : 0110(这里的最后一个字节,要给到下面),payload_unit_start_indicator = 1. 0x081 : 0 0000 1000 0001, pid = 0x081(说明是PMT表,因为前面的PAT表给出了) 0x10 : 0001 0000, adaptionFieldControl = 01,说明仅含有效负载(TS包第三种情况)
负载 : 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 FF FF FF FF FF......FF
指针 : 00 table id : 02 固定值 : B section_length : 0 17(值:23,表示到后面FF FF FF FF FF FF之前总共有23个字节) program_number : 00 01 reserved2 & version_number & current_next_indicator : C1 section_number : 00 last_section_number : 00 PCR_PID : E8 10 program_info_length : F0 00 前4位为保留位 后12位为描述信息长度 此处为0
第一流分析 : 1B E8 10 F0 00 stream_type : 1B 视频流(H264)(ITU-T H.264建议书| SO/IEC 14496-10 视频中定义的 AVC 视频流) elementary_PID : E8 10 前3位为保留位取后13位 则PID=810 表示此PID的都是视频流 ES_info_length : F0 00 前4位为保留位 后12位为描述信息长度 此处为0
第二流分析 : 03 E8 14 F0 00 stream_type : 03 音频流(MP3) elementary_PID : E8 14 前3位为保留位取后13位 则PID=814 表示此PID的都是音频流 ES_info_length : F0 00 前4位为保留位 后12位为描述信息长度 此处为0
CRC : 66 74 A4 2D
reserved4 + program_info_length = | 1111 0000 | 0000 0000 | program_info_length = 0
stream_type : 03 表示流是音频流 MP3 格式 814 表示 pid=814 的TS包存储的是MP3格式的音频流. stream_type : 01 表示流是视频流 h264格式 810 表示 pid=810 的TS包存储的是h264格式的视频流
这里: payload_unit_start_indicator = 1, 说明有效载荷起始符为1,含有PES包头 adaptionFieldControl = 01, 说明仅含有效负载(TS包第三种情况)
负载 : 00 00 01 C0 01 88 80 80 05 21 00 01 96 07 FF FD 85 00 33 22 22 11 22 11 11 11 11 11 11 24 82 41 00 90 40 00 00 00 00 00 40 00 ....... 70 34 5B CE 64 B7 D2 F5 4E 07 50 8E 11 1E 60 61 21 32 11 59
packetStartCodePrefix : 00 00 01 streamID : C0 pes_PacketLength : 01 88(值为392,占用392个字节,一帧数据长度,也可以置为0) Sned PES HEADER : 占用不确定位 本例为:80 80 05 21 00 01 96 07
Sned PES HEADER 包括以下几个字段: 80 80 05 21 00 01 96 07(解析为二进制显示) | 8 0 | 8 0 | 0 5 | 2 1 | 0 0 | 0 1 | 9 6 | 0 7 | | 1000 0000| 1000 0000 | 0000 0101 | 0010 0001 | 0000 0000 | 0000 0001 | 1001 0110 | 0000 1110 |
(注意,下面的数值是用二进制表示,不特别声明,都是用16进制表示) (0x80) constTen : 10 固定 PES_scrambling_control : 00 PES加扰控制 PES_priority : 0 PES 包中该有效载荷的优先级 data_alignment_indicator : 0 数据定位指示符 copyright : 0 PES 包有效载荷的素材依靠版权所保护 original_or_copy : 0 PES 包有效载荷的内容是原始的
(0x80) PTS_DTS_flags : 10 PES 包头中 PTS 字段存在 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
(0x05) PES_header_data_length : 0000 0101(值为5)PES头数据长度,表示后面还有5个字节,之后就是一帧的数据
(0x4200032C)(十进制:1107297068) PTS(presentation time stamp): 0010 0001 0000 0000 0000 0001 1001 0110 0
下面字段在本例中都没有: ESCR(42) = ESCR_base(33) + ESCR_extension(9) ES_rate(22) DSM特技方式(8) additional_copy_info(7) previous_PES_packet_CRC(16) PES_Extension(不确定)
因为 PTS_DTS_flags == 10,所以本例中只有PTS没有DTS.
注意 : 本TS包 包含PES头信息 说明开始下一帧
这里: payload_unit_start_indicator = 0, 说明有效载荷起始符为0,不含有PES包头 adaptionFieldControl = 01, 说明仅含有效负载(TS包第三种情况)
这里: payload_unit_start_indicator = 0, 说明有效载荷起始符为0,不含有PES包头 adaptionFieldControl = 11, 说明先有自适应字段,再有有效载荷(TS包第一种情况)
负载 : 99 00 FF FF FF ... FF 52 DE E6 B5 D0 76 CD CB B2 24 B3 92 AD 4E CD 19 D2 CC 82 D4 78 10 80 6C 0E 99 49 A4 59 C0
adaptation_field_length : 99(值为153,表示占用153个字节)
discontinuity_indicator & random_access_indicator & elementary_stream_priority_indicator & PCR_flag & OPCR_flag & splicing_point_flag & transport_private_data_flag & adaptation_field_extension_flag : 00 剩下的所有字段都为0
(00 FF FF FF ... FF)这里都是调整字段,从52 DE E6 B5 D0(从00(FF之前,99之后) 开始算是第1个字节,跳到第153个字节)开始,就是真正的帧数据了
这里: payload_unit_start_indicator = 1, 说明有效载荷起始符为1,含有PES包头 adaptionFieldControl = 01, 说明仅含有效负载(TS包第三种情况)
负载 : 00 00 01 C0 01 88 80 80 05 21 00 01 A6 E7 FF FD
packetStartCodePrefix : 00 00 01 streamID : C0 pes_PacketLength : 01 88(值为392,占用392个字节) Sned PES HEADER : 占用不确定位
所以本包数据流ID 和 第二个包的流ID是一样的
注意 : 本TS包 又包含PES头信息 说明开始下一帧
这里: payload_unit_start_indicator = 1, 说明有效载荷起始符为1,含有PES包头 adaptionFieldControl = 11, 说明含有调整字段和有效负载(TS包第一种情况)
负载 : 07 10 00 00 01 0F 7E 88 00 00 01 E0 00 00 80 C0 0A 31 00 01 96 07 11 00 01 7E 91 00 00 00 01 67 4D 40 1E 96 ...... D2 99 71 F3
adaptation_field_length : 07(值为7,表示占用153个字节)
discontinuity_indicator & random_access_indicator & elementary_stream_priority_indicator & PCR_flag & OPCR_flag & splicing_point_flag & transport_private_data_flag & adaptation_field_extension_flag : 10
(10 00 00 01 0F 7E 88)调整字段
packetStartCodePrefix : 00 00 01 streamID : EO pes_PacketLength : 00 00(值为0,占用0个字节,一帧数据长度,也可以置为0,此时需要自己去计算) Sned PES HEADER : 占用不确定位
这里: payload_unit_start_indicator = 0, 说明有效载荷起始符为0,不含有PES包头 adaptionFieldControl = 01, 说明仅含有效负载(TS包第三种情况)
总结这个八个包:
第一个TS包(PID:0X00) : 包含了PAT. 第二个TS包(PID:0X81) : 包含了PMT. 第三个TS包(PID:0x814) : 音频PES包头所有的TS包. 第四个TS包(PID:0x814) : 音频TS包. 第五个TS包(PID:0x814) : 音频TS包. 第六个TS包(PID:0x814) : 音频PES包头所有的TS包. 第七个TS包(PID:0x810) : 视频PES包头所有的TS包. 第八个TS包(PID:0x810) : 视频TS包.
// Packet Header: // PID是TS流中唯一识别标志,Packet Data是什么内容就是由PID决定的.如果一个TS流中的一个Packet的Packet Header中的PID是0x0000, // 那么这个Packet的Packet Data就是DVB的PAT表而非其他类型数据(如Video,Audio或其他业务信息).
// 分析一个Header: // 二进制: 0100 0111 0000 0111 1110 0101 0001 0010 // 十六进制: 4 7 0 7 e 5 1 2
// syncByte = 0x47 就是0x47,这是DVB TS规定的同步字节,固定是0x47 // transportErrorIndicator = 0 表示当前包没有发生传输错误 // payloadUnitStartIndicator = 0 具体含义参考ISO13818-1标准文档 // transportPriority = 0 表示当前包是低优先级 // pid = 0x07e5(0 0111 1110 0101) Video PID // transportScramblingControl = 00 表示节目没有加密 // adaptionFieldControl = 01 具体含义参考ISO13818-1标准文档 // continuityCounter = 0010 表示当前传送的相同类型的包是第3个
// 分析一段TS流:(PAT) // Packet Header : 0x47 0x40 0x00 0x10 // Packet Data : 00 00 b0 11 00 01 c1 00 00 00 00 e0 1f 00 01 e1 00 24 ac48 84 ff ff ... ff ff
// Header PID = 0x0000 说明数据包是PAT表信息,包头后需要除去一个字节才是有效数据(payload_unit_start_indicator="1") // 所以,Packet Data就应该是 : 00 b0 11 00 01 c1 00 00 00 00 e0 1f 00 01 e1 00 24 ac48 84 ff ff ... ff ff
// // 00 | b0 11 | 00 01 | c1 | 00 | 00 | 00 00 | e0 1f | 00 01 e1 00 | //
// table_id = 0000 0000
// section_syntax_indicator = 1 // zero = 0 // reserved1 = 11 // sectionLength = 0000 0001 0001
// transportStreamID = 0000 0000 0000 0001
// reserved2 = 11 // versionNumber = 0000 0 // currentNextIndicator 1
// sectionNumber = 0000 0000
// lastSectionNumber = 0000 0000
// programNumber = 0000 0000 0000 0000
// reserved3 = 111 // networkPID = 0 0000 0001 1111
// crc32
// 分析一段TS流:(PMT) // Packet Header : 0x47 0x43 0xe8 0x12 // Packet Data : 00 02 b0 12 00 01 c1 00 00 e3 e9 f0 00 1b e3 e9 f0 00 f0 af b4 4f ff ff ... ff ff
// Header PID = 0x03e8 说明数据包是PMT表信息,包头后需要除去一个字节才是有效数据(payload_unit_start_indicator="1") // 所以,Packet Data就应该是 : 02 b0 12 00 01 c1 00 00 e3 e9 f0 00 1b e3 e9 f0 00 f0 af b4 4f ff ff ... ff ff
// 1 2 3 4 5 6 7 8 9 10 11 12 // 02 | b0 12 | 00 01 | c1 | 00 | 00 | e3 e9 | f0 00 | 1b | e3 e9 | f0 00 | f0 af b4 4f | //
// 1: // table_id = 0000 0010
// 2: // section_syntax_indicator = 1 // zero = 0 // reserved1 = 11 // section_length = 0000 0001 0010
// 3: // program_number = 0000 0000 0000 0001
// 4: // reserved2 = 11 // version_number = 00 000 // current_next_indicator = 1
// 5: // section_number = 0000 0000
// 6: // last_section_number = 0000 0000
// 7: // reserved3 = 111 // PCR_PID = 0 0011 1110 1001
// 8: // reserved4 = 1111 // program_info_length = 0000 0000 0000
// 9: // stream_type = 0001 1011
// 10: // reserved5 = 111 // elementary_PID = 0 0011 1110 1001
// 11: // reserved6 = 1111 // ES_info_length = 0000 0000 0000
// 12: // crc
##TS流解码过程
##参考文档: