
讯享网
第一节
如上图所示 分别是个人总结和网络总结 可以看出一个PS流的解析大概流程 我的个人理解是讲一个PS流或TS流解析分成五个层级和四层解析
第一层 :PS流或TS流通过流协议解析 解析成一个个PS包
第二层 :对每个PS包进行解析 一个PS包可能包含的是(video I 帧 video p/b帧 audio 帧)
第三层 :对每帧进行解析 video I帧相比与P/B帧 会多出一个PSM包
第四层 :对每个PES包进行解析 PES包由PES Header和PES Payload构成
理清PS流的基础层级后 接下来需要知道的就是针对每一层 怎么通过二进制数据来进行解析 下面将对每一层的包都进行解析 顺序为PES包 PSM包(同级)PS包 这三个包来进行解析
第二节 PSM包的解析
PSM包(ps_system_map)都由VIdeo I Frame携带 出现在IDR帧前 一般都当作和PES包同格式 原因是PSM包和PES包的前三个字节都是固定的 为0x000001 第四个字节用来区分PSM包还是PES包 PSM包的第四个字节 是固定的BC
接下来 讲对着标准详细介绍每个字节对应着什么信息(左边为字节数 右边为信息)
3字节 24bits------Packet start code prefix字段:包头起始码,固定为0x000001,与后面的字段map_stream_id一起组成分组开始码,标志着分组的开始
1字节 8bits------map_stream_id字段:类型字段,标志此分组是什么类型,如果此值为0xBC,则说明此PES包为PSM
2字节 16bits------program_stream_map_length字段:长度字段,占位16bit;表示此字段之后PSM的总长度,最大值为1018(0x3FA)
1 bit------current_next_indicator字段:标识符,置位1表示当前PSM是可用的,置位0则表示当前PSM不可以,下一个可用
2 bits------Reserved:保留字段
5 bits------program_stream_map_version字段:版本字段,占位5bit;表示PSM的版本号,取值范围1到32,随着PSM定义的改变循环累加;若current_next_indicator == 1,表示当前PSM的版本号,若current_next_indicator == 0,表示下一个PSM的版本号
7 bits------Reserved:保留字段
1 bit------marker_bit:标记字段,占位1bit,固定为1
16 bits------program_stream_info_length字段:长度字段,占位16bit;表示此字段后面的descriptor字段的长度
不固定 bits------Descriptor字段:program Stream信息描述字段,长度由前个字段确定
16 bits------elementary_stream_map_length字段:长度字段,占位16bit;表示在这个PSM中所有ES流信息的总长度;包括stream_type, elementary_stream_id, elementary_stream_info_length的长度,即 N*32bit;是不包括具体ES流描述信息descriptor的长度的
8 bits------stream_type字段:类型字段,占位8bit;表示原始流ES的类型;这个类型只能标志包含在PES包中的ES流类型;值0x05是被禁止的;常见取值类型有MPEG-4 视频流:0x10;H.264 视频流:0x1B;G.711 音频流:0x90;因为PSM只有在关键帧打包的时候,才会存在,所以如果要判断PS打包的流编码类型,就根据这个字段来判断
8 bits------elementary_stream_id字段:流ID字段,占位8bit;表示此ES流所在PES分组包头中的stream_id字段的值;其中0xC0-0xDF指音频,0xE0-0xEF为视频(同PES包判断audio video标准)
16 bits------elementary_stream_info_length字段:长度字段,占位16bit;表示此字段之后的,ES流描述信息的长度
不固定bits------Descriptor:描述信息,长度由前个字段确定;表示此类型的ES流的描述信息(即ES DATA),这个描述信息的长度是不包含在elementary_stream_map_length字段里面的
32 bits------CRC_32:CRC字段,占位32bit,CRC校验值
第三节 PES包的解析
与PSM包相比 PES包的解析要相对简洁一点 大致可以分成PES Header和PES Payload两部分,然后PES Header分成固定包头和可选包头两部分 PES包解析的复杂点在于对可选包头的解析 可选包头分为两种情况 下面开始对着标准详细介绍每个字节对应着什么信息(左边为字节数 右边为信息)
第一部分 固定包头(共六个字节):
3字节 24bits------Packet start code prefix:包头起始码,固定为0x000001
1字节 8bits------Stream id:(UI)PES包中的负载流类型,一般视频为0xe0到0xEF,音频为0xc0到0xDF,占位8bit
2字节 16bits------PES packet length:(UI)PES包长度,包括此字节后的可选包头和负载的长度,占位16bit,当其为0时,需要根据下个PS包头起始码来确定PES包长度
第二部分 可选包头解析(分为两大部分)
第一分类 可选包头:
接着固定包头后的两个bits 不是 ”10“ 字段 而是”00“字段 那么跟着固定包头后面的第三四个bits 代表着是否包含PTS DTS(10 代表有PTS 11代表有PTS DTS 不存在01字段)(根据跟在固定包头后的一个字节的前四个bits来进行区分后面字节的意义)
如果只有PTS 那么接下来五个字节是表示PTS内容的字段(五个字节的内容怎么代表PTS 再怎么计算出PTS 在说完第二种可选包头的分布中会介绍)
如果既有PTS又有DTS 那么接下来10个字节是表示PTS和DTS的内容字段(计算方式同五个字节的PTS计算)
第二分类 可选包头:
接着固定包头后的两个bits是”10”分段 则划分为第二分类可选包头 大框架可以按照
8bits 一个字节(紧跟固定包头后的那个字节)
8bits 一个字节 标识各种flag
8bits 一个字节 PES_header_data_length
下面对着大框架来一 一解析每个bits的意义
第一部分:8bits 一个字节
2bits------固定字段 “10”
2bits------PES scrambling control:加密模式,占2bit;00未加密,01或10或11由用户定义,一般默认为00;
1bits------PES priority:有效负载的优先级,占位1bit;值为1比值为0的负载优先级高,一般默认为1;
1bits------Data alignment indicator:数据定位指示器,占位1bit
1bits------Copyright:版权信息,1为有版权,0无版权,占位1bit,默认值为0x00;
1bits------Original or copy:原始或备份,1为原始,0为备份,占位1bit;默认值为0x00;
第二部分:8bits 一个字节 标识各种flag
2bits------PTS_DTS_flags,PTS和DTS标志位,10表示首部有PTS字段,11表示有PTS和DTS字段,00表示都没有,01被禁止,不会出现此种情况,一般在分包时,第一个包为11,其他为0;
1bits------ESCR_flag,ESCR标志,占位1bit,1表示首部有ESCR字段,0则无此字段,默认为0;
1bits------S_rate_flag:ES_rate字段,占位1bit,1表示首部有此字段,0无此字段,默认为0;
1bits------DSM_trick_mode_flag:占位1bit,1表示有8位的DSM_trick_mode_flag字段,0无此字段,默认为0;
1bits------Additional_copy_info_flag:占位1bit,1表示首部有此字段,0表示无此字段,默认为0;
1bits------PES_CRC_flag:占位1bit,1表示PES分组有CRC字段,0无此字段,默认为0;
1bits------PES_extension_flag:占位1bit,扩展标志位,置1表示有扩展字段,0无此字段,默认为0
第三部分:8bits 一个字节 PES_header_data_length
PES首部中可选字段和填充字段的长度,占位8bit,可选字段的内容由上面7个flags来进行控制, 主要是PTS_DTS_flags控制的PTS和DTS字段,填充字节需要注意的是,当对原始流进行 PES 分组,尤其是需要将一帧信息断开分成多个 PES 分组时,
从第二个分组开始不需要 PTS,PES_header_data_length 和它前面的一个字节又都为 0x00,很可能与后面断开的数据组合形成 0x00 00 01 等类似的伪起始码或关键字,令解码端在收到流不完整时产生误判,因此填充字节 stuffing_byte 至少必须加入 1 byte 以确保这种误判不会发生。同时为了入一些私有信息,目前规定 stuffing_byte 至少必须加入 2byte。
第四节 PTS的计算和ES数据的长度计算
PTS/DTS 都是相对SCR(system-time)的时间戳,并不是绝对时间,以系统频率90000为单位 并且PTS/DTS的内容是从40byte中读取33byte来计算得来 下面详细介绍计算过程
一共40个byte 5个字节:
1.start_code: 4byte---起始码 根据第二部分的PTS_DTS_flags 来确定start_code的值 PTS_DTS_flags == ‘10’,则说明只有PTS,起始码为0010;若PTS_DTS_flags == ‘11’,则PTS和DTS都存在,PTS的起始码为0011,DTS的起始码为0001;(PTS的起始码后2个bit与flag相同)
2.PTS数据第一部分 PTS1---PTS部分的【32-30】3byte大小
3.marker_bit 1byte大小 标志位 用来分隔数据
4.PTS数据第二部分 PTS2---PTS部分的【29-15】15byte大小
5.marker_bit 1byte大小 标志位 用来分隔数据
6.PTS数据第三部分 PTS3---PTS部分的【14-0】15byte大小
7.marker_bit 1byte大小 标志位 用来分隔数据
综上 PTS数据分为三部分 PTS1【32-30】 PTS2【29-15】 PTS3【14-0】
计算公式:
PTS = (PTS1 & 0x0e) << 29 + (PTS2 & 0xfffe) << 14 + (PTS3 & 0xfffe ) >> 1
DTS规则与PTS一致,一般PES header data length是10+填充位,其他可选字段大都不存在,解封装的时候,先计算PES长度,再计算PES header data长度,最后计算出ES的长度及起始位置,计算工时如下:

