WebRTC QoS方法之Sender Side BWE实现

1.背景介绍

BWE(Bandwidth Estimation)可能是WebRTC视频引擎中最关键的模块了。BWE模块决定视频通讯中可以发送多大码率视频不会使网络拥塞,防止视频通讯质量下降。

早期的带宽评估算法比较简单,大多是基于丢包来估计,基本的策略是逐步增加发送的数据量,直到检测到丢包为止。为了让发送端获悉网络上的丢包信息,可以使用标准的RTCP的RR来发送周期性的报告。

现代的带宽评估算法则可以在网络链路发生丢包以前就监测到网络拥塞,它可以通过侦测数据包接收的时延来预测未来可能的拥塞。它是基于链路上的路由器都有一定的缓存,在数据包开始被丢弃之前,先发生数据在缓存里堆积的事件,所以时延相比于丢包,对拥塞的反应更加灵敏。

最新版本webrtc使用trendline算法实现网络拥塞预估,早期版本使用KalmanFilter算法。两种算法都是基于接收端的网络延迟进行码率估计。早期的KalmanFilter算法是在接收端根据网络延时,计算出合适的带宽,通过REMB RTCP报文反馈给发送端,让发送端按照该码率发送视频数据。trendline算法对此进行了优化,在发送端根据网络延时,计算合适的带宽。

2.实现原理

发送端码控模块结构,如上图所示。这里的remb bitrate仅做向下兼容使用。兼容老版本的KalmanFilter算法。

3. 基于丢包拥塞控制

发送端基于丢包率控制发送码率,其基本思想是:丢包率反映网络拥塞状况。如果丢包率很小或者为0,说明网络状况良好,在不超过预设最大码率的情况下,可以增大发送端码率;反之如果丢包率变大,说明网络状况变差,此时应减少发送端码率。在其它情况下,发送端码率保持不变。

WebRTC中发送端收到RTCP RR报文并解析得到丢包率后,根据下图公式计算发送端码率:当丢包率大于0.1时,说明网络发生拥塞,此时降低发送端码率;当丢包率小于0.02时,说明网络状况良好,此时增大发送端码率;其他情况下,发送端码率保持不变。

4. 基于延时拥塞控制

基于延迟的拥塞控制是通过每组包的到达时间的延迟差(delta delay)的增长趋势来判断网络是否过载,如果过载进行码率下调,如果处于平衡范围维持当前码率,如果是网络承载不饱满进行码率上调。这里有几个关键技术:包组延迟评估(InterArrival)、滤波器趋势判断(TrendlineEstimator)、过载检测(OveruseDetector)和码率调节(AimdRateControl)。

5.包组延迟评估

音频报文发送的时间间隔是按照一帧的打包时长发送的,但是视频却不能按照实际帧率发送,因为一帧视频有可能分别封装在几个RTP报文,若这个视频帧的RTP报文一起发送到网络上,必然会导致网络瞬间拥塞。以25fps为例,若这帧视频的RTP报文,能够在40ms之内发送给接收端,接收端既可以正常工作,也缓冲了网络拥塞的压力。所以计算视频的包延时,不能用单包计算,需要按照一组包(一帧视频)计算。Trendline滤波器需要的三个参数:发送时刻差值(delta_timestamp)、到达时刻差值(delta_arrival)和包组数据大小差值(delta_size)。从上图可以得出:

  • 滤波趋势判断

如果平稳网速下传输数据的延迟时间就是数据大小除以速度,如果这数据块很大,超过恒定网速下延迟上限,这意味着要它要占用其他后续数据块的传输时间,那么如此往复,网络就产生了延迟和拥塞。Trendline filter通过到达时间差、发送时间差和数据大小来得到一个趋势增长值,如果这个值越大说明网络延迟越来越严重,如果这个值越小,说明延迟逐步下降。计算公式如下:

先计算单个包组传输增长的延迟,可以记作:

然后做每个包组的叠加延迟,可以记作:

在通过累积延迟计算一个均衡平滑延迟值,alpha=0.9可以记作:

然后统一对累计延迟和均衡平滑延迟再求平均,分别记作:

我们将第i个包组的传输持续时间记作:

趋势斜率分子值为:

