把Hls的流写成文件,分析其码流格式。
抓包如下:
写成文件格式:
用码流分析工具进行分析:
码流分为PSI,TS,PES,ES进行研究。
前面4个字节定义如下:
先取出4个字节进行分析吧
47 40 00 10
2进制如下:
0100 0111 0100 0000 0000 0000 0001 0000
sync_byte :0100 0111 ===》0x47 为固定8位
transport_error_indicator: 0
payload_unit_start_indicator:1 表示负载从第几个字节开始
transport_priority:0
PID:0 0000 0000 0000
transport_scrambling_control:00
adaptation_field_control:01
continuity_counter:0000
应为pid为0 表示这个ts包为节目关联表(pat),在看下节目关联表(pat)的定义:
*********************错误的码流*********************
上码流:
2进制:
0000 0000 0000 0000 1011 0000 0000 1101
0000 0000 0000 0001 1100 0001 0000 0000
0000 0000 0000 0000 0000 0001 1110 0001
0000 0000 1110 1000 1110 1001 0101 1110
0111 1101
table_id :00 固定为0x00 ,标志是该表是PAT
section_syntax_indicator:0 默认是1
reserved:0
section_length:176 表示这个字节后面有用的字节数,包括CRC32。假如后面的字节加上前面的字节数少于188,后面会用0XFF填充。假如这个数值比较大,则PAT会分成几部分来传输
transport_stream_id: 0x0d00 该传输流的ID
version_number:0
current_next_indicator:1
section_number:1100 0001
last_section_number:0000 0000
***********************end 错误的分析***************************
ts流包含格式如下:
PID为0的情况 :PAT节目关联表
上述的解析完全错误,我发现我犯了一个错误,就是不应该从第5个字节开始计算,而是应该从第6个自己计算,为什么呢?
因为 payload_unit_start_indicator:1 表示负载从负载的第二个字节开始,不是第一个字节。重新来过。
转成2进制如下:
0000 0000 1011 0000 0000 1101 0000 0000
0000 0001 1100 0001 0000 0000 0000 0000
0000 0000 0000 0001 1110 0001 0000 0000
1110 1000 1110 1001 0101 1110 0111 1101
able_id :00 固定为0x00 ,标志是该表是PAT
section_syntax_indicator:1 默认是1
reserved:11
section_length:13 表示这个字节后面有用的字节数,包括CRC32。假如后面的字节加上前面的字节数少于188,后面会用0XFF填充。假如这个数值比较大,则PAT会分成几部分来传输
transport_stream_id: 1 该传输流的ID
reserved:11
version_number:0
current_next_indicator:1
section_number:0
last_section_number:0
program_number:0000 0000 0000 0001
reserved:111
program_map_PID:0 0001 0000 0000
通过上述分析,得知下一个数据包应该是psi,PID为0x100
PMT分析:
上定义:
上码流:
前面5个字节无需解析,从第六个字节开始。开始先转成2进制,好分析一点
0000 0010 1011 0000 0001 0111 0000 0000
0000 0001 1100 0001 0000 0000 0000 0000
1110 0001 0000 0010 1111 0000 0000 0000
0000 1111 1110 0001 0000 0001 1111 0000
0000 0000 0001 1011 1110 0001 0000 0010
1111 0000 0000 0000 0010 0100 1110 0001
1111 1101 1101 0000
table_id:0000 0010 固定为0x02 ,标志是该表是PMT。
section_syntax_indicator:1
'0':0
reserved:11
section_length:0000 0001 0111
program_number:0000 0000 0000 0001 节目号,表示该PMT对应的节目
reserved:11
version_number:00 000
current_next_indicator:1
section_number:0000 0000
last_section_number:0000 0000
reserved:111
PCR_PID:0 0001 0000 0010 (节目时钟参考)所在TS分组的PID,根据PID可以去搜索相应的TS分组,解出PCR信息。
reserved 4:1111
program_info_length: 0000 0000 0000 该节目的信息长度,在此字段之后可能会有一些字节描述该节目的信息
stream_type:0000 1111 0x0F 表示AAC音频 指示了PID为elementary_PID的PES分组中原始流的类型,比如视频流,音频流等,
reserved:111
elementary_PID:0 0001 0000 0001 该节目中包括的视频流,音频流等对应的TS分组的PID
reserved:1111
ES_info_length:0000 0000 0000 该节目相关原始流的描述符的信息长度
stream_type:0001 1011 0x1B 表示H264视频
reserved:111
elementary_PID:0 0001 0000 0010
reserved:1111
ES_info_length:0000 0000 0000
CRC_32:0010 0100 1110 0001 1111 1101 1101 0000
PES分析:
先研究前面4个字节和前面的区别
47 41 02 30 与 47 41 00 10看看那些字段不一样
通过对比发现,pid不一样
30 :0011 0000 =》transport_scrambling_control:00 adaptation_field_control:11 continuity_counter:0000
10: 0001 0000 =》transport_scrambling_control:00 adaptation_field_control:01 continuity_counter:0000
pes的adaptation_field_control 为11
所以进入adaptation_field()的case
还是老样子,进行2进制解析
0000 0111 0001 0000 0000 0000 0000 0110
1101 1001 0010 0000 0111 1110 0000 0000
adaptation_field_length:0000 0111 ==》7 记录紧跟在此字段之后的调整字段的长度
discontinuity_indicator:0
random_access_indicator:0
elementary_stream_priority_indicator:0
PCR_flag:1
OPCR_flag:0
splicing_point_flag:0
transport_private_data_flag:0
adaptation_field_extension_flag:0
program_clock_reference_base:0000 0000 0000 0110 1101 1001 0010 0000 0 =》897600
reserved:111 111
program_clock_reference_extension:0 0000 0000
由于pes包太大了,一个ts包放不下,我们再取下一个ts包再研究一下:
47 01 02 11==》
0100 0111 0000 0001 0000 0010 0001 0001
sync_byte :0100 0111 ===》0x47 为固定8位
transport_error_indicator: 0
payload_unit_start_indicator:0 表示负载从第几个字节开始
transport_priority:0
PID:0 0001 0000 0010
transport_scrambling_control:00
adaptation_field_control:01 ==》后续为填充字节
continuity_counter:0001
注意事项:
原来,再ts流中,pes的长度可以不用填写,直接赋值为0,通过其他方式可以直接计算出长度,看下面的介绍
*****************************************************************************
至此TS流的分析结束