HLS协议深入分析
在上一篇文章中,我们重点介绍了HLS协议中M3U8文件里面和时间相关的一些字段,以及这些字段在不同平台MAC,Android上的一些应用,本文介绍一下HLS中TS文件里面和时间相关的字段。
一.TS介绍
TS,全称是Transport Stream,最早应用在数字电视系统中。数字电视的标准有三个,美国的ATSC,日本的ISDB和欧洲的DVB,我们国家大概在2001开始引入数字电视,采用的欧洲的DVB标准。在DVB标准中,对于编码后的音视频信息,使用TS格式进行封装,一般情况下,TS的格式的封包大小是188个字节,其中包括了4个字节的头信息和184字节的数据载荷(Payload),我们先简单了解一下TS的封装格式,如下所示:
TS头(4Bytes) |
数据(184) |
图1 TS格式
TS头4个字节包括了如下内容:
Sync byte(8bits) |
Transport error(1bit) |
Payload start indicator(1bit) |
Transport priority(1bit) |
PID(13bits) |
Transport scrambling control(2bits) |
Adaption field control(2bits) |
Continuity counter(4bits) |
图2 TS头
其它红色部分,需要重点关注,也是我们今天讨论的重点。
Sync byte,同步字节,值为0x47,用来进行数据对齐,当连续5个188字节的首字节都是0x47,则认为数据已经同步,即数据可以进行正常的处理。
Payload start indicator,数据载荷起始指示符,数据载荷有两种,一是编码后的音视频数据,二是用户描述音视频信息的表格(PSI、SI),表格信息不是今天介绍的重点。顾名思义,起始指示符就是当每帧视音频数据或每次表格信息的第一个字节出现时,就把该位置1。
PID,在TS中,不同类型的信息,如视频,音频,不同的表格信息,都通过PID来进行区分,不同PID对应的信息类型在PSI,SI表格中描述。
Adaption field control:调整字段指示符。调整字段,它的作用有两个,一是用来传输PCR时钟(我们本文要讲的一个时间相关的参数),另外当数据载荷的长度不够184时,用来填充一些无效数据。
Continuity counter:连续计数,用来标识TS包的连续性,0x1~0xF循环,依次加1,对于相同PID的TS包,如果相依两个TS包的Continuity counter(Mod 0x10)差值不是1,则表示有丢包。
TS格式的设计的初衷是为了抗网络丢包,在网络传输的过程中,不管因为何种原因导致丢包,只要能够进行数据同步,后面的数据就可以进行正常的处理。
今天的重点是介绍HLS的TS中和时间相关的参数,对TS流其它信息感兴趣的话,可以参考一下ISO 13818-1的标准。
二 TS中时间相关的参数
1.DTS和PTS
编码后的视音频数据称为ES(Elementary Stream),在对ES进行解码显示,会遇到两个问题,一是这些数据什么时候应该解码,什么时候应该显示,对网络流,我们可以说接受到就解码,但因为网络抖动的原因也是出现数据传输不均匀,那就会解码随着网络的抖动时快时慢;二是音视频如何同步。为了解决上面两个问题,在对将ES打包成TS之前,首先在每帧音视频数据前面打个的解码时间(DTS)和显示时间(PTS),来告诉解码器每帧数据的解码时间和显示时间,打上PTS和DTS的ES称为PES。
为了提高时间精度,在TS中,PTS和DTS的时间单位不是毫秒,而是1/90000秒。
对于音频帧而言,正常情况下DTS和PTS相等,即解码后立即显示,因此只存放PTS即可。
对于视频帧而言,如果只有I帧和P帧,和音频相同处理,只存放PTS即可。但当出现B帧时情况就变得复杂起来了。假设有一组图像如下,进入编码器前如下图所示:
P110 P211P312P413P514P615P716
上标表示PTS,带两个B帧的编码情况后,编码后的输出如下:
P1109 P41310P21111P31212 P71613P51414P61515
下标表示DTS,红色为I帧,蓝色为P帧,绿色为B帧;图中P2和P3在编码时参考了P4,因此它们要等P4解码后才能解码。在这种情况下,对于I帧和P帧就需要同时存放DTS和PTS。
对于DTS和PTS有两点需要注意(不考虑达到最大值绕头的情况Wrap around):
Ø DTS是一个单调递增数列。
Ø PTS必须不小于DTS,因为从逻辑上讲,只有解码之后再能显示。
关于DTS和PTS的模型也可以参考一下ISO-13818-1的文档。
2.PCR
上面提到DTS和PTS两个时间,有一个问题没有提到,这个时间参考基准是什么?系统时间吗?貌似也可以,把接收到第一个DTS时的系统时间和DTS做一个差值,然后每次比较时一下这个基准时间(当前系统时间+差值)和DTS或PTS,但是,处理过硬件时钟的同学都知道,每个时钟和每个时钟的晶振都会的差异,运行的时间越长,越偏差就会越大,因此需要进行校正,哪用谁来校正呢?在DVB标准中,把这个校正的时间称为PCR(ProgramClock Reference),PCR放在了AdaptationField 中,它的精度更高,单位是1/27000000秒。每当TS中出现PCR时,就要用这个PCR去校正一下我们之前的时间基准,从而达到和编码时的时钟一致。
在TS的传输过程中,一般DTS和PCR差值会在一个合适的范围,这个差值就是要设置的视音频Buffer的大小,一般情况下视频DTS和PCR的差值在700ms~1200ms之间,音频差值在200ms-700ms之间。
3.连续计数
Continuity counter ,在前面我们介绍过,是用来标识TS包的连续性,对于相同PID的TS包,它的连续计数值是逐个加1的。
4.TS文件名
在HLS标准中,对于TS命名没有规定,可以是合法的任意字符串,但是在实际的实现中,如果我们合理的对TS进行命名,也可以解决和时间相关的一些问题,推荐TS命名中至少包括毫秒级的系统UTC时间。这样的做的好处于,通过不同TS命名中UTC时间的差值和DTS的差值,我们可以用来判断网络传输是否存在慢速。当UTC的差值大于DTS的差值到一定阀值时,我们就可以认为发生了慢速。当然这个阀值要根据实际的情况进行设置,在这里不再赘述。
三 小结
通过两篇文章的介绍,我们对HLS协议中和时间相关的一些字段进行了分析,了解这些参数的含意后,在对HLS直播过程的问题进行分析时,我们就可以重点观察一下这些和时间相关的参数的变化。