TS Stream 详解
![](https://note.wiz.cn/wiz-resource/0dc33ff3-e3a9-4ae7-94fd-056b02b950c7/871dcd25-d15e-4070-a2fb-11360b77bedc/index_files/4b4e4fe3-f2eb-4b94-91aa-dbfcc93823d5.png)
![](https://note.wiz.cn/wiz-resource/0dc33ff3-e3a9-4ae7-94fd-056b02b950c7/871dcd25-d15e-4070-a2fb-11360b77bedc/index_files/6eefd68a-7e1c-4c0d-b95c-ad844468327e.png)
●PES:置为1,标识TS包的有效净荷以PES包的第一个字节开始,即此TS包为PES包的起始包,且此TS分组中有且只有一个PES包的起始字段;置为0,表示TS包不是PES包的起始包,是后面的数据包。●PSI:置为1,表示TS包中带有PSI数据分段的第一个字节,即这个TS包是PSI
Section的起始包,则此TS包的负载(payload)的第一个字节带有pointer_field,用来指示PSI数据的在payload 中的位置;置为0,表示TS包不带有PSI
Section的第一个字节,即此TS包不是PSI的起始包,即在有效负载中没有point_field,有效负载的开始就是PSI的数据内容。point_field的定义将在下面的PSI节中进行介绍;对于空包的包,payload_unit_start_indicator应该置为0。例如:若TS包载荷为PAT,则当接收到的TS包的payload_unit_start_indicator为1时,表明这个TS包包含了PAT头信息,从这个包里面解析出section_length和continuity_counter,然后继续收集后面的payload_unit_start_indicator
= 0的TS包,并判断continuity_counter的连续性,不断读出TS包中的净载荷(也就是PAT数据),用section_length作为收集TS包结束条件。
●0x0000代表PAT●0x0001代表CAT●0x0002-0x000F保留●0x1FFF表示空包
●总结
如果adaptation_field_control == 1x,表示后面跟有自适应字段;
如果adaptation_field_control == x1,表示后面跟有没有自适应字段;
➤自适应调整字段
![](index_files/e6495c66-25c7-4fb5-af95-92483417dafb.jpg)
➣ adaptation_field_length:调整字段长度标示,标示此字节后面调整字段的长度,占位8bit;值为0时,表示在TS分组中插入一个调整字节,后面没有调整字段,紧跟着的是有效负载;adaptation_field_control ==
‘11’时,此值在0~182之间,adaptation_field_control == ‘10’时,此值为183,若字段没这么长则填充0xFF字段;后面的字段都是在adaptation_field_length>0的时候才会出现,顺序如下:
➣ discontinuity_indicator:不连续状态指示符,占位1bit,置位1时表示此TS分组的不连续状态为真;
➣ random_access_indicator:随机访问指示符,占位1bit;
➣ elementary_stream_priority_indicator:原始流数据优先级指示符,占位1bit,置位1表示此原始流数据比相同PID的TS包中的其他原始流优先级高;
➣ PCR_flag:PCR标志位,占位1bit,置位1表示调整字段中包含PCR字段,置位0则没有PCR字段;
PCR字段:当PCR_flag == 1时,此字段才存在,占位48bit,依次顺序为:
●program_clock_reference_base字段: 占位33bit;
●reserved字段: 占位6bit;
●program_clock_reference_extension字段:占位9bit;
OPCR字段:当OPCR_flag == 1时,此字段才存在,占位48bit,依次顺序为:
●original_program_clock_reference_base字段: 占位33bit;
●reserved字段: 占位6bit;
●original_program_clock_reference_extension字段:占位9bit;
splice_countdown字段:当splicing_point_flag == 1时此字段存在,占位8bit;
transport_private_data字段:私有数据字段,当transport_private_data_flag == 1时此字段存在,占位N*8bit,字节顺序为:
●transport_private_data_length:表明私有数据的字节长度,占位8bit;
●private_data_byte:私有数据,长度由前面的长度字段确定;
➣ adaptation_field_extension_flag:调整字段扩展标志位,占位1bit,置位1表示含有调整字段扩展字段,置位0则无扩展字段;
adaptation_field_extension字段:调整字段扩展字段,占用长度不确定,当adaptation_field_extension_flag == 1时此字段存在,字段中也有3个标志位,来确定一些字段存不存在,其具体字节顺序如下:
●adaptation_field_extension_length:调整字段扩展字段的长度,占位8bit;
●ltw_flag:ltw字段标志位,置位1时表示此字段存在,占位1bit;
●piecewise_rate_flag:piecewise_rate字段标志位,置位1时此字段存在,占位1bit;
●seamless_splice_flag:seamless_splice标志位,置位1时此字段存在,占位1bit;
●Reserved:保留字段,占位5bit;
●Ltw字段:当ltw_flag == 1时此字段存在,占位16bit,其由以下两个字段组成
ltw_valid_flag:占位1bit,当ltw_valid_flag == 1时,ltw_offset才有效;
ltw_offset:占位15bit;
●piecewise_rate字段:当piecewise_rate_flag == 1时此字段存在,占位24bit,其字节顺序如下:
reserved字段:保留字段,占位2bit;
piecewise_rate字段:占位22bit;此字段只有在当ltw_flag == 1和ltw_valid_flag == 1时才有定义,有定义时此字段是一个正整数;
●seamless_splice字段:当seamless_splice_flag == 1时此字段存在,占位40bit;字节顺序依次为:
splice_type字段:占位4bit;标识delay和rate值;
DTS_next_AU[32..30]:占位3bit;
marker_bit字段:占位1bit;
DTS_next_AU[29..15]字段:占位15bit;
marker_bit:占位1bit;
DTS_next_AU[14..0]:占位15bit;
marker_bit:占位1bit;
●stuffing_byte:填充字段,固定为0xFF
➣Payload_bytes:有效负载字段,字节来自PES包,PSI部分等;
![](https://note.wiz.cn/wiz-resource/0dc33ff3-e3a9-4ae7-94fd-056b02b950c7/871dcd25-d15e-4070-a2fb-11360b77bedc/index_files/9f30f881-477d-4a29-a6a3-2d643a2a0c14.jpg)
可以看出,PES包是由固定包头,可选包头和负载三部分组成,其中固定包头固定6个字节;PES包长度字段占位16bit,最大值为65536,故一帧可能会分为多个PES包;下面依次介绍其每个字段的含义:
➣Packet start code prefix:包头起始码,固定为0x000001,占位24bit;
➣Stream id:(UI)PES包中的负载流类型,一般视频为0xe0,音频为0xc0,占位8bit;
➣PES packet length:(UI)PES包长度,包括此字节后的可选包头和负载的长度,占位16bit;
Optional PES Header,顺序依次为:
➣'10'字段:占位2bit;
➣PES scrambling control:加密模式,占2bit;00未加密,01或10或11由用户定义;
➣PES priority:有效负载的优先级,占位1bit;值为1比值为0的负载优先级高;
➣Data alignment indicator:数据定位指示器,占位1bit;
➣Copyright:版权信息,1为有版权,0无版权,占位1bit;
➣Original or copy:原始或备份,1为原始,0为备份,占位1bit;
☢ 后面是7个flags,对应的flag 如果被置1 , 就在PES header data length字段后追加相应的数据(一般我们关注的就是PTS
DTS的标志位):
➣PTS_DTS_flags:PTS和DTS标志位,占位2bit;10表示首部有PTS字段,11表示有PTS和DTS字段,00表示都没有,01被禁止,不会出现此种情况;
PTS/DTS字段:显示时间戳/解码时间戳,占位40bit,当PTS_DTS_flags == 1x时此字段存在;时间占用33个bit,PTS和DTS的内容是在这40bit中取33位,方式相同;
PTS(presentation time stamp)显示时间戳和DTS(Decoding Time
Stamp)解码时间戳,是用来音视频同步的,是打在PES包的包头里面的,PTS/DTS是相对SCR(系统参考)的时间戳,是以90000为单位的,PTS/DTS到ms的转换公式是PTS/90,系统时钟频率(H264采样频率?)为90Khz,所以转换到秒为PTS/90000,所以如果是以ms为单位的播放器,PTS/DTS是要使用公式ms=pts/90来转换才行的,而如果是以时钟频率为单位的话,则直接将PTS/DTS送进去解码即可;如果没有B帧,PTS和DTS的顺序应该是一致的,如果有B帧,则需要先解码P帧,才能解出来B帧,所以需要PTS和DTS来控制解码时间和显示时间;
![](https://note.wiz.cn/wiz-resource/0dc33ff3-e3a9-4ae7-94fd-056b02b950c7/871dcd25-d15e-4070-a2fb-11360b77bedc/index_files/0.41503784466709837.png)
字节顺序依次:
●start_code:起始码,占位4bit;若PTS_DTS_flags == ‘10’,则说明只有PTS,起始码为0010;若PTS_DTS_flags == ‘11’,则PTS和DTS都存在,PTS的起始码为0011,DTS的起始码为0001;(PTS的起始码后2个bit与flag相同)
●PTS[32..30]:占位3bit;
●marker_bit:占位1bit;
●PTS[29..15]:占位15bit;
●marker_bit:占位1bit;
●PTS[14..0]:占位15bit;
●marker_bit:占位1bit;
PTS/DTS = (PTS1 & 0x0e) << 29 + (PTS2 & 0xfffe) << 14 + (PTS3 & 0xfffe ) >> 1;
➣ESCR_flag:ESCR标志,占位1bit;1表示首部有ESCR字段,0则无此字段
ESCR字段:此字段占位48bit,由33bit的ESCR_base字段和9bit的ESCR_extension字段组成,ESCR_flag == 1时此字段存在;数据依次顺序:
●Reserved:保留字段,占位2bit;
●ESCR_base[32..30]:占位3bit;
●marker_bit:占位1bit;
●ESCR_base[29..15]:占位15bit;
●marker_bit:占位1bit;
●ESCR_base[14..0]:占位15bit;
●marker_bit:占位1bit;
●ESCR_extension:(UI)占位9bit;周期数,取值范围0~299;循环一次,base+1;
●marker_bit:占位1bit;
➣ES_rate_flag:ES_rate字段,占位1bit;1表示首部有此字段,0无此字段;
ES rate字段:目标解码器接收PES分组字节速率,禁止为0,占位24bit,ES_rate_flag == 1时此字段存在;数据顺序为:
●marker_bit:占位1bit;
●ES_rate:占位22bit;
●marker_bit:占位1bit;
➣DSM_trick_mode_flag:占位1bit;1表示有8位的DSM_trick_mode_flag字段,0无此字段;
Trick mode control字段:表示哪种trick mode被应用于相应的视频流,占位8个bit,DSM_ trick_mode_flag == 1时此字段存在;其中trick_mode_control占前3个bit,根据其值后面有5个bit的不同内容;
如果trick_mode_control == ‘000’,依次字节顺序为:
●field_id:占位2bit;
●intra_slice_refresh :占位1bit;
●frequency_truncation:占位2bit;
如果trick_mode_control == ‘001’,依次字节顺序为:
●rep_cntrl:占位5bit;
如果trick_mode_control == ‘010’,依次字节顺序为:
●field_id:占位2bit;
●Reserved:占位3bit;
如果trick_mode_control == ‘011’,依次字节顺序为:
●field_id:占位2bit;
●intra_slice_refresh:占位1bit;
●frequency_truncation:占位2bit;
如果trick_mode_control== ‘100’,依次字节顺序为:
●rep_cntrl:占位5bit;
其他情况,字节顺序为:
●reserved :占位5bit;
➣Additional_copy_info_flag:占位1bit;1表示首部有此字段,0表示无此字段;
Additional copy info字段:占8个bit,Additional_copy_info_flag == 1时此字段存在;数据顺序为:
●marker_bit:占位1bit;
●copy info字段:占位7bit;表示和版权相关的私有数据;
➣PES_CRC_flag:占位1bit;置1表示PES分组有CRC字段,0无此字段;
●Previous PES CRC字段:占位16bit字段,包含CRC值,PES_CRC_flag == 1时此字段存在;
➣PES_extension_flag:占位1bit;扩展标志位,置1表示有扩展字段,0无此字段
PES exten sion字段:PES扩展字段,PES_extension_flag == 1时此字段存在;内容如下,字节顺序依次为:
●PES_private_data_flag:占位1bit,置1表示有私有数据,0则无;
PES_private_data字段:私有数据内容,占位128bit,PES_private_data_flag == 1时此字段存在;
●Pack_header_field_flag:占位1bit,置1表示有Pack_header_field字段,0则无;
Pack_header_field字段:Pack_header_field_flag == 1时此字段存在;字段组成顺序如下:
Pack_field_length字段:(UI)指定后面的field的长度,占位8bit;
pack_header_field():长度为Pack_field_length指定;
●Program_packet_sequence_counter_flag:占位1bit,置1表示有此字段,0则无;
Program_packet_sequence_counter字段:计数器字段,16个bit;当flag字段Program_packet_sequence_counter_flag == 1时此字段存在;字节顺序依次为:
marker_bit:占位1bit;
packet_sequence_counter字段:(UI)占位7bit;
marker_bit:占位1bit;
MPEG1_MPEG2_identifier:占位1bit;置位1表示此PES包的负载来自MPEG1流,置位0表示此PES包的负载来自PS流;
original_stuff_length:(UI)占位6bit;表示PES头部填充字节长度;
●P-STD_buffer_flag:占位1bit,置1表示有P-STD_buffer字段,0则无此字段;
P-STD_buffer字段:表示P-STD_buffer内容,占位16bit;P-STD_buffer_flag == '1'时此字段存在;字节顺序依次为:
’01’字段:占位2bit;
P-STD_buffer_scale:占位1bit;表示用来解释后面P-STD_buffer_size字段的比例因子;如果之前的stream_id表示音频流,则此值应为0,若之前的stream_id表示视频流,则此值应为1,对于其他stream类型,此值可以0或1;
P-STD_buffer_size:占位13bit;无符号整数;大于或等于所有P-STD输入缓冲区大小BSn的最大值;若P-STD_buffer_scale == 0,则P-STD_buffer_size以128字节为单位;若P-STD_buffer_scale == 1,则P-STD_buffer_size以1024字节为单位;
●Reserved字段:3个bit;
●PES_extension_flag_2:占位1bit,置1表示有扩展字段,0则无此字段;
PES_extension2字段:扩展字段的扩展字段;占用N*8个bit,PES_extension_flag_2 == '1'时此字段存在;字节顺序依次为:
marker_bit:占位1bit;
PES_extension_field_length:占位7bit,表示扩展区域的长度;
Reserved字段:占位8*PES_extension_field_length个bit;
Stuffing bytes:填充字段,固定为0xFF;不能超过32个字节;
PES_packet_data_byte:PES包负载中的数据,即ES原始流数据
➣PES header data length:(UI)PES首部中可选字段和填充字段的长度;占位8bit;可选字段的内容由上面7个flags来进行控制;
TS Stream 详解的更多相关文章
- [视频播放] HLS协议之M3U8、TS流详解
本文转载自:<hls之m3u8.ts流格式详解> HLS,Http Live Streaming 是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部 ...
- JDK1.8中的Stream详解
Stream简介 Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 XML ...
- 爱你不容易 —— Stream详解
作为前端,我们常常会和 Stream 有着频繁的接触.比如使用 gulp 对项目进行构建的时候,我们会使用 gulp.src 接口将匹配到的文件转为 stream(流)的形式,再通过 .pipe() ...
- gulp源码解析(一)—— Stream详解
作为前端,我们常常会和 Stream 有着频繁的接触.比如使用 gulp 对项目进行构建的时候,我们会使用 gulp.src 接口将匹配到的文件转为 stream(流)的形式,再通过 .pipe() ...
- 性能篇系列—stream详解
Stream API Java 8集合中的Stream相当于高级版的Iterator Stream API通过Lambda表达式对集合进行各种非常便利高效的聚合操作,或者大批量数据操作 Stream的 ...
- Java8之Stream详解
Java8中提供了Stream对集合操作作出了极大的简化,学习了Stream之后,我们以后不用使用for循环就能对集合作出很好的操作. 一.流的初始化与转换 Java中的Stream的所有操作 ...
- 此流非彼流——Stream详解
Stream是什么? Java从8开始,不但引入了Lambda表达式,还引入了一个全新的流式API:Stream API.它位于java.util.stream包中. Stream 使用一种类似用 S ...
- Java 8 Stream API详解--转
原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...
- Java8的Stream语法详解(转载)
1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...
随机推荐
- HDU 1846 Brave Game 巴什博奕
解题报告:Alice和Bob在做一个取石子游戏,有一堆n个石子,然后规定每个人每次最少要去1个石子,最多可以取m个石子,最后一次取完石子的人为胜. 巴什博奕,关键是找到必胜点和必败点,我们可以先列举出 ...
- 【leetcode 简单】 第一百一十题 分发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干.对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 j ,都有一个尺寸 ...
- HDU 3790 最短路径问题 (最短路)
题目链接 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. ...
- 【译】第九篇 SQL Server代理了解作业和安全
本篇文章是SQL Server代理系列的第九篇,详细内容请参考原文 在这一系列的上一篇,学习了如何在SQL Server代理作业步骤启动外部程序.你可以使用过时的ActiveX系统,运行批处理命令脚本 ...
- 苹果手机浏览器$(document).on(“click”,function(){})点击无效的问题
<label class="js_highlight" style="display: inline-block;float: left;width: 50%;&q ...
- iOS学习笔记(2)— UIView用户事件响应
UIView除了负责展示内容给用户外还负责响应用户事件.本章主要介绍UIView用户交互相关的属性和方法. 1.交互相关的属性 userInteractionEnabled 默认是YES ,如果设置为 ...
- linux cpu、内存、硬盘空间查询
[CPU] 算式: CPU总核数 = 物理CPU个数 * 每颗物理CPU的核数 总逻辑CPU数 = 物理CPU个数 * 每颗物理CPU的核数 * 超线程数 #查看CPU型号 cat /proc/cpu ...
- Mac上删除不了的文件,Windows上也粉碎不了怎么办?
推荐一个Mac上的软件:Tuxera Disk Manager 用法很简单:选择删除文件原来所在的文件进行维护就可以了. 维护之后,在废纸篓中清除,成功.
- maven package exec 及 maven 配置文件详解
maven package test包下执行test 的配置文件 生成target目录,编译.测试代码,生成测试报告,生成jar/war文件 maven 配置文件详解 http://blog.csdn ...
- Windows 8 应用程序前后台切换事件监听
在一些情况下,我们需要监听应用程序切换到后台或者从后台切换至前台的事件,从而进行相关处理操作.支付宝应用锁屏(IOS,Android平台)的处理中就需要监听此事件,在用户将应用切换至后台一段时间后再切 ...