在数字电视的应用中,TS流数据的播放是其中一个重要环节。TS流的播放从接收端的角度来考虑,是如何保证解码器的缓冲器不出现溢出;从发送端来考虑,是如何保证码流按照其自身的码率较为均匀地离开发送设备。
目前TS流的发送有两种方式,一种是传统的通过硬件设备,输出ASI信号,另一种是通过IP网络以IP的数据包方式进行发送。本文就后者进行讨论。
通过IP网络传输TS流数据,主要是通过单播(UDP)或组播(Multicast)的方式进行传输。考虑到以太网中数据帧的最大长度为1500字节,所以TSOverIP规定,每7个TS数据包封装在一起组成一个IP包进行发送。
基于IP发送TS的基本原则是,先计算IP包发送的理论时间,再统计实际发送完时的时间,以目前百兆网卡甚至是千兆网卡的发送能力,理论发送时间应该大于实际发送时间(如果小于说明码率太大,将无法正常发送),每发送一定数量的IP包,休息一段时间,休息的这个时间为理论时间和实际发送时间之间的差值。
IP包理论发送时间的计为:Send_time(n) 实际发送时间可以取当前的系统时间(Sys_time)。
在第一次发送数据时,此时Send_time(0)为0,此时需要记录系统时间和发送时间的差值。
Distance_Send_Sys = Sys_time(0)-Send_time(0);
式中下标为IP包的索引号,下同。
每发送完一定数据量的IP包后,休息时间的计算公式为:
Wait_time(n)= Send_time(n)-(Sys_time(n)- Distance_Send_Sys);
休息时间即码流中的时间间隔和系统流逝的时间之间的差
对于CBR的TS流,我们可以根据给定的码率计算每个IP包的发送时刻,计算公式如下:
Send_time(n) = (IP_Pack_Index * 7 * 188 * 8)/ bit_rate
在上式中Send_time(n)是第n个IP包要发送的时间;IP_Pack_Index是该IP包的索引(即下标n),从0开始,依次增加;7*188一个IP包的字节数,乘8后变成以位为单位;bit_rate是指定的码率。
以38M的码率为例,每个IP包发送的时间大约为:
7*188*8/38000000=0.000277(s)
考虑到计算机或其它发送设备一般都精确到毫秒级,我们可以计算一定单位时间内需要发送的IP包数,比如100ms为单位时间,需要的发送的IP包数计算公式如下:
IP_Pack_Count =(bit_rate/10) /(188*7*8)
其中bit_rate为指定发送的码率,除10后为100ms的码率;188*7*8为一个IP数据包的位数。这样我们就得到了100ms要发送的IP包的个数,大约为361个IP包。
这样我们每发送完一定数量IP包后,根据“TS发送的基本原则”一节描述的计算“休息时间”的公式,休息一段时间,再继续发送下一组数据。
对VBR而言,因为码率在时刻进行变化,我们无法再根据码率进行发送。这时我们需要根据TS流中的视音频数据的DTS进行发送。
我们知道在TS中,一般来讲码率的变化主要是因为视频在编码时IBP帧的大小不一致导致的,而音频一般仍为固定码率,或者近似于固定码率;那么我们如何选择根据视频还是音频的DTS呢?在这里我们建议使用音频的DTS,因为在Mpeg-2标准中,定义的音频解码器的缓冲要比视频解码器的缓冲小得多,也就是说音频DTS相对于PCR的波动较视频更为严格,一旦波动越出缓冲器的大小,将会导致缓冲器溢出。
在VBR中,Send_time(n) 可以直接取该IP包所包含音频的DTS,每次发送的数据长度,可以取一个音频帧,也可以取几个音频帧。因为在TS流中,每个音频帧的长度为固定24ms,建议取6个音频帧,也就是144ms,因为有的复用器在打包时会直接把6个音频帧打包成一个PES包。
这样,我们在发送VBR时,以IP包的大小7*188为单位进行数据读取,每当该IP包包含一个音频的DTS时,将当前的DTS和上一次发送的DTS进行比较,如果大于我们指定的时间间隔(24ms或144ms),就开始发送这一组IP包,发送完成后,根据“TS发送的基本原则”一节描述的公式,计算要休息的时间。
随着TSOverIP技术的广泛应用,基于IP播放TS流将会得到更多人的关注。在本文中,我们对CBR和VBR两种TS的发送方法进行探讨,并通过实验得到了比较满意的结果。根据上述方法发送的TS流,通过VLC播放,无任何错误提示。感兴趣的读者可以试用TS-Broad的最新软件。
另外,基于系统时钟和DTS进行时间控制的思想,也为我们解码播放时处理音视频的同步提供了想象的空间。这个话题留给有志于解决这方面问题的开发人员进行深入的思考的吧。
VLC 源码