介绍
《 A Google Congestion Control Algorithm for Real-Time Communication on the World Wide Web (2012) 》 描述两种用于 RTCWEB 的拥塞控制方法:one sender-based and one receiver-based 。
《 A Google Congestion Control Algorithm for Real-Time Communication (2016) 》 描述两种用于 RTCWEB 的拥塞控制方法:one delay-based and one loss-based 。
通过阅读两文不难发现:
loss-based controller 通常在 sender 实现
-
delay-based controller 既可以在 sender 实现 也可以 在 receviver 实现
delay-based controller 在 sender 实现时,依赖 receviver 反馈 I-D.holmer-rmcat-transport-wide-cc-extensions (TWCC)消息, TWCC 消息包含 receviver 收到的 一个 transport-wide 的所有 packets 的 arrival time 。
delay-based controller 在 receviver 实现时,依赖 RTP Packet 头扩展 abs-send-time 传递 packet 的 send-time,且 receviver 使用 I-D.alvestrand-rmcat-remb(REMB) 消息将 delay-based controller 输出的 bitrate 反馈给 sender,从而完成 remote delay-based congestion control 。
sender-based :实际上是 loss-based controller 的实现。
receiver-based :实际上便是 delay-based controller 在 receviver 的实现。在 2012 的版本中,暂未提供 delay-based controller 在 sender 的实现,而在 2016 的版本中进行了补充。
本文主要记录对 《 A Google Congestion Control Algorithm for Real-Time Communication (2016) 》的学习翻译,并有可能加入部分个人理解,个人理解难免有误,请多指教。
GCC in 2016 draft
摘要
本文档描述了两种用于 RTCWEB 的拥塞控制方法:one delay-based and one loss-based 。
介绍
拥塞控制是共享 internet 资源的所有应用程序的需求。
为实时流媒体进行拥塞控制是一个极大的挑战,主要涉及以下原因:
- 媒体编码通常是以某些形式(不能快速改变适应带宽变化)进行编码,这对带宽的需求通常只能以离散的、相当大的跨度进行更改。
- 参与者可能对如何回应拥塞有某些特定的愿望:比如可能不会减少 出现拥塞的流 所需的带宽 (例如:优先保障音频) 。
- 编码通常对数据包丢失很敏感,然而由于实时性的要求,通常不会采用重传来修复丢包。
本文档描述了两种拥塞控制算法,它们一起能够与使用相同拥塞控制算法(即本文描述的两种拥塞控制算法)的其他音视频流以及共享相同链路的 TCP 流提供良好的性能和合理的带宽共享。
使用的信令包括实验性(即非标准,GCC定义的) RTP 头扩展和 RTCP 消息 [RFC3550] 。
数学符号
Syntax | Description |
---|---|
X_hat | 变量 X 的真实值的估计,通常在变量名的顶部用一个抑扬符标记(拉丁文字的扬抑符是个山形符号 ( ˆ )、而希腊文的扬抑符则可以是波浪号 ( ˜ ) 或反转的短音符 ( ̑ ))。后文会出现例如:A_hat,As_hat 表示 A的估计值,As的估计值 等 。 |
X(i) | 向量 X 的第 i 个值 |
E{X} | 随机变量 X 的期望值 |
拥塞控制系统模型
拥塞控制系统中包含以下要素:
要素 | 说明 |
---|---|
RTP packet | 一个包含媒体数据的 RTP 包 |
Group of packets | 由 absolute send time(abs-send-time :"RTP Header Extension for Absolute Sender Time")唯一标识的从发送方发送的一组 RTP 数据包。这组RTP包可能是 video 包,audio 包,也可能是一组混合 video 和 audio 的包。 |
Incoming media stream | 由 RTP 包组成的 帧 组成的 流。 |
RTP sender | 通过网络将 RTP stream 发送至 RTP 接收者。由 RTP sender 生成 RTP timestamp 和 abs-send-time 的头扩展。 |
RTP receiver | 接收 RTP stream。记录到达时间。 |
RTCP sender at RTP receiver | RTP 接收端的 RTCP 发送者,发送接收端的reports,REMB messages 和 transport-wide RTCP feedback messages |
RTCP receiver at RTP sender | RTP 发送端的 RTCP 接收者,接收接收端的reports,REMB messages 和 transport-wide RTCP feedback messages;并将这些信息上报给sender侧的controller。 |
RTCP sender at RTP sender | RTP发送端的RTCP发送者,发送发送端的reports |
RTCP receiver at RTP receiver | RTP接收端的RTCP接收者,接收发送端的reports |
Loss-based controller | 根据 丢包率,往返时间(RTT),Delay-based controller 建议的 bitrate,计算目标发送比特率。 |
Delay-based controller | 在 RTP 接收器(在接收端实现时) 或 从来自发送者的 RTP 反馈(TWCC消息)中(在发送端实现时)获取数据包到达信息,并计算 bitrate。 |
loss-based controller 和 delay-based controller 共同实现 拥塞控制 算法。
反馈和扩展
有两种方法可实现提出的算法:
- 法一:loss-based controller 和 delay-based controller 都运行在发送端。
- 法二:loss-based controller 运行在发送端,delay-based controller 运行在接收端。
delay-based controller 运行在发送端
loss-based controller 和 delay-based controller 都运行在发送端。
本方法依赖反馈协议:[I-D.holmer-rmcat-transport-wide-cc-extensions] (TWCC)。
RTP 接收者
RTP 接收者将记录每个 RTP 包的到达时间和 transport-wide(传输范围) sequence number,它将 transport-wide feedback message 定期发送回发送者。建议的反馈间隔是每个接收到的视频帧一次,如果是纯音频或多流,则至少每 30 毫秒一次,如果需要限制反馈开销,这个间隔可以增加到 100 毫秒。
RTP 发送者
RTP 发送者将从接收到的 feedback message 获得 {sequence number, arrival time} ,并将 feedback message 所涵盖的每个包的 sequence number 映射其 send-time ,然后将 {send-time, arrival time} 喂给 delay-based controller 。同时,发送者还将根据 feedback message 中的 sequence number 计算丢包率。
个人理解
依赖 TWCC 消息,接收端 通过 TWCC 消息向 发送端 反馈 一组包的到达时间,发送端根据 TWCC 消息反馈的 {sequence number, arrival time} 以及本地的 send-time 喂给 delay-based controller 计算bitrate ,并计算丢包率,最后 loss-based controller 根据 bitrate 和 丢包率 给出最终的目标 bitrate 。
delay-based controller 在发送端,但是发送端不知道 RTP 包的到达时间,因此需要接收端使用 TWCC 消息向发送端反馈 RTP 包的到达时间,以便 delay-based controller 进行带宽估计,此时带宽估计的计算量在发送端。
delay-based controller 运行在接收端
loss-based controller 运行在发送端,delay-based controller 运行在接收端。
本方法依赖 接收端 的 delay-based controller 监控和处理到达时间和到达的包数量。发送者使用 abs-send-time 的RTP头扩展,使得接收端可以计算 inter-group 的延迟变化。接收端使用 REMB 消息 将 delay-based controller 输出的 bitrate 反馈给 接收端,从而实现 remote congestion control 。
RTP 接收者
接收端的 delay-based controller 的输出是一个 bitrate,接收端输出的 bitrate 在法二中将通过 REMB feedback message [I-D.alvestrand-rmcat-remb] 发送至发送端。
丢包通过 RTCP receviver reports 发回。
RTP 发送者
发送端 将 REMB message 中的 bitrate 和 RTCP report 中的 丢包率 喂给 loss-based controller, loss-based controller 输出最终的目标码率。建议在检测到拥塞后立即发送 REMB 消息,否则至少每秒发送一次。
个人理解
依赖 REMB 消息,接收端的 delay-based controller 输出一个 bitrate,通过 REMB 消息告知 发送端,发送端的 loss-based controller 根据 REMB 消息的 bitrate 以及丢包率 给出 最终的目标 bitrate 。
delay-based controller 在接收端,即基于延迟的带宽估计在接收端,通过 REMB 消息向发送端报告基于延迟的带宽估计结果。
发送引擎
Pacing 用于驱动 controller 计算的目标比特率。
当媒体编码器产生数据时,这将被送入 Pacer 队列。
Pacer 每隔 burst_time 间隔向网络发送一组数据包。推荐的 burst_time 是 5 ms 。一组数据包的大小被计算为目标 bitrate 和 burst_time 之间的乘积。
Delay-based control
Delay-based control 算法可进一步拆分为 4 部分:
- a pre-filtering : 前置过滤
- 处理由通道中断引起的延迟瞬变,多组包一同到达
- an arrival-time fiter : 到达时间过滤器
- 估计组间到达延迟,可用于检测瓶颈链路是否 over-used
- an over-use detector : over-use 探测器
- 根据 arrival-time fiter 的结果检测信道是否 over-use
- a rate controller : 码率控制器
- 增加码率,保持码率,降低码率
Arrival-time model
因子
本节描述了一个自适应过滤器,它根据接收到的数据包组的时间不断更新网络参数的估计。
我们定义到达时间间隔为:, 即两组包的到达时间的差值。相对地,出发时间间隔为:,即两组包地出发时间的差值。最后,组间延迟变化:,即 到达时间间隔 和 出发时间间隔 之间的差值,也可以解释为第 i 组和第 i-1 组的延迟之间的差异: 。其中:
- T(i) 是当前正在处理的一组数据包中(每个burst_time发出一组)最后一个数据包的出发时间戳。
- t(i) 是接收端为每一组包赋值的一个接收时间,该接收时间对应于收到该组的最后一个数据包的时间。
如果 , 则一个组相对于它的前一个组是延迟的。
建模
我们可以将组间延迟变化建模为:,此次的 w(i) 是随机过程W中的一个样本,随机过程W是链路容量、当前交叉流量和当前发送比特率的函数。我们把W建模为一个 White Gaussian Noise (WGN) 过程。
- 如果我们过度使用通道,我们期望 w(i) 的平均值会增加.
- 如果网络路径上的队列被清空,则 w(i) 的平均值会减小;
- 否则 w(i) 的平均值将为零。
从 w(i) 中分解出均值 m(i) 以使过程均值为零,我们得到等式一: ,其中 噪声项 v(i) 表示模型未捕获的网络抖动和其他延迟效应。
Pre-filtering
目的
前置过滤 的目的在于 处理由通道中断引起的延迟瞬变。在中断期间在网络缓冲区中排队的数据包,由于与拥塞无关的原因,在中断结束后以突发方式传递。
实现
前置过滤 的实现是 将一下子到达的多组包合并。
如果以下的两个条件之一成立,那么数据包将被合并在同一组中:
-
从发送的角度:在 burst_time 间隔内发送的一系列数据包构成一个组。(使用发送时间间隔判断,理论上就是将这一系列包作为的一个组发送的)
- 推导:正常的发送引擎:每间隔一个 burst_time 发送一组数据包。
-
从到达的角度:到达时间间隔小于 burst_time 且组间延迟变化 d(i) 小于 0 的数据包被认为是当前数据包组的一部分。(使用到达时间间隔和组间延迟变化判断)(该角度即前置过滤的目的)
- 推导:如果 中断导致 i-1 组 和 i 组被缓存,而 i - 1 组先进入缓冲区,因此 i-1 组被缓存的时间肯定要比 i 组的长,而中断结束后以突发方式传递,导致他们的到达时间间隔小于 burst_time,同时由于 i-1 组被缓存的时间比 i 组的长 从而使得 组间延迟变化 d(i) 小于 0 。
Arrival-time filter
当 i > 1 时,参数组间延迟变化 d(i) 对每一组包是可用的。我们希望估算 Arrival-time model 中的 m(i) ,并使用这个估算值来检测瓶颈链路是否 over-used 。参数 m(i) 可以使用任何可用的 filter 进行估算,在此我们采用了 Kalman filter 。
令 m(i) 为 i 时的估计值,我们将从 i 时到 i+1 时的状态演化模型建为:
其中,u(i) 是我们将其建模为具有零均值和方差 的高斯统计的平稳过程的状态噪声。q(i) 的推荐值是 10^-3 。
在等式 1 中,我们给到 ,其中 v(i) 是零均值高斯白测量噪声,方差
Kalman filter 递归地更新我们的估计 m_hat(i) 为:
方差 使用指数平均过滤器估计,针对可变采样率进行修改:
其中 是接收到最后 K 个数据包组的最高速率;chi 是一个滤波器系数,通常选择为区间 [0.1, 0.001] 中的数字。
由于我们假设 v(i) 应该为零均值的 WGN(White Guassian noise) 在某些情况下不太准确,因此我们在 var_v_hat 的更新周围引入了一个额外的异常值过滤器。如果 过滤器将更新为 而不是 。例如,在数据包以高于信道容量的速率发送的情况下,v(i) 不会是 white,在这种情况下,它们将彼此排在后面。
Over-use detector
信号 over-use,under-use, normal
arrival-time filter 输出组间延迟变化估计值 m(i), m(i) 被用于与阈值 del_var_th(i) 进行比较:若 m(i) 高于 del_var_th(i) 则被认为是 over-use 的一个指示。这样的指示是不足以让检测器向速率控制子系统(rate control subsystem)发出 over-use 的信号的。只有 在至少 overuse_time_th 毫秒内连续检测到 over-use 时,才会发出 over-use 信号。
但是,如果 m(i) < m(i-1),即使满足上述所有条件,也不会发出 over-use 信号。
类似地,当 m(i) < - del_var_th(i) 时,检测到相反的状态,under-use(over-use 的反义词)。 如果既没有检测到过度使用(over-use)也没有检测到使用不足(under-use),则检测器将处于 normal 状态。
阈值 del_var_th
阈值 del_var_th 对算法的整体动态和性能有显着影响。
特别是,已经有实践表明,使用静态阈值 del_var_th,由所提出算法控制的流可能会被并发 TCP 流 [Pv13] 饿死。可以通过将阈值 del_var_th 增加到足够大的值来避免这种饥饿。
原因是,通过使用较大的 del_var_th,可以容忍较大的排队延迟 (即允许较大的 m(i) 值);对于较小的 del_var_th,over-use detector 会通过生成 over-use 信号来快速对偏移估计 m(i) 的小幅增加做出反应(减少基于延迟估计的可用带宽 A_hat)。
出于这个原因,我们建议根据以下动态方程改变阈值 del_var_th(i):
基本原理是当 超出范围 时 增加(避免饿死),而当偏移估计 回落到该范围内时, 会减小(避免过高的排队延迟)。在该方式下,当 增加时(例如由于 TCP 流进入相同的瓶颈), 增加可避免不受控制地生成 over-use 信号 (不受控制地生成 over-use 信号可能导致所提出的算法控制的流的饥饿 [Pv13])。
如果 那么 ,否则 。因此建议选择 以使 增加的速率高于其减少的速率。 使用此设置,可以在并发 TCP 流的情况下增加阈值并防止饥饿以及执行协议内公平性。
此外,如果此条件成立,则不应更新 :
此外,建议将 限制在 范围内,因为过小的 会导致检测器变得过于敏感,过大的 会导致检测器变得不敏感。
另一方面,当 回落到范围 时,阈值 会降低,从而可以实现更低的排队延迟(即不想忍受太大的 )。
、、 和 的推荐值分别为 12.5 ms、10 ms、0.01 和 0.00018。
Rate control
Rate control 被分为两部分:
- 一部分为基于延迟控制带宽预测
- 一部分为基于丢包控制带宽预测
只要没有检测到拥塞,两者都旨在增加对可用带宽 A_hat 的估计,并确保最终匹配信道的可用带宽,并检测到 over-use。
一旦发现 over-use,由 delay-based controller 估计的可用带宽减少。通过这种方式,我们得到了可用带宽的递归和自适应估计。
在本文档中,我们假设 rate control subsystem 是周期性执行的,并且这个周期是恒定的。
rate control subsystem
rate control subsystem 有 3 个 states:Increase、Decrease 和 Hold。
- Increase 是没有检测到拥塞时的状态;
- Decrease 是检测到拥塞的状态,
- Hold 是等到建立的队列耗尽后再进入 Increase 状态的状态。
signal \ state | Hold | Increase | Decrease |
---|---|---|---|
over-use | Decrease | Decrease | |
normal | Increase | Hold | |
under-use | Hold | Hold |
Increase
subsystem 从 increase 状态开始,increase 状态将一直停留在 subsystem 中直到 over-use 或 under-use 。 在 increase 状态下,每次更新时,基于延迟估计的可用带宽都会增加(无论是 multiplicative increase 还是 additive increase,乘法还是加法取决于其当前状态,见下文)。
如果当前带宽估计看起来离收敛很远,则系统会进行乘法增加,而如果看起来更接近收敛,系统会进行加法增加。(何为离收敛很远,何为接近收敛,见下文)。
接近收敛
如果当前输入的比特率 R_hat(i) 接近我们之前处于 Decrease 状态时的输入比特率的平均值,我们假设我们接近收敛。“接近”定义为围绕该平均值的三个标准差。建议使用平滑因子为 0.95 的指数移动平均线测量此平均值和标准差,因为预计该平均值涵盖了我们处于 Decrease 状态的多个场合。
远离收敛
每当这些统计数据的有效估计不可用时,我们假设我们尚未接近收敛,因此仍处于乘法 Increase 状态。
如果 R_hat(i) 增加到平均最大比特率的三个标准偏差以上,我们假设当前拥塞级别已经改变,此时我们重置平均最大比特率并返回乘法 Increase 状态。
R_hat(i)
R_hat(i) 是 delay-based controller 在 T 秒窗口内测量的输入比特率:
N(i) 是过去 T 秒接收到的数据包数量,L(j) 是数据包 j 的有效负载大小。 建议使用 0.5 到 1 秒之间的窗口 T。
乘法增加
delay-based controller 的可用带宽估计 A_hat 。
在乘法增加(multiplicative increase)期间,估计每秒最多增加 8% :
加法增加
delay-based controller 的可用带宽估计 A_hat 。
在加法增加(additive increase)期间,每个 response_time 间隔最多增加一半数据包的估计值。 response_time 间隔估计为往返时间加上 100 ms ( 100ms 作为 over_use 估计器和检测器反应时间的估计 ) 。
expected_packet_size_bits 用于在较低比特率下为加法增加(additive increase)采用稍慢的斜率。 例如,可以通过假设每秒 30 帧的帧速率从当前比特率计算:
阈值
由于系统依赖于过度使用信道来验证当前可用带宽估计,我们必须确保我们的估计不会偏离发送方实际发送的速率。 因此,如果发送方无法以拥塞控制器要求的比特率生成比特流,则可用带宽估计应保持在给定范围内。 因此我们引入一个阈值:
其中, A_hat(i) 是 delay-based control 可用带宽估计,R_hat(i) 是当前 实际接收 bitrate 。
Decrease
当检测到过度使用时,系统转换到 Decrease 状态,其中 delay-based control 可用带宽估计 A_hat(i) 降低到当前 接收bitrate R_hat(i) 的一个因子。
beta 通常选择在区间 [0.8, 0.95] 内,0.85 是推荐值。
当检测器向速率控制子系统发出 under-use 的信号时,我们知道网络路径中的队列正在被清空,这表明我们的可用带宽估计值 A_hat 低于实际可用带宽。 收到该信号后,速率控制子系统将进入 hold 状态,在此状态下接收端可用带宽估计将保持不变,同时等待队列稳定在较低级别——这是一种尽可能降低延迟的方法。
建议
建议更新 A_hat(i) 的例程至少在每个 response_time 间隔运行一次。
Parameters settings
Parameter | Description | RECOMMENDE Value |
---|---|---|
burst_time | 作为一组 packet 突发传输 的时间间隔,单位为毫秒 | 5ms |
q | 状态噪声协方差矩阵 | q = 10^-3 |
e(0) | 系统误差协方差的初始值 | e(0) = 0.1 |
chi | 用于测量方差的系数 | [0.1, 0.001] |
del_var_th(0) | 自适应阈值的初始值 | |
overuse_time_th | 触发一个 overuse 信号所需的时间(overuse 在 Delay-Based Controller 持续这么一个时间才会发出 overuse 信号) | 10ms |
K_u | 自适应阈值系数 | 0.01 |
K_d | 自适应阈值系数 | 0.00018 |
T | 测量接收 bitrate 的时间窗口 | [0.5, 1] s |
beta | Decrease 速率因子 | 0.85 |
Loss-based control
第二部分的拥塞控制器(Loss-based controller)的决策基于 RTT ,丢包 packet loss 和 来自 delay-based controller 的可用带宽估计 A_hat 。
Loss-based controller 的可用带宽估计用 As_hat 表示。
由 Delay-based controller 产生的可用带宽估计 A_hat 仅在沿路径的队列大小足够大时才可靠。如果队列非常短,over-use 只会通过丢包可见(如果队列长,over-use 会引起 packet 在队列中排队的时间长,从而引起时延的变化,delay-based control 就能感知到 over-use),而 Delay-based controller 不会关心丢包。
每次接收到来自 receiver 的反馈(反馈 丢包 等信息))时,Loss-based controller 都应该运行:
- 如果自 receive 上次 report 以来丢失了 2-10% 的数据包,则发送方可用带宽估计 As_hat(i) 将保持不变。
- 如果超过 10% 的数据包丢失,则计算新的估计值 As_hat(i) = As_hat(i-1)(1-0.5p),其中 p 是丢失率。
- 只要少于 2% 的数据包丢失,As_hat(i) 就会增加 As_hat(i) = 1.05(As_hat(i-1)) 。
将 Loss-based controller 的估计 As_hat 与 Delay-based controller 的估计 A_hat 进行比较。 实际发送速率设置为 As_hat 和 A_hat 之间的最小值。
我们通过注意到如果传输通道由于 over-use 而有少量丢包,如果发送者不调整他的比特率,这个量很快就会增加,那么很快就会超过 10% 的阈值并调整 As_hat(i)。 但是,如果丢包率没有增加,那么丢包可能与自己造成的拥塞无关,因此我们不应该对它们做出反应。
安全考虑
能够在连接上插入或删除消息的攻击者将能够破坏速率控制。 这可能使算法产生一个发送速率不足利用瓶颈链路容量,或者发送速率过高导致网络拥塞。
在这种情况下,控制信息是在 RTP 内部携带的,并且可以使用 SRTP 来防止修改或消息插入,就像媒体一样。 鉴于时间戳包含在未加密的 RTP 标头中,因此无法防止泄露,但仅基于时间信息似乎很难发起攻击。