传统的拥塞控制算法通常只依赖一种信号(要么是丢包,要么是延迟)。而GCC则采用延迟加丢包两种拥塞信号,同时运行两个独立的控制器:

  1. 基于延迟的控制 (Delay-based Control):这是一种主动式、预测性的方法。它通过监测数据包在网络中传输的单向延迟变化趋势来判断拥塞。当延迟开始持续增长时,GCC 会认为网络路径上的某个路由器队列正在被填满,这是拥塞即将发生的早期信号。GCC 会在大量丢包发生之前就降低发送速率,从而有效控制延迟。
  2. 基于丢包的控制 (Loss-based Control):这是一种被动式、反应性的方法。它是网络拥塞控制的传统方法。当网络中出现丢包时,GCC 会认为网络已经发生了明确的拥塞(路由器队列已满,开始丢弃数据包)。此时,它会根据丢包率来计算一个合适的发送速率。

最终的发送码率由这两个控制器共同决定,总是取两者估算出的码率中更小、更保守的那一个。这样就确保了系统的稳定性和安全性。

GCC的首要目标是保证低延迟,其次才是高带宽。

算法原理

基于延迟的控制器

信息获取

  1. 发送端:为每个发出的 RTP 包打上一个全链路唯一的序列号(Transport-Wide Sequence Number)和发送时间戳 tsend(i)。
  2. 接收端:记录每个包的到达时间戳 tarrival(i)。
  3. 反馈:接收端通过 RTCP TCC (Transport-wide Congestion Control) Feedback 消息,定期将包的序列号和对应的到达时间戳打包,发送回发送端

这样,发送端就拿到了一系列的配对信息:{ seq_num1, tsend1, tarrival1 }, { seq_num2, tsend2, tarrival2}, …

1:计算延迟变化

发送端收到反馈后,可以计算出每个数据包的单向传播延迟: d(i)=tarrival(i)−tsend(i)

但是,绝对的延迟会因为时钟不同步而有误差。GCC 关注的是延迟的变化量,这可以消除时钟偏移的影响。它计算相邻两个数据包(或数据包组)之间的延迟差值: Δd(i)=d(i)−d(i−1)

这个 Δd(i) 反映了网络路径上排队延迟的变化。

  • 如果 Δd(i)>0,说明网络中的排队队列可能正在变长。
  • 如果 Δd(i)<0,说明队列可能正在缩短。
  • 如果 Δd(i)≈0,说明网络状态相对稳定。

2:状态估计

网络延迟的测量值是充满“噪声”的,会受到网络抖动等因素的瞬时影响。为了从这些嘈杂的数据中提取出真实的排队延迟增长趋势,GCC 创造性地使用了卡尔曼滤波器 (Kalman Filter)

  • 作用:卡尔曼滤波器是一种强大的数学工具,可以从一系列不完整和包含噪声的测量中,估计出动态系统的状态
  • 在GCC中的应用:它将测得的延迟变化量 Δd(i) 作为输入,通过内部的状态转移和更新模型,对齐进行平滑和去噪,最终输出一个更准确的网络排队延迟估计值 q(i)

3:过载检测

有了经过卡尔曼滤波器处理后的排队延迟估计值 q(i),接下来就需要判断网络是否“过载”了。

  • 算法设定一个动态的阈值 γ
  • 将 q(i) 与阈值 γ 进行比较,判断网络状态:
    • Over-use (过载): 如果 q(i)>γ 并且持续了一小段时间,说明排队延迟明显且持续增长,网络处于过载状态。
    • Under-use (低载): 如果 q(i)<−γ,说明排队延迟在减小,网络负载很低,有提升码率的空间。
    • Normal (正常): 如果 ∣q(i)∣≤γ,说明网络状态稳定。

4:速率控制

根据过载检测器输出的状态,速率控制器会调整目标码率 Ad(基于延迟估算的码率):

  • 检测到 Over-use:立即执行乘性减 (Multiplicative Decrease)

    Ad=Ad×β(其中 β≈0.85)

    这是一种快速降低码率的方式,以迅速缓解网络拥塞。

  • 检测到 Under-useNormal:执行加性增 (Additive Increase)乘性增 (Multiplicative Increase),这被称为“探测阶段”。

    • 算法会缓慢地增加码率,以探测网络是否还有更多的可用带宽。增加的速度会受到当前码率和网络往返时间(RTT)的影响,确保探测行为是温和的,不会立即引发新的拥塞。

基于丢包的控制器

这部分逻辑相对简单,作为网络严重拥塞时的“安全网”。

1:计算丢包率

发送端根据自己发送的包记录和从接收端反馈回来的确认信息,可以很容易地计算出最近一个时间窗口(如 1 秒)内的丢包率 Ploss。

2:计算目标码率

基于丢包率,GCC 会计算出一个目标码率 Al。这个计算通常基于经典的 TCP 友好码率控制(TFRC)公式的变种。

  • 当丢包率很低时(如 < 2%):认为网络状况良好,此时 Al 不会成为码率的限制因素。它甚至可能会允许码率缓慢增加。

  • 当丢包率处于中等水平时(如 2% - 10%):算法会根据丢包率、RTT 和数据包大小计算出一个目标码率。丢包率越高,计算出的 Al 越低。

    Al≈f(RTT,Ploss,packet_size)

  • 当丢包率很高时(如 > 10%):这是一个明确的强拥塞信号。算法会快速且大幅度地降低码率,通常也是采用乘性减的方式。

时延控制和延迟控制结合

在任何一个时刻,GCC 都会同时运行上述两个控制器,得到两个目标码率:

  • Ad:来自基于延迟的控制器。
  • Al:来自基于丢包的控制器。

最终发送端采用的目标码率 Atarget 是两者中的最小值,并且还会受到应用层设置的最高/最低码率限制。

Atarget=min(Ad, Al, Amax_app)

  • 场景1(拥塞初期):延迟开始增加,但还未丢包。此时 Ad 会首先下降,Atarget 会跟随 Ad 下降,实现了主动降速,避免了丢包和高延迟。
  • 场景2(突发拥塞):网络突然恶化,直接开始大量丢包。此时 Ploss 飙升,导致 Al 急剧下降。Atarget 会跟随 Al 下降,对严重拥塞做出快速反应。