实时流媒体应用的最大特色是实时性,而延迟是实时性的最大敌人。从媒体收发端来说,媒体数据的处理速度是形成延迟的重要缘由;而从传输角度来说,网络拥塞则是形成延迟的最主要缘由。网络拥塞可能形成数据包丢失,也可能形成数据传输时间变长,延迟增大。web
拥塞控制是实时流媒体应用质量保证(QoS)的重要手段之一,它在缓解网络拥堵、减少网络延迟、平滑数据传输等质量保证方面发挥重要做用。WebRTC通控制发送端数据发送码率来达到控制网络拥塞的目的,其采用谷歌提出的拥塞控制算法(Google Congestion Control,简称GCC[1])来控制发送端码率。算法
本文是关于WebRTC拥塞控制算法GCC的上半部分,主要集中于对算法的理论分析,力图对WebRTC的QoS有一个全面直观的认识。在下半部分,将深刻WebRTC源代码内部,仔细分析GCC的实现细节。网络
Google关于GCC的RFC文档在文献[1],该RFC目前处于草案状态,尚未成为IETF的正式RFC。此外,Google陆续发布了一系列论文[2][3][4]来论述该算法的实现细节,以及其在Google Hangouts、WebRTC等产品中的应用。本文主要根据这些文档资料,从理论上学习GCC算法。学习
GCC算法分两部分:发送端基于丢包率的码率控制和接收端基于延迟的码率控制。如图1所示编码
图1 GCC算法总体结构spa
基于丢包率的码率控制运行在发送端,依靠RTCP RR报文进行工做。WebRTC在发送端收到来自接收端的RTCP RR报文,根据其Report Block中携带的丢包率信息,动态调整发送端码率As。基于延迟的码率控制运行在接收端,WebRTC根据数据包到达的时间延迟,经过到达时间滤波器,估算出网络延迟m(t),而后通过过载检测器判断当前网络的拥塞情况,最后在码率控制器根据规则计算出远端估计最大码率Ar。获得Ar以后,经过RTCP REMB报文返回发送端。发送端综合As、Ar和预配置的上下限,计算出最终的目标码率A,该码率会做用到Encoder、RTP和PacedSender等模块,控制发送端的码率。code
GCC算法在发送端基于丢包率控制发送码率,其基本思想是:丢包率反映网络拥塞情况。若是丢包率很小或者为0,说明网络情况良好,在不超过预设最大码率的状况下,能够增大发送端码率;反之若是丢包率变大,说明网络情况变差,此时应减小发送端码率。在其它状况下,发送端码率保持不变。orm
GCC使用的丢包率根据接收端RTP接收统计信息计算获得,经过RTCP RR报文中返回给发送端。RTCP RR报文统计接收端RTP接收信息,如Packet Loss,Jitter,DLSR等等,如图2所示:blog
图2 RTCP RR报文结构[5]ci
图3 GCC基于丢包率的码率计算公式[4]
最终码率会做用于Encoder、RTP和PacedSender模块,用以在编码器内部调整码率和平滑发送端发送速率。
GCC算法在接收端基于数据包到达延迟估计发送码率Ar,而后经过RTCP REMB报文反馈到发送端,发送端把Ar做为最终目标码率的上限值。其基本思想是: RTP数据包的到达时间延迟m(i)反映网络拥塞情况。当延迟很小时,说明网络拥塞不严重,能够适当增大目标码率;当延迟变大时,说明网络拥塞变严重,须要减少目标码率;当延迟维持在一个低水平时,目标码率维持不变。
基于延时的拥塞控制由三个主要模块组成:到达时间滤波器,过载检查器和速率控制器;除此以外还有过载阈值自适应模块和REMB报文生成模块,如图1所示。下面分别论述其工做过程。
该模块用以计算相邻相邻两个数据包组的网络排队延迟m(i)。数据包组定义为一段时间内连续发送的数据包的集合。一系列数据包短期里连续发送,这段时间称为突发时间,建议突发时间为5ms。不建议在突发时间内的包间隔时间作度量,而是把它们作为一组来测量。经过相邻两个数据包组的发送时间和到达时间,计算获得组间延迟d (i)。组间延迟示意图及计算公式如图4所示:
T(i)是第i个数据包组中第一个数据包的发送时间,t(i)是第i个数据包组中最后一个数据包的到达时间。帧间延迟经过以下公式计算获得:
d(i) = t(i) – t(i-1) – (T(i) – T(i-1)) (3.1.1)
公式1.3.1是d(i)的观测方程。另外一方面,d(i)也可由以下状态方程获得:
d(i) = dL(i)/C(i) + w(i) (3.1.2) d(i) = dL(i)/C(i) + m(i) + v(i) (3.1.3)
其中dL(i)表示相邻两帧的长度差,C(i)表示网络信道容量,m(i)表示网络排队延迟,v(i)表示零均值噪声。m(i)便是咱们要求得的网络排队延迟。经过Kalman Filter能够求得该值。具体计算过程请参考文献[1][4][6]。
该模块以到达时间滤波器计算获得的网络排队延迟m(i)为输入,结合当前阈值gamma_1,判断当前网络是否过载。判断算法如图5所示[2]。
图5 过载检测器伪代码
须要注意的是,阀值gamma_1对算法的影响很大,而且阈值gamma_1是自适应性的。若是其是静态值,会带来一系列问题,详见文献[4]。因此gamma_1须要动态调整来达到良好的表现。这就是图1中的Adaptive threshould模块。阈值gamma_1动态更新的公式以下:
gamma_1(i) = gamma_1(i-1) + (t(i)-t(i-1)) * K(i) * (|m(i)|-gamma_1(i-1)) (3.2.4)
当|m(i)|>gamma_1(i-1)时增长gamma_1(i),反之减少gamma_1(i),而当|m(i)|– gamma_1(i) >15,建议gamma_1(i)不更新。K(i)为更新系数,当|m(i)|<gamma_1(i-1)时K(i) = K_d,不然K(i) = K_u。同时建议gamma_1(i)控制在[6,600]区间。过小的值会致使探测器过于敏感。建议增长系数要大于减小系数K_u > K_d。文献[1]给出的建议值以下:
gamma_1(0) = 12.5 ms gamma_2 = 10 ms K_u = 0.01 K_d = 0.00018
该模块以过载检测器给出的当前网络状态s为输入,首先根据图7所示的有限状态机判断当前码率的变化趋势,而后根据图8所示的公式计算目标码率Ar。
图7 目标码率Ar变化趋势有限状态机
当前网络过载时,目标码率处于Decrease状态;当前网络低载时,目标码率处于Hold状态;当网络正常时,处于Decrease状态时迁移到Hold状态,处于Hold/Increase状态时都迁移到Increase状态。当判断出码率变化趋势后,根据图8所示公式进行计算目标码率。
图8 目标码率Ar计算公式
REMB报文每秒发送一次,当Ar(i) < 0.97 * Ar(i-1)时则当即发送。
发送端最终目标码率的肯定结合了基于丢包率计算获得的码率As和基于延迟计算获得的码率Ar。此外,在实际实现中还会配置目标码率的上限值和下限值。综合以上因素,最终目标码率肯定以下:
target_bitrate = max( min( min(As, Ar), Amax), Amin) (3.4.1)
目标码率肯定以后,分别设置到Encoder模块和PacedSender模块。
本文在普遍调研WebRTC GCC算法的相关RFC和论文的基础上,全面深刻学习GCC算法的理论分析,以此为契机力图对WebRTC的QoS有一个全面直观的认识。为未来深刻WebRTC源代码内部分析GCC的实现细节奠基基础。