WebRTC 基于GCC的拥塞控制(下)
转自;http://blog.csdn.net/ljh081231/article/details/79152578
本文在文章[1]的基础上,从源代码实现角度对WebRTC的GCC算法进行分析。主要内容包括: RTCP RR的数据源、报文构造和接收,接收端基于数据包到达延迟的码率估计,发送端码率的计算以及生效于目标模块。
拥塞控制是实时流媒体应用的重要服务质量保证。通过本文和文章[1][2],从数学基础、算法步骤到实现细节,对WebRTC的拥塞控制GCC算法有一个全面深入的理解,为进一步学习WebRTC奠定良好基础。
1 GCC算法框架再学习
本节内容基本上是文章[1]第1节的复习,目的是再次复习GCC算法的主要框架,梳理其算法流程中的数据流和控制流,以此作为后续章节的行文提纲。GCC算法的数据流和控制流如图1所示。

对发送端来讲,GCC算法主要负责两件事:1)接收来自接收端的数据包信息反馈,包括来自RTCP RR报文的丢包率和来自RTCP REMB报文的接收端估计码率,综合本地的码率配置信息,计算得到目标码率A。2)把目标码率A生效于目标模块,包括PacedSender模块,RTPSender模块和ViEEncoder模块等。
对于接收端来讲,GCC算法主要负责两件事:1)统计RTP数据包的接收信息,包括丢包数、接收RTP数据包的最高序列号等,构造RTCP RR报文,发送回发送端。2)针对每一个到达的RTP数据包,执行基于到达时间延迟的码率估计算法,得到接收端估计码率,构造RTCP REMB报文,发送回发送端。
由此可见,GCC算法由发送端和接收端配合共同实现,接收端负责码率反馈数据的生成,发送端负责根据码率反馈数据计算目标码率,并生效于目标模块。本文接下来基于本节所述的GCC算法的四项子任务,分别详细分析之。
2 RTCP RR报文构造及收发
关于WebRTC上的RTP/RTCP协议的具体实现细节,可参考文章[3]。本节主要从RR报文的数据流角度,对其数据源、报文构造和收发进行分析。其数据源和报文构造如图2所示,报文接收和作用于码率控制模块如图3所示。
在数据接收端,RTP数据包从Network线程到达Worker线程,经过Call对象,VideoReceiveStream对象到达RtpStreamReceiver对象。在该对象中,主要执行三项任务:1)接收端码率估计;2) 转发RTP数据包到VCM模块;3)接收端数据统计。其中1)是下一节的重点,2)是RTP数据包进一步组帧和解码的地方;3)是统计RTP数据包接收信息,作为RTCP RR报文和其他数据统计模块的数据来源,是我们本节重点分析的部分。
在RtpStreamReceiver对象中,RTP数据包经过解析得到头部信息,作为输入参数调用ReceiveStatistianImpl::IncomingPacket()。该函数中分别调用UpdateCounters()和NotifyRtpCallback(),前者用来更新对象内部的统计信息,如接收数据包计数等,后者用来更新RTP回调对象的统计信息,该信息用来作为getStats调用的数据源。

RTCP发送模块在ModuleProcess线程中工作,RTCP报文周期性发送。当线程判断需要发送RTCP报文时,调用SendRTCP()进行发送。接下来调用PrepareReport()准备各类型RTCP报文的数据。对于我们关心的RR报文,会调用AddReportBlock()获取数据源并构造ReportBlock对象:该函数首先通过ReceiveStatistianImpl::GetStatistics()拿到类型为RtcpStatistics的数据源,然后以此填充ReportBlock对象。GetStatistics()会调用CalculateRtcpStatistics()计算ReportBlock的每一项数据,包括丢包数、接收数据包最高序列号等。ReportBlock对象会在接下来的报文构造环节通过BuildRR()进行序列化。RTCP报文进行序列化之后,交给Network线程进行网络层发送。

