# 丢包based 带宽估计 · 兜底的另一只眼

> 延迟based 有盲区，丢包based 作为另一只眼补上。这一章读 goog_cc 的 LossBasedBweV2：它怎么用丢包率估带宽、为什么和延迟based 取小、以及从早期简单丢包阈值到 v2 的演进——把丢包信号用得更精细。

- 作者：David（道雾轩）
- 专栏：音视频与 WebRTC 详解（https://daiw.org/manual/webrtc.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/webrtc/loss-based-bwe
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 丢包based 带宽估计 · 兜底的另一只眼

[延迟based 是主控](https://daiw.org/manual/webrtc/delay-based-bwe)，但它并非全知。有些网络场景它会失灵，这时需要**另一只眼**——**丢包based** 带宽估计。它是 [GoogCC 双控制器](https://daiw.org/manual/webrtc/congestion-control-overview)的另一半，`goog_cc/loss_based_bwe_v2.h` 里的 `LossBasedBweV2`。

## 为什么还需要看丢包

[延迟based](https://daiw.org/manual/webrtc/delay-based-bwe)已经很灵敏了，为什么不够？

<Callout type="info">
  **延迟based 假设「拥塞 → 排队 → 延迟涨」，但有些网络不排队就直接丢包，延迟信号会失灵。** 典型：

  - **浅缓冲 / 主动丢包的链路** —— 有些路由器缓冲区极小，或用 AQM（主动队列管理）**在排队变长前就丢包**。这时延迟涨得不明显，[延迟based](https://daiw.org/manual/webrtc/delay-based-bwe)嗅不到，但**丢包率已经上来了**。
  - **无线链路的随机丢包** —— Wi-Fi / 蜂窝有本底的随机丢包（信号干扰），和拥塞无关。这又是反过来：丢包不一定意味着拥塞。

  所以**丢包是另一个维度的信号**，和延迟互补：延迟看「排队」，丢包看「溢出 / 损耗」。两者结合，覆盖面才全。这也是为什么 [GoogCC 要跑两个控制器并取小](https://daiw.org/manual/webrtc/congestion-control-overview)——任一控制器说「该降」，就降，谁也别漏报拥塞。
</Callout>

## 丢包信号怎么用：从简单阈值到 v2

丢包based 估计的演进，是把「丢包」这个信号**用得越来越精细**：

- **早期（简单阈值）** —— 一套朴素规则：丢包率**低于**某阈值（如 2%）→ 可以涨；**高于**某阈值（如 10%）→ 降；中间 → 保持。直接、但粗糙——它没充分利用「丢多少、和码率什么关系」。
- **`LossBasedBweV2`（现代）** —— 更精细的模型。它综合**丢包率**、**当前码率**、**[已确认的吞吐](https://daiw.org/manual/webrtc/congestion-control-overview)** 等，用一个更完整的方法估出「在当前丢包水平下，可持续的带宽是多少」，而非简单的「过阈值就降」。它的入口是 `UpdateBandwidthEstimate`，吃一批 [`PacketResult`](https://daiw.org/manual/webrtc/transport-cc)（每个包丢没丢）：

```cpp
// goog_cc/loss_based_bwe_v2.h(节选)
class LossBasedBweV2 {
  void UpdateBandwidthEstimate(std::span<const PacketResult> packet_results, ...);
};
```

<Callout type="info">
  **`v2` 又是 [WebRTC「带版本号的现代重写」](https://daiw.org/manual/webrtc/rtp-rtcp-module)。** 从简单丢包阈值到 `LossBasedBweV2`，反映了拥塞控制的持续打磨：同样是「看丢包」，v2 把丢包信号和码率、吞吐联系起来，估得更准、和延迟based 配合得更好——尤其在延迟信号不可靠的网络里，它扛起了主要判断。读到 goog_cc 里各种 `v2`/`v3`，都是这种「同一信号，越用越精」的迭代痕迹。带宽估计是个**永远在优化**的领域，因为真实网络的花样是无穷的。
</Callout>

## 取小：谁保守听谁

[总览说过](https://daiw.org/manual/webrtc/congestion-control-overview)，GoogCC **取延迟based 和丢包based 的较小值**作为最终估计。再强调一次这个设计的稳妥：

- 延迟based 说 3 Mbps、丢包based 说 5 Mbps → 用 **3 Mbps**（延迟已预警，别冒进）。
- 延迟based 说 5 Mbps、丢包based 说 2 Mbps → 用 **2 Mbps**（丢包已很多，必须降）。

**任一信号预警，就采纳更保守的那个。** 拥塞控制里，「宁可保守、不可冒进」是安全的默认——因为[冒进的代价（卡顿）远大于保守的代价（画质略降）](https://daiw.org/manual/webrtc/delay-based-bwe)。两只眼睛，一个看排队、一个看损耗，取更警觉的那个，GoogCC 才能在五花八门的真实网络里都不翻车。

## 小结与下一章

**丢包based 估计**是[延迟based](https://daiw.org/manual/webrtc/delay-based-bwe)的互补兜底：有些网络**不排队就丢包**（浅缓冲、AQM）或有**随机丢包**（无线），延迟信号失灵，得靠丢包率。现代 `LossBasedBweV2`（`UpdateBandwidthEstimate` 吃 [`PacketResult`](https://daiw.org/manual/webrtc/transport-cc)）比早期简单阈值更精细，综合丢包率、码率、吞吐估带宽。GoogCC **取延迟 / 丢包两估计的较小值**——[任一预警就保守](https://daiw.org/manual/webrtc/congestion-control-overview)。

估计是「被动」测量，但 GoogCC 也会**主动出击**——发探测包试探「能不能更快」。下一章讲带宽探测。👉 [带宽探测](https://daiw.org/manual/webrtc/probing)。

## 参考资料

- [1] libwebrtc 源码.`modules/congestion_controller/goog_cc/loss_based_bwe_v2.h` / `.cc`（`UpdateBandwidthEstimate`）。
- [2] libwebrtc 源码.`goog_cc/send_side_bandwidth_estimation.h`（早期丢包逻辑）。
- [3] IETF「GoogCC」draft —— 丢包based 部分。
