流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优

流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优

——
我正在的github给大家开发一个用于做实验的项目 —— github.com/qw225967/Bifrost

目标:可以让大家熟悉各类Qos能力、带宽估计能力,提供每个环节关键参数调节接口并实现一个json全配置,提供全面的可视化算法观察能力。

欢迎大家使用
——

文章目录

  • 流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优
  • 一、GCC算法部分缺点解析
    • 1.1 有线网络缺点分析
    • 1.2 局域网GCC竞争
  • 二、仿真实验
    • 2.1 实验一
      • 2.1.1 分时进入
      • 2.1.2 同时进入
    • 2.2 实验二
      • 2.2.1 分时进入
      • 2.2.2 同时进入
    • 2.3 实验三
      • 2.3.1 分时进入
      • 2.3.1 同时进入
  • 三、参数调整与优化
    • 3.1 上探与拥塞检测
      • 3.1.1 趋势窗口
      • 3.1.2 上探码率
    • 3.2 局域竞争问题
      • 调整
  • 四、总结


一、GCC算法部分缺点解析

  GCC算法是WebRTC中使用的拥塞控制算法——Google Congestion Control。WebRTC作为Chrome的P2P音视频实时通话内核,它充分利用了P2P的优势。谷歌分别在2012年——one sender-based and one receiver-based、2016年——one delay-based and one loss-based,提供了两个版本的GCC算法,最后谷歌把发送端带宽估计作为后续一直使用的最终模式。Google结合实时音视频的使用场景设计的GCC拥塞控制算法,(从接收端带宽估计到发送端带宽估计)采用了这样的思想:
  1.具备足够的敏感度;
  2.足够稳定;

  基于以上的思想,GCC的整个传输展现出了锯齿状的带宽图谱(下面是600kbps带宽限制的码率传输图):

流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第1张图片

  明显可以看出来在存在带宽瓶颈的时候,GCC算法会尝试向上探测后又继续下降,由此往复而产生了锯齿状的带宽估计形状。

1.1 有线网络缺点分析

1.高敏感度——会在触碰到600kbps的瞬间立刻触发了拥塞检测并下降码率;
2.足够稳定——上探的过程会较慢,避免编码器剧烈变化;

结合可得——过于敏感以及频繁的下调码率,很可能会导致GCC整体带宽利用率略显不足(相对现在很多利用率更高的带宽估计算法GCC确实不足)。

流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第2张图片

  给大家展示的图是荷兰 the Delft University of Technology 的一篇硕士毕业论文(这里下载)。其中描述了单条GCC流的缺陷中,第一个被提到的点就是带宽利用率的问题。
  1.GCC流在正常的带宽环境中,由于稳定的策略上探的速度很慢,需要消耗很长的时间才能到达带宽瓶颈(上图论文中计算得到的收敛时间约11s左右);
  2.到达带宽瓶颈后,从乘性增模式切换为加性增后会出现上涨更慢的情况,因此在后续网络抖动发生时会极容易触发码率下降。

1.2 局域网GCC竞争

  前段时间在进行局域网内100+的GCC流竞争过程中发现,同GCC流的竞争中会存在饿死,我对这个现象的发生极为好奇。回到上述那篇硕士论文,其中也对竞争流问题进行了分析:
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第3张图片
  文章提到的是同为GCC算法流之间的竞争公平性是非常好的。注意观察上述的图片的特点,都是从较低的启动码率开始进行增长的,这样整体很快就会实现平衡。

  这现象与我遇到的现象完全不一样!

  事情发生的环境:下行、服务器使用Mediasoup集成WebRTC中的GCC算法、参与人集中于单个路由器中,出现了下行带宽估计码率的竞争失衡问题。为了保证下行的秒开速度,我们GCC起始的码率设置是较大的~约2m。而且有一个很大的影响前提,就是屏幕分享的码率动态差距很大,字数较多的情况可以达到2mbps,但常规状态下码率又非常低只有约300kbps。
  由此我引出了一个GCC算法在使用过程中的一个问题,并且对此我进行了全面的仿真实验,验证整个算法的在传输中的异常情况。