在发送端(即RTCP报文接收端),RTCP报文经过Network线程到达Worker线程,最后到达ModuleRtpRtcpImpl模块调用IncomingRtcpPacket()进行报文解析工作。解析完成以后,调用TriggerCallbacksFromRTCPPackets()反馈到回调模块。在码率估计方面,会反馈到BitrateController模块。ReportBlock消息最终会到达BitrateControllerImpl对象,进行下一步的目标码率确定。
至此,关于RTCP RR报文在拥塞控制中的执行流程分析完毕。
3 接收端基于延迟的码率估计
接收端基于数据包到达延迟的码率估计是整个GCC算法最复杂的部分,本节在分析WebRTC代码的基础上,阐述该部分的实现细节。
接收端基于延迟码率估计的基本思想是:RTP数据包的到达时间延迟m(i)反映网络拥塞状况。当延迟很小时,说明网络拥塞不严重,可以适当增大目标码率;当延迟变大时,说明网络拥塞变严重,需要减小目标码率;当延迟维持在一个低水平时,目标码率维持不变。其主要由三个模块组成:到达时间滤波器,过载检查器和速率控制器。
在实现上,WebRTC定义该模块为远端码率估计模块RemoteBitrateEstimator,整个模块的工作流程如图4所示。需要注意的是,该模块需要RTP报文扩展头部abs-send-time的支持,用以记录RTP数据包在发送端的绝对发送时间,详细请参考文献[4]。

接收端收到RTP数据包后,经过一系列调用到RtpStreamReceiver对象,由该对象调用远端码率估计模块的总控对象RemoteBitrateEstimatorAbsSendTime,由该对象的总控函数IncomingPacketInfo()负责整个码率估计流程,如图4所示,算法从左到右依次调用子对象的功能函数。
总控函数首先调用InterArrival::ComputeDeltas()函数,用以计算相邻数据包组的到达时间相对延迟,该部分对应文章[1]的3.1节内容。在计算到达时间相对延迟时,用到了RTP报文头部扩展abs-send-time。另外,实现细节上要注意数据包组的划分,以及对乱序和突发时间的处理。
接下来算法调用OveruseEstimator::Update()函数,用以估计数据包的网络延迟,该部分对应文章[1]的3.2节内容。对网络延迟的估计用到了Kalman滤波,算法的具体细节请参考文章[2]。Kalman滤波的结果为网络延迟m(i),作为下一阶段网络状态检测的输入参数。
算法接着调用OveruseDetector::Detect(),用来检测当前网络的拥塞状况,该部分对应文章[1]的3.2节内容。网络状态检测用当前网络延迟m(i)和阈值gamma_1进行比较,判断出overuse,underuse和normal三种网络状态之一。在算法细节上,要注意overuse的判定相对复杂一些:当m(i) > gamma_1时,计算处于当前状态的持续时间t(ou),如果t(ou) > gamma_2,并且m(i) > m(i-1),则发出网络过载信号Overuse。如果m(i)小于m(i-1),即使高于阀值gamma_1也不需要发出过载信号。在判定网络拥塞状态之后,还要调用UpdateThreshold()更新阈值gamma_1。
算法接着调用AimdRateControl::Update()和UpdateBandwidthEstimate()函数,用以估计当前网络状态下的目标码率Ar,该部分对应文章[1]的3.3节。算法基于当前网络状态和码率变化趋势有限状态机,采用AIMD(Additive Increase Multiplicative Decrease)方法计算目标码率,具体计算公式请参考文章[1]。需要注意的是,当算法处于开始阶段时,会采用Multiplicative Increase方法快速增加码率,以加快码率估计速度。
此时,我们已经拿到接收端估计的目标码率Ar。接下来以Ar为参数调用VieRemb对象的OnReceiveBitrateChange()函数,发送REMB报文到发送端。REMB报文会推送到RTCP模块,并设置REMB报文发送时间为立即发送。关于REMB报文接下来的发送和接收流程,和第1节描述的RTCP报文一般处理流程是一样的,即经过序列化发送到网络,然后发送端收到以后,反序列化出描述结构,最后通过回调函数到达发送端码率控制模块BitrateControllerImpl。
至此,接收端基于延迟的码率估计过程描述完毕。
4 发送端码率计算及生效
在发送端,目标码率计算和生效是异步进行的,即Worker线程从RTCP接收模块经回调函数拿到丢包率和REMB码率之后,计算得到目标码率A;然后ModuleProcess线程异步把目标码率A生效到目标模块如PacedSender和ViEEncoder等。下面分别描述码率计算和生效过程。

