reed-solomon纠错码在实时通信中的应用及工程实践

    网络的可靠性传输在实时通信中至关重要;就算后期做再多的处理,都不如网络传输可靠的效果好。在实际中我们经常要求低延时,低延时就带来我们的buffer特别小,buffer特别小抵抗网络抖动的能力就小,也就是发生卡顿的概率高;可以毫不客气的说,低延时和流畅率两个指标是在某些程度是互相矛盾的。为了实现低延时并且高流畅率的目标,一个牛逼的自适应buffer很重要,但是如果能做到网络不卡不掉数据,是更实际的解决工程的应用,但是理想很性感,现实很骨感;我们只能尽可能的保证网络数据的完整性。

    由于在实时通信中tcp固有的缺陷,所以在实际的工程应用中基本上都是udp方式进行网络传输;udp在网络传输中不能保证可靠性,经常丢包、乱序;乱序还好解决,关键是丢包,所以可以得出这么一个结论:解决丢包问题时udp可靠性传输的关键问题。常用的抵抗丢包的方法是fec、nack。

    抵抗丢包是我们接下来研究的重点,抵抗丢包可以分为两种情况,一个是网络rtt很低,一个是rtt很高;很高和很低两个词说得太轻松,不能量化,说了等于没说;现在我们定义一下啥就叫很低,啥就很高,从根本上说符合用户真实感受的才是标准;自己瞎定义一个没用,人家也不认。在这篇文章里面我们定义:如果你的rtt高于期望延时(200ms)就叫高,小于期望延时的一半就叫很低。如果你的rtt高于期望延时了,包没收到,你如果怎么从发送方要数据都会高于这个延时,如果rtt小于期望延时的一半你有两次机会重新要包。

    先来理解在rtt很低的时候,我们可以通过nack向发送发请求重发包基本上可以抵抗丢包;恢复的比率很高,比如你的网络50%的丢包,我有两次请求的机会,基本上可以恢复。

    在rtt很高的时候怎么办呢,更痛苦的是移动网络很大部分情况都是rtt会超过我们要求的实时通信(200ms),我们视频编码又都是基于gop的,如果丢了一个包没有恢复这个gop的就废掉了;这种概率就相当于gop有100个包,任何一个包丢了就废了。fec是我们抵抗rtt很高情况下的丢包的方法,fec的方法的好坏会直接影响到实际的流畅率大盘。

    flexfec、ulpfec都是基于xor的,这种fec在实际的应用中通过理论分析和实际埋点分析抵抗网络丢包的能力很弱;举个例子:50%的冗余,理论上可以抵抗33%(1/3)的丢包,实际网络中经常一丢不是一个而是附近的好几个;这种丢包情况下基于xor的fec是无法抵抗的。

    划重点,分析了不能用的,就要给出能用的;通过研究reed-solomon纠错算法,发现这种算法非常适用于多丢包的情况下的恢复。它可以做到任意k个原始包加上r个冗余包,可以抵抗r个数据的丢包;比如50%的冗余,理论上可以抵抗33%的丢包率,k=16,r=8,也就是只要这24个包收到了16个就可以恢复原始的16的包,就是这么强大。我们在实际应用中发现在rtt=500ms,30%的丢包情况下,基于xor的基本上很卡,当时基于reed-solomon的一点也不卡。

    开源的rsfec代码库:https://github.com/wangjinzhouqw/reed-solomon-fec.git

你可能感兴趣的:(实时通信,学习之路)