二、仿真实验

  上述我们提到了多条GCC算流竞争的问题,在很多文章中都说GCC是一个非常公平的拥塞控制算法,事实上也是如此。但任何事物都在更新迭代,GCC算的公平性在自竞争的过程中也展现出来了一些有意思的特点。为此我们设计了以下的实验方式:

  1.双流竞争1200kbps的带宽,起始的码率都从600kbps,最大1400kbps:
    a.先进入一条流,30s后进入另一条流;
    b.两条流同时进入;

  2.双流竞争800kbps的带宽,起始的码率都从600kbps,最大1400kbps:
    a.先进入一条流,30s后进入另一条流;
    b.两条流同时进入;

  2.双流竞争1500kbps的带宽,起始的码率都从1000kbps,最大1400kbps:
    a.先进入一条流,30s后进入另一条流;
    b.两条流同时进入;

  我们将会从上述的实验中发现,不同的起始码率、甚至整个竞争过程中,GCC都会发生不同程度的变化。

2.1 实验一

2.1.1 分时进入

  下图展示了1200kbps的码率限制,先后进入GCC流的带宽估计码率以及趋势线图,整个传输过程还是非常接近于上述论文的效果的。
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第4张图片
  这是因为:发送码率在30s的时候是 1200 kbps + 600 kbps,一共溢出了 600kbp的数据。而GCC算中下调码率的速度是 ack码率的 0.85,在拥塞的一瞬间码率下调是 ack * 0.85作为新的吞吐量下调。也就是说,在第二条流进入的瞬间我们两条流的带宽占用可能是:

  1200*(1200/(1200 + 600))*0.85 = 679.9kbps。

  也就是说第一条流会立刻下降到接近一半带宽,所以整个传输的过程就会非常迅速的实现了整体传输的平衡。那么我们是不是可以得到一个很有意思的点,就是起始码率约接近平衡点的发送码率,那么整个传输过程的竞争收敛速度就越快?

2.1.2 同时进入

  下图展示了1200kbps的码率限制,两条GCC流同时进入的带宽估计码率以及趋势线图。根据我们上述的公式计算来猜测,同时进入也是会迅速的收敛到平衡的状态:
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第5张图片

  确实和我们上面提到的计算码率的公式有很大的关系,即使同时进入竞争,也会很快的趋于平衡的状态。

2.2 实验二

2.2.1 分时进入

  下图展示了800kbps的码率限制,先后进入GCC流的带宽估计码率以及趋势线图。而这次800kbps码率的中间值是400kbps,这次会影响到竞争到平衡的收敛速度。
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第6张图片

  可以看到整个传输的过程中竞争非常激烈,看右边的趋势线显示的更是抖动的非常激烈——也就是频繁的检测到拥塞情况(确实对比起来收敛的速度很慢)。

2.2.2 同时进入

  下图展示了800kbps的码率限制,两条GCC流同时进入的带宽估计码率以及趋势线图。收敛速度同样出现了问题,没有离开进行了下降。
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第7张图片

2.3 实验三

2.3.1 分时进入

  下图展示了1500kbps的码率限制,两条GCC流先后进入的带宽估计码率以及趋势线图。
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第8张图片
  结合两个起始带宽占用比较偏的情况下,整体竞争非常的激烈。但是相比于带宽比较低的情况缺稳定不少,但时常会有一条流抢到更多的带宽。

  首先为什么会出现有一条流竞争到更多的带宽的情况呢?
  答:当其中一条流检测到带宽正在向下降,另一条流在向上探测就会出现这样巧合的情况,其中一条流约占越多,另一条降越低。直到另一条流触顶下降,然后才会出现重新的平衡。
  为什么1500kbps限制看起来和800kbps限制更稳定,800kbps会剧烈的变化?
  答:因为WebRTC中GCC的码率上涨是一个固定值,800kbps的情况下很容易涨一下就溢出了码率限制。因此整个传输会出现很明显的激烈竞争。