趋势斜率分母值为:

最终的趋势值为:

  • 过载检测

在计算得到trendline值后WebRTC通过动态阈值gamma_1进行判断拥塞程度,trendline乘以周期包组个数就是m_i,以下是判断拥塞程度的伪代码:

通过以上伪代码就可以判断出当前网络负载状态是否发生了过载,如果发生过载,WebRTC是通过一个有限状态机来进行网络状态迁徙,关于状态机细节可以参看下图:

从上图可以看出,网络状态机的状态迁徙是由于网络过载状态发生了变化,所以状态迁徙作为了aimd带宽调节的触发事件,aimd根据当前所处的网络状态进行带宽调节,其过程是处于Hold状态表示维持当前码率,处于Decr状态表示需要进行码率递减,处于Incr状态需要进行码率递增。那他们是怎么递增和递减的呢?WebRTC引入了aimd算法解决这个问题。

  • AIMD码率调节

AIMD的全称是Additive Increase Multiplicative Decrease,意思是:和式增加,积式减少。aimd controller是TCP底层的码率调节概念,但是WebRTC并没有完全照搬TCP的机制,而是设计了套自己的算法,用公式表示为:

如果处于Incr状态,增加码率的方式分为两种:一种是通信会话刚刚开始,相当于TCP慢启动,它会进行一个倍数增加,当前使用的码率乘以系数,系数是1.08;如果是持续在通信状态,其增加的码率值是当前码率在一个RTT时间周期所能传输的数据速率。

如果处于Decrease状态,递减原则是:过去500ms时间窗内的最大acked bitrate乘上系数0.85,acked bitrate通过feedback反馈过来的报文序号查找本地发送列表就可以得到。

AIMD根据上面的规则最终计算到的码率就是基于延迟拥塞评估到的bwe bitrate码率。

代码详解

1. 最终码率取基于丢包和基于延时探测的最小值

参考函数GoogCcNetworkController::MaybeTriggerOnNetworkChanged。

2. 获取码率Pacer、FEC、编码器配置原则

  • Pacer默认是探测码率的2.5倍。

  • FecControllerDefault::UpdateFecRates根据实时统计到的FEC和NACK数据量,计算出冗余数据占有量。探测码率减去冗余码率,剩下的分给编码器。

  • FEC和NACK冗余数据量根据实际需要来,不做流量限制。只是会动态调低编码器码率,降低整体数据的发送量

具体函数走读:

RtpTransportControllerSend::PostUpdates:

GoogCcNetworkController::GetPacingRates:

pacing_factor_默认2.5。也就是说pacer发送报文的码率是探测码率的2.5倍

const float PacedSender::kDefaultPaceMultiplier = 2.5f;

RtpVideoSender::OnBitrateUpdated:

根据探测码率、当前帧率、丢包率、rtt环路延时、丢包模型,更新FEC冗余度。

FecControllerDefault::UpdateFecRates:

实时获取FEC、NACK发送的数据量,计算可剩余留给编码器的码率

RtpVideoSender::ProtectionRequest:

实时获取NACK和FEC的码率

RtpSenderEgress::UpdateRtpStats:

实时更新发送数据的码率

VideoSendStreamImpl::OnBitrateUpdated:

计算并生效编码码率参数

若是仅使用WebRTC的BWE带宽估计,决定以多大码率发送报文时,会遇到如下难处:

  1. 发送端通过BWE算法,根据网络状态动态调节发送的码率。但是系统启动阶段初始码率应该设置成多大比较合适?

  2. BWE估计带宽,这个算法的特点是:快降慢升,网络质量差时能迅速响应衰减带宽;但是网络持续向好时,不能迅速增加对应带宽。

  3. 网络持续向好,BWE探测码率持续上涨,若直接把码率提升上来,会有风险。

所以需要一种快速探测算法,探测当前网络合适的带宽,保证音视频按照最佳码率值发送数据。WebRTC在探测带宽时,是probe算法和BWE算法配合使用,BWE算法仅仅是一个参考值。实际生效需要根据probe结果决定。

原文链接:WebRTC QoS方法之Sender Side BWE实现

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

猜你喜欢

转载自blog.csdn.net/yinshipin007/article/details/129939419