基于IP播放TS流的码率控制策略

前言

在数字电视的应用中,TS流数据的播放是其中一个重要环节。TS流的播放从接收端的角度来考虑,是如何保证解码器的缓冲器不出现溢出;从发送端来考虑,是如何保证码流按照其自身的码率较为均匀地离开发送设备。

 

目前TS流的发送有两种方式,一种是传统的通过硬件设备,输出ASI信号,另一种是通过IP网络以IP的数据包方式进行发送。本文就后者进行讨论。

TSOverIP

通过IP网络传输TS流数据,主要是通过单播(UDP)或组播(Multicast)的方式进行传输。考虑到以太网中数据帧的最大长度为1500字节,所以TSOverIP规定,每7个TS数据包封装在一起组成一个IP包进行发送。

 

TS发送的基本原则

基于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的播放策略

对于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的播放策略

对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 源码

分享到: 
  • 上一篇:线程池(翻译自MSDN)
  • 下一篇:PE文件学习总结
  • 查看评论
    23楼  zhl2001xlh800 2012-05-08 20:54发表  [回复]
    您好,吴老师,我看了你的有关TS发送的理论,觉得很有道理,我自己研究了很久,都没有找到合适的方法来实现IP发送TS流,在接收端实现流畅的播放。

    我根据你的理论,自己实现了一下,但是效果还是不很理想,linux下使用VLC 1.1.9在接收端播放,在其统计工具里发现音频帧持续丢失,相应的,声音的播放是断断续续的。视频还好。但是当使用VLC 2.0在windows和苹果电脑上播放时(ubuntu无法安装VLC2.0,自己编译也不行),就没问题,感觉是VLC2.0帮我修复了某个问题。

    我是使用ffmpeg的库进行的转码,然后根据PCR进行发送,我不知道具体您是如何处理的,我是按照您的理论,检查两个连续的PCR之间的差,和相应的系统时间之间再次求差,若发送快了,就休息,否则就继续发送。但是不知道为什么结果还是不行。

    此外,还有一个问题,就是我发现ffmpeg帮我打的PCR中,大部分PCR的base都是增加7200(80ms),但是每隔若干个,就会有两个递增3600(40ms),这还好,更有甚者是会出现个别的超级大的PCR,extention部分很大,base部分也很大,十分奇怪,没有规律,不知道是为什么?

    此外,我看到您有IP播放TS的代码,不知道能不能给我发一份,我真的十分需要,十分感谢![email protected]
    22楼  wutong_login 2010-01-13 17:10发表  [回复]
    liaoqianyu:
    你好。
    组播的相关知识,可以学习一下TCP/IP协议,笼统点说,组播是指加入组中的多个成员可以同时接收到发送者发送的同一份数据数据。

    组播TS流时,需要注意的是,按照标准的TSOverIP的要求,把每7个TS的数据包(共188*7=1316)进行IP打包即可。
    21楼  liaoqianyu 2009-12-15 09:23发表  [回复]
    请教吴先生:通过IP网络传输TS流数据,组播(Multicast)的方式是怎样进行传输的呢?需要注意哪些方面的东西?组播指的是能同时传输2路或者2路以上的ts流吗 ?
    20楼  dvb_dvb 2009-02-18 14:45发表  [回复]
    变速播放的问题先等等,目前遇到了一个支持并发流的问题: ip推流已经成功了.

    软件就是这样写的, 一个流有两个线程 和 一个buffer queue,. 一个从硬盘或者网络读数据,一个根据pcr向外发,

    如果运行这个软件是10个exe, 每个流10Mbps输出,(从两个net card输出) ,是可以的,

    但是如果把这个10个做为10个线程,在一个exe里面运行,就不行了, 磁盘碎片,硬盘速度,都考虑了,结果还是不行. 请给个意见.



    我也试过了lilve555的,同时点播4个就不行了,

    在别的电视台看了别人的vod点播.能同时点播20个, 每个也是10Mbps, (千兆交互机),还有央视高清,18mbps,

    难道他也是启动一个服务exe, 开了20个线程么? 那它是怎么管理的呢?

    请给些意见.
    19楼  wutong_login 2009-02-17 09:33发表  [回复]
    不知道你是打算二倍发送,还是二倍播放,如果是二倍发送的话,直接把发送的时间除以2即可,比如用我们上面的算法,每个144ms处理一次,这时,反把144ms除以2,即在72ms内把这些数据发完;如果说二倍播放,那就需要做两方面的工作,一是发送端的配合,因为需要的数据量增加了两倍,二是播放端要做处理。如果播放端不是自己控制的话,可能就需要手动改每帧数据DTS和PTS了。不过我还是建议在播放端进行处理。
    18楼  dvb_dvb 2009-02-15 20:13发表  [回复]
    吴先生,有时间的话,请指点一二:
    目前,一倍数就是按照pcr发了,
    那 fast foward,的二倍数播发,我已经给mepg的把所有的i b p frame的file offset给取出来了,到底发那些frame,舍弃那些frame.目前已经实现的ff (快进)是怎么做的.谢谢了.
    17楼  dvb_dvb 2009-02-09 20:10发表  [回复]
    实在抱歉,我的发帖,老重复,(因为不知道成功了没有),请删除我多余的帖子,以便整理,谢谢!
    16楼  dvb_dvb 2009-02-09 20:10发表  [回复]
    实在抱歉,我的发帖,老重复,(因为不知道成功了没有),请删除我多余的帖子,以便整理,谢谢!
    15楼  dvb_dvb 2009-02-09 20:08发表  [回复]
    你好,我发帖的时候,经常,提交不成功.
    我接着说下面的问题吧:
    目前要做ts ip 发送的快进,和快退.
    目前live555的做法是,为ts文件生成tsx的video frame的index文件.然后根据几倍数,把I frame发出去,可是占用的ip带宽太大了.
    请问一下,别的公司的FastForward是怎么做的.
    FF,到底是不是能保持带宽不变呢?
    14楼  dvb_dvb 2009-02-09 15:55发表  [回复]
    谢谢收到了,最近比较忙,看了你的code, 有很多帮助:

    首先是一个wait的动作, 你本来好像用下列code, 但是又不用了,用sleep, (这个select函数,也可以作为sleep呀,live555就是这样用的呀.你为什么不用了.我倒好像发现新大陆一样.准备用了).
    int selectResult = select(fMaxNumSockets, &readSet, NULL, NULL,
    &tv_timeToDelay);
    13楼  dvb_dvb 2009-02-09 15:52发表  [回复]
    谢谢收到了,最近比较忙,看了你的code, 有很多帮助:

    首先是一个wait的动作, 你本来好像用下列code, 但是又不用了,用sleep, (这个select函数,也可以作为sleep呀,live555就是这样用的呀.你为什么不用了.我倒好像发现新大陆一样.准备用了).
    int selectResult = select(fMaxNumSockets, &readSet, NULL, NULL, &tv_timeToDelay);
    12楼  dvb_dvb 2009-02-09 15:49发表  [回复]
    谢谢收到了,最近比较忙,看了你的code, 有很多帮助:

    首先是一个wait的动作, 你本来好像用下列code, 但是又不用了,用sleep, (这个select函数,也可以作为sleep呀,live555就是这样用的呀.你为什么不用了.我倒好像发现新大陆一样.准备用了).
    int selectResult = select(fMaxNumSockets, &readSet, NULL, NULL,
    &tv_timeToDelay);
    11楼  dvb_dvb 2009-02-09 15:48发表  [回复]
    谢谢收到了,最近比较忙,看了你的code, 有很多帮助:

    首先是一个wait的动作, 你本来好像用下列code, 但是又不用了,用sleep, (这个select函数,也可以作为sleep呀,live555就是这样用的呀.你为什么不用了.我倒好像发现新大陆一样.准备用了).
    int selectResult = select(fMaxNumSockets, &readSet, NULL, NULL,
    &tv_timeToDelay);
    10楼  wutong_login 2009-02-04 17:03发表  [回复]
    读了你的实验结论,很有启发。

    总体上来讲,我们的思路是一致。因为通过PCR也好,通过音频的DTS也好,最终的目标其实都是得到码率。因为我们知道,对于TS来讲,如果我们认为PCR是从0开始的话,那么每个PCR就是码流播放到这个包含PCR的TS包的时间,而这个TS包的位置,即播放到这个TS包时播放的总的字节数,就是距离,空间的距离。码率的问题,简单点讲,就是公式:码率(速度)=距离/时间。

    为什么说我们的思路是一致的呢?我们知道标准中规定 PCR出现的最大时间间隔不能超过40ms,通过PCR进行发送,也就是在PCR(n)-PCR(n-1)时间内把PCR(n)和PCR(n-1)之间的数据全部发送。根据上面的公式,我们有了总的字节数,有了需要发送的时间,我们可以像你说的那样计算每个TS包要发送的时间,也可以计算每16ms要发送的TS的个数。

    在文章中,我为什么没有用PCR呢,是因为在实际的应用中,遇到了一些没有PCR的码流,而通过观察和实验,我发现在有PCR的码流中,音频的DTS几乎和PCR平行(音频DTS一般大于PCR 70~100ms),也就是说音频DTS的变化基本上反映了PCR的变化,根据这个特性,不管是变码率还是恒码率,其实我们都可以使用音频DTS进行发送。当然如果音频的DTS间隔过大,则另当别论。

    另外,你提到空包过滤的问题,其实对于空包,我们不必做任何处理,只需把原来的码流结构进行发送即可,为什么要过滤空包呢?空包存在的目的之一,就是通过填充空包,可以把变码率的TS流变为恒码率,所在发送时不用特别处理。

    IP发送TS注的代码已经发送你的信箱,请查收。
    9楼  dvb_dvb 2009-02-03 10:26发表  [回复]
    经过经一步的探索, 我得到了如下的结论:
    1,你的这个思路是首先要得到码率. 可是得到很准确的码率是比较困难的.
    原因如下:
    1)目前很多的spts是通过编码器出来的, 他的码率是比较固定的,基本上很准的.
    2) 有的ts文件是通过复用器采集的.原有的4Mbps,复用后是38Mbps了,插了很多空包.
    3) 有时候觉得空包太多,把所有的空包过滤了,这个是对码流伤害最大的一种.(编码器出来的码流都有空包)
    感觉版主的这个方法并不上适合这些码流.
    你的这个是根据码率来发送的.我目前做的是根据pcr来发送的.
    当看了vlc的code后,基本上是结合码率和pcr来发送的.

    1,在调试过程中,我监测了vlc的发出的码率,基本上每16毫秒都有数据,最大不会超过32毫秒. 
    而版主的方法, 要wait很多,这个已经造成了stb的报告同步丢失.就是数据包不均匀.

    目前的做法是, 先根据码率算出每16ms大约发多少个 7 *188的包. (这个时候码率准不准无所谓,这是粗调,将来可以通过pcr来细调)
    比如码率是18Mbps的高清码率.(h264和mepg2相同) 每16ms大约发的包数为: 18000000 / 8 / (7 * 188) / (1000 * 16),假设等于XX
    这个时候一般都肯定比如是8.369,我们就取8. 也就是说,每16ms大约发的包数为8,这个是比时间的码率低些.
    然后我们每16ms找一个pcr, 然后比较系统时间(这个需要转换,详情请参考vlc),
    如果这个pcr小于发系统时间,那下次就发 (xx++) * 7 * 188, 
    如果下次找到的pcr还小那下次就发 (xx++) * 7 * 188,

    如果下次pcr大于发系统时间,那下次就发 (xx--) * 7 * 188, 
    注意xx--的最小值也是8.太小了不好.

    结果我们的stb就可以和vlc推出的流媲美了. stb也不会报错,(以前,如果我每50ms发一次,stb就有马塞克, 但vlc发,stb是没有的.)
    所有我认为版主的方法需要改进. 就写这么多吧.
    E_Mail: jishiyu2005ATyahoodotcomdotcn
    目前正在研究vlc, live555的code ,还望各位多提意见.
    8楼  wutong_login 2009-01-21 07:46发表  [回复]
    dvb_dvb,留个你的Email吧。我直接发给你。
    7楼  dvb_dvb 2008-12-29 16:17发表  [回复]
    你好,看了这个链接了,他需要银行帐号,需要vip会员. 才能下载.
    6楼  dvb_dvb 2008-12-29 16:16发表  [回复]  [引用] [举报]
    你好,看了这个链接了,他需要银行帐号,需要vip会员. 才能下载.
    5楼  dvb_dvb 2008-12-29 16:16发表  [回复]
    你好,看了这个链接了,他需要银行帐号,需要vip会员. 才能下载.
    4楼  dvb_dvb 2008-12-29 16:15发表  [回复]
    你好,看了这个链接了,他需要银行帐号,需要vip会员. 才能下载.
    3楼  wutong_login 2008-12-27 09:58发表  [回复]
    基于IP播放TS的源码,请从如下地址下载:
    http://www.pudn.com/downloads129/sourcecode/windows/multimedia/detail553057.html
    2楼  wutong_login 2008-12-27 09:57发表  [回复]
    基于IP播放TS的源码,请从如下地址下载:
    http://www.pudn.com/downloads129/sourcecode/windows/multimedia/detail553057.html
    1楼  dvb_dvb 2008-12-25 22:10发表  [回复]
    请问,您有没用类似的source code, 或者关于vlc的详细稳定.细细, 还有ts splice的问题 准备请教你, 我给你发私信了,谢谢

    你可能感兴趣的:(基于IP播放TS流的码率控制策略)