码率计算过程如图5所示:Worker线程从RTCPReceiver模块经过回调函数拿到RTCP RR报文和REMB报文的数据,到达BitrateController模块。RR报文中的丢包率会进入Update()函数中计算码率,码率计算公式如文章[1]第2节所述。然后算法流程进入CapBitrateToThreshold()函数,和配置的最大最小码率和远端估计码率进行比较后,确定最终目标码率。而REMB报文的接收端估计码率Ar则直接进入CapBitrateToThreshold()函数参与目标码率的确定。目标码率由文章[1]的3.4节所示公式进行确定。需要注意的是,RR报文和REMB报文一般不在同一个RTCP报文里。

发送端码率生效过程如图6所示:ModuleProcess线程调用拥塞控制总控对象CongestionController周期性从码率控制模块BitrateControllerImpl中获取当前最新目标码率A,然后判断目标码率是否有变化。若是,则把最新目标码率设置到相关模块中,主要包括PacedSender模块,RTPSender模块和ViEEncoder模块。
对于PacedSender模块,设置码率主要是为了平滑RTP数据包的发送速率,尽量避免数据包Burst造成码率波动。对于RTPSender模块,设置码率是为了给NACK模块预留码率,如果预留码率过小,则在某些情况下对于NACK报文请求选择不响应。对于ViEEncoder模块,设置码率有两个用途:1)控制发送端丢帧策略,根据设定码率和漏桶算法决定是否丢弃当前帧。2)控制编码器内部码率控制,设定码率作为参数传输到编码器内部,参与内部码率控制过程。
至此,发送端码率计算和生效过程分析完毕。
5 总结
本文结合文章[1],深入WebRTC代码内部,详细分析了WebRTC的GCC算法的实现细节。通过本文,对WebRTC的代码结构和拥塞控制实现细节有了更深层次的理解,为进一步学习WebRTC奠定良好基础。
WebRTC 基于GCC的拥塞控制(下)的更多相关文章
- WebRTC 基于GCC的拥塞控制(上)
转自:http://blog.csdn.net/doitsjz/article/details/56481981 实时流媒体应用的最大特点是实时性,而延迟是实时性的最大敌人.从媒体收发端来讲,媒体数据 ...
- 【转载】WebRTC基于GCC的拥塞控制(上) - 算法分析
实时流媒体应用的最大特点是实时性,而延迟是实时性的最大敌人.从媒体收发端来讲,媒体数据的处理速度是造成延迟的重要原因:而从传输角度来讲,网络拥塞则是造成延迟的最主要原因.网络拥塞可能造成数据包丢失,也 ...
- WebRTC基于GCC的拥塞控制算法[转载]
实时流媒体应用的最大特点是实时性,而延迟是实时性的最大敌人.从媒体收发端来讲,媒体数据的处理速度是造成延迟的重要原因:而从传输角度来讲,网络拥塞则是造成延迟的最主要原因.网络拥塞可能造成数据包丢失,也 ...
- 基于jQuery美化联动下拉选择框
今天给大家介绍一款基于jQuery美化联动下拉选择框.这款下下拉选择框js里自带了全国所有城市的数数库.下拉选择框适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲 ...
- 基于jQuery动画二级下拉导航菜单
春节回来给大家分享一款基于jQuery动画二级下拉导航菜单.鼠标经过的时候以动画的形式出现二级导航.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div id=" ...
- 基于CSS3金属风格下拉菜单
基于CSS3金属风格下拉菜单,css,金属风格,下拉菜单,CSS3导航. css3按钮:http://www.huiyi8.com/css3/anniu/
- 基于Zepto移动端下拉加载(刷新),上拉加载插件开发
写在前面:本人水平有限,有什么分析不到位的还请各路大神指出,谢谢. 这次要写的东西是类似于<今日头条>的效果,下拉加载上啦加载,这次做的效果是简单的模拟,没有多少内容,下面是今日头条的移动 ...
- 基于GCC的openMP学习与测试
(一).openMP简述 Open Multiprocessing (OpenMP) 框架是一种功能极为强大的规范,可以帮助您利用 C.C++ 和 Fortran 应用程序中的多个核心带来的好处,是基 ...
- 基于iscroll.js实现下拉刷新和上拉加载特效
现在已经不是纯Android独霸天下的时代了,H5嵌入Android的Hybrid混合开发是大势所趋.今天给大家带来的就是移动端中常见的"上拉刷新,下拉加载"特效,这个特效将会基于 ...
随机推荐
- IDEA & Android Studio换主题背景
IDEA系列主题 http://www.riaway.com/index.phphttp://color-themes.com/?view=index 详细用法: https://www.jiansh ...
- 把任意exe程序注册成windows系统服务
某gae代理软件每次开机都需要手动启动,就算添加成开机启动项,在win8.1下权限的管理更加严格,开机时并不能成功启动软件(无人值守时开机),因此在网上搜索把exe注册成系统服务的办法,找到论坛两个帖 ...
- .NetCore生产环境下构建Consul(单个DC数据中心)的服务器健康检查
下载最新的consul程序 consul 启动方式有两种 server 和client 默认是client 如果你不需要记录数据可以用 consul agent -dev 来启动 consul age ...
- MVC 区域路
VS2013和VS2015中MVC 区域路由匹配顺序相反 创建测试工程 分别在vs2013和vs2015中创建mvc项目,并创建First.Second.Three三个Area,每个Area下面创 ...
- form表单自动提交
form表单提交是web项目中经常遇到的,但是如果form中只有一个input为text类型的输入框时, 需要格外注意,因为这时候只要你按下回车键,form表单就会自动提交,这是form表单的一个特性 ...
- 005.基于docker部署etcd集群部署
一 环境准备 ntp配置:略 #建议配置ntp服务,保证时间一致性 etcd版本:v3.3.9 防火墙及SELinux:关闭防火墙和SELinux 名称 地址 主机名 备注 etcd1 172.24. ...
- Web大前端面试题-Day1
1. var的变量提升的底层原理是什么? JS引擎的工作方式是:1) 先解析代码,获取所有被声明的变量:2)然后在运行.也就是说分为预处理和执行两个阶段. 变量提升:所有变量的声明语句都会被提升到代码 ...
- 2977 二叉堆练习1 codevs
题目描述 Description 已知一个二叉树,判断它是否为二叉堆(小根堆) 输入描述 Input Description 二叉树的节点数N和N个节点(按层输入) 输出描述 Output Descr ...
- Codeforces.314E.Sereja and Squares(DP)
题目链接 http://www.cnblogs.com/TheRoadToTheGold/p/8443668.html \(Description\) 给你一个擦去了部分左括号和全部右括号的括号序列, ...
- Hystrix简单介绍
Netflix的Hystrix是一个帮助解决分布式系统交互超时处理和容错的类库,同样拥有保护系统的能力. 服务隔离 服务降级 1.服务隔离 在一个系统中,一个业务通常会依赖多个服务,且这若干个服务的调 ...