导语 | 本文为大家详细解读一下WebRTC中Sender Side BWE的实现。文章中引用的WebRTC代码基于master,commit:f412945f05ce1ac372a7dad77d85498d23deaae源码分析。
背景介绍
BWE(Bandwidth Estimation)可能是WebRTC视频引擎中最关键的模块了。BWE模块决定视频通讯中可以发送多大码率视频不会使网络拥塞,防止视频通讯质量下降。
早期的带宽评估算法比较简单,大多是基于丢包来估计,基本的策略是逐步增加发送的数据量,直到检测到丢包为止。为了让发送端获悉网络上的丢包信息,可以使用标准的RTCP的RR来发送周期性的报告。
现代的带宽评估算法则可以在网络链路发生丢包以前就监测到网络拥塞,它可以通过侦测数据包接收的时延来预测未来可能的拥塞。它是基于链路上的路由器都有一定的缓存,在数据包开始被丢弃之前,先发生数据在缓存里堆积的事件,所以时延相比于丢包,对拥塞的反应更加灵敏。
最新版本webrtc使用trendline算法实现网络拥塞预估,早期版本使用KalmanFilter算法。两种算法都是基于接收端的网络延迟进行码率估计。早期的KalmanFilter算法是在接收端根据网络延时,计算出合适的带宽,通过REMB RTCP报文反馈给发送端,让发送端按照该码率发送视频数据。trendline算法对此进行了优化,在发送端根据网络延时,计算合适的带宽。
实现原理
发送端基于丢包率控制发送码率,其基本思想是:丢包率反映网络拥塞状况。如果丢包率很小或者为0,说明网络状况良好,在不超过预设最大码率的情况下,可以增大发送端码率;反之如果丢包率变大,说明网络状况变差,此时应减少发送端码率。在其它情况下,发送端码率保持不变。
WebRTC中发送端收到RTCP RR报文并解析得到丢包率后,根据下图公式计算发送端码率:当丢包率大于0.1时,说明网络发生拥塞,此时降低发送端码率;当丢包率小于0.02时,说明网络状况良好,此时增大发送端码率;其他情况下,发送端码率保持不变。
基于延迟的拥塞控制是通过每组包的到达时间的延迟差(delta delay)的增长趋势来判断网络是否过载,如果过载进行码率下调,如果处于平衡范围维持当前码率,如果是网络承载不饱满进行码率上调。这里有几个关键技术:包组延迟评估(InterArrival)、滤波器趋势判断(TrendlineEstimator)、过载检测(OveruseDetector)和码率调节(AimdRateControl)。
音频报文发送的时间间隔是按照一帧的打包时长发送的,但是视频却不能按照实际帧率发送,因为一帧视频有可能分别封装在几个RTP报文,若这个视频帧的RTP报文一起发送到网络上,必然会导致网络瞬间拥塞。以25fps为例,若这帧视频的RTP报文,能够在40ms之内发送给接收端,接收端既可以正常工作,也缓冲了网络拥塞的压力。所以计算视频的包延时,不能用单包计算,需要按照一组包(一帧视频)计算。Trendline滤波器需要的三个参数:发送时刻差值(delta_timestamp)、到达时刻差值(delta_arrival)和包组数据大小差值(delta_size)。从上图可以得出:
先计算单个包组传输增长的延迟,可以记作:
然后做每个包组的叠加延迟,可以记作:
在通过累积延迟计算一个均衡平滑延迟值,alpha=0.9可以记作:
然后统一对累计延迟和均衡平滑延迟再求平均,分别记作:
我们将第i个包组的传输持续时间记作:
趋势斜率分母值为:
最终的趋势值为:
通过以上伪代码就可以判断出当前网络负载状态是否发生了过载,如果发生过载,WebRTC是通过一个有限状态机来进行网络状态迁徙,关于状态机细节可以参看下图:
从上图可以看出,网络状态机的状态迁徙是由于网络过载状态发生了变化,所以状态迁徙作为了aimd带宽调节的触发事件,aimd根据当前所处的网络状态进行带宽调节,其过程是处于Hold状态表示维持当前码率,处于Decr状态表示需要进行码率递减,处于Incr状态需要进行码率递增。那他们是怎么递增和递减的呢?WebRTC引入了aimd算法解决这个问题。
如果处于Incr状态,增加码率的方式分为两种:一种是通信会话刚刚开始,相当于TCP慢启动,它会进行一个倍数增加,当前使用的码率乘以系数,系数是1.08;如果是持续在通信状态,其增加的码率值是当前码率在一个RTT时间周期所能传输的数据速率。
如果处于Decrease状态,递减原则是:过去500ms时间窗内的最大acked bitrate乘上系数0.85,acked bitrate通过feedback反馈过来的报文序号查找本地发送列表就可以得到。
AIMD根据上面的规则最终计算到的码率就是基于延迟拥塞评估到的bwe bitrate码率。
代码详解
参考函数GoogCcNetworkController::MaybeTriggerOnNetworkChanged。
具体函数走读:
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带宽估计,决定以多大码率发送报文时,会遇到如下难处:
所以需要一种快速探测算法,探测当前网络合适的带宽,保证音视频按照最佳码率值发送数据。WebRTC在探测带宽时,是probe算法和BWE算法配合使用,BWE算法仅仅是一个参考值。实际生效需要根据probe结果决定。
关于云架构平台部
云架构平台部是腾讯规模最大的技术部门之一,长期深耕音视频、存储、接入和计算服务等技术领域,通过海量的存储和数据库平台,世界级的CDN&音视频服务,先进的操作系统和视频编解码技术,助力腾讯云以技术的力量持续赋能客户,帮他们提升效率,降低成本。
WebRTC相关资源汇总
为了方便广大开发者快速了解上手WebRTC,我们对WebRTC相关的开源项目、工作招聘、测试工具以及行业内的RTC厂商资源进行了汇总。感兴趣的同学可以点击「阅读原文」前往 https://github.com/webrtcwork/webrtcwork 全面了解WebRTC相关内容。
腾讯云音视频在音视频领域已有超过21年的技术积累,持续支持国内90%的音视频客户实现云上创新,独家具备 RT-ONE™ 全球网络,在此基础上,构建了业界最完整的 PaaS 产品家族,并通过腾讯云视立方 RT-Cube™ 提供All in One 的终端SDK,助力客户一键获取众多腾讯云音视频能力。腾讯云音视频为全真互联时代,提供坚实的数字化助力。