2.3.1 同时进入

  简单展示同时进入的图:
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第9张图片

三、参数调整与优化

3.1 上探与拥塞检测

3.1.1 趋势窗口

  GCC算法的拥塞检测是TrendLine模块检测的,而计算趋势的窗口值(kDefaultTrendlineWindowSize)是一个影响比较大的参数。
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第10张图片

  在上述的探测实验中,我使用的窗口值为 80,这个值我是根据每次feedback的值使用的。例如:每次确认的delta为 15 ~ 30个,那么在最初启动的阶段会等待3次左右的feedback才会触发第一次趋势计算。而后续历史值会占用约2/3的位置,计算出来的趋势就会更稳定一些,这个大家可以根据自己的使用需求去调整自己的窗口值。

3.1.2 上探码率

  GCC上探的码率有一个最大值限制,其中会乘上一个1.5的倍率。这里我们可以调整到更大来获得一个更快的上探速度。

流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第11张图片

  这个我们可以根据自身码率的需求来调整它的上探速度,目前我测试可得:3.5左右的时候收敛速度就可以到62kbps的增长了,大家可以用上面的demo试试。

3.2 局域竞争问题

  上述的参数作为一个补充介绍给大家,我们回到局域网竞争的问题。我在测试的过程中发现,剧烈的码率变化(前面提到的屏幕共享码率问题)会导致整个GCC算法的公平性完全失效。

  例如:存在一条流曾经探测到了2mbps的带宽,而在下行传输过程中为了不让转发受限过早,我们在码率变回300kbps左右时仍然维持在Alr状态,此时整个传输过程算法并没有检测到带宽拥塞。
流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第12张图片

  假设此时另外一条流大码率进入就会出现以下情况:其中一条流2mbps发送码率,另一条300kbps发送码率。这时候网络没有出现异常,但是第一下会发送出来一帧关键帧——大约2mbps,这个关键帧就会触发所有的下行流都发送2mbps的码率,以至于造成了剧烈的拥塞就开始了,随后就会出现上述的竞争过程。

  上面的所有巧合就会同时都触发:
  1.有的流上涨、有的流检测拥塞下降,导致了部分流相差甚远;
  2.有的流分配码率低、有的流分配码率高,那么下行接收端就会一直有缺数据的终端,那么WebRTC请求关键帧的逻辑就会频发触发,进而导致强烈的拥塞发生;
  3.整正常传输的过程中,会因为一下子300kbps、一下子2mbps导致有的无数据上探时码率无法探到更高。

调整

  分析原因后,我做了以下的调整,并从GCC暴露出来的接口进行设置:
  1.去除Mediasoup原有的频繁设置gcc上探代码,解决上层对gcc探测的干扰;
  2.gcc根据码率动态调整阈值(码率越大阈值越低越敏感/反之越迟钝);
  3.gcc根据码率动态调整feedback计算窗口大小,提高计算准确度、灵敏度(码率越小越需要参考前面的数据,因为feedback数量很少);
  4.gcc根据码率动态确定是否进入alr状态(应用限制状态-无数据可探测),避免长期无数据上涨;
  5.gcc码率增长中吞吐量乘积参数调整(1.5 调整为 5.5),用于适应分享流的超大码率差值问题;
  6.gcc最小最大码设置逻辑调整为(204.8kbps/4096kbps);

流媒体弱网优化之路(WebRTC)——GCC带宽估计算法调优_第13张图片

四、总结

  经过上述的调整,我们下行的屏幕分享流可以很快的进行平衡收敛,随后在发生拥塞的过程中立刻打乱后又重新进行收敛。目的就是实现绝对的码率平均——当然这样的做法只能说是暂时的缓解了问题,大家一起讨论看看有没有更好的方式去调整GCC算法呢?

你可能感兴趣的:(mediasoup,webrtc,弱网优化,webrtc,算法)