ESlen = PESlen-2-1-pes_header_data_length
PES包头之后,紧跟着就是原始的视频帧数据(ES)或者音频数据
第五节 PS包头字段的封装和解析
PS头是对PES包的进一步封装,是将具有共同时间基准的一个或多个PES包组合而成的单一的数据流,PS流总是以0x000001BA开始,以0x000001B9结束,对于一个PS文件,有且只有一个结束码0x000001B9,不过对于网传的PS流,则应该是没有结束码的;具体PS包头字段组成顺序如下:
- pack_start_code:起始码,占位32bit,标识PS包的开始,固定为0x000001BA
- ‘01’字段:占位2bit
- SCR字段:占位46bit,其中包含42bit的SCR值和4个bit的marker_bit值;其中SCR值由system_clock_reference_base和system_clock_reference_extension两部分组成,字节顺序依次是:
(1) system_clock_reference_base [32…30]:占位3bit
(2) marker_bit:占位1bit
(3) system_clock_reference_base [29…15]:占位15bit
(4) marker_bit:占位1bit
(5) system_clock_reference_base [14…0]:占位15bit
(6) marker_bit:占位1bit
(7) system_clock_reference_extension:占位9bit
(8) marker_bit:占位1bit - program_mux_rate字段:速率值字段,占位22bit,正整数,表示P-STD接收此字段所在包的PS流的速率;这个值以每秒50字节作为单位;禁止0值;
- Marker_bit:标记字段,占位1bit,固定为’1’;
- Marker_bit:标记字段,占位1bit,固定为’1’;
- Reserved字段:保留字段,占位5bit;
- pack_stuffing_length字段:长度字段,占位3bit;规定了此字段之后填充字段的长度;
- stuffing_byte:填充字段,固定为0xFF;长度由前一字段确定;
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/120190.html