Transport-CC 反馈 · 通往拥塞控制的桥
现代 WebRTC 拥塞控制的信号源,是 Transport-CC 反馈:发送端给每个包打一个全局序号,接收端如实报回每个包的到达时间,发送端据此算出延迟变化。这一章讲清这套反馈怎么运转、为什么把带宽估计放在发送端,以及它如何连接第 4 与第 5 部分。
Transport-CC 反馈 · 通往拥塞控制的桥
WebRTC 到底该发多快?发太快网络就堵、丢包飙升;发太慢又浪费带宽、画质打折。要动态找到这个「刚刚好」的速率,得先有精确的信号——知道网络当前的拥塞状况。现代 WebRTC 的信号源,就是 Transport-CC(Transport-wide Congestion Control)反馈。它是第 4 部分(RTP/RTCP)通往第 5 部分(拥塞控制)的桥。
机制:打全局序号,报到达时间
Transport-CC 的运转,是发送端和接收端一场精心配合:
① 发送端给每一个发出的包(跨所有流)打一个连续的全局序号——transport-wide-cc 序号头扩展。② 接收端记下每个序号的包的精确到达时间**。③ 接收端周期性地把「哪些序号、分别何时到达」通过 RTCP 的 TransportFeedback 报文报回发送端。④ 发送端于是同时握有「每个包我何时发的」和「它何时到的」,算出单向延迟怎么变化。**
这个「延迟变化」是拥塞的先兆信号:如果包的传输延迟在逐渐变大,说明网络的缓冲区正在排队堆积——拥塞即将发生,该降速了;如果延迟平稳,说明还有余量,可以试着提速。在丢包真正发生之前,延迟的变化就预警了拥塞——这让 WebRTC 能「未堵先让」,比「丢了才反应」快得多。这正是 GCC 延迟based 带宽估计的核心输入(第 5 部分详解)。
对应的类是 TransportFeedback(modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h,继承 Rtpfb)——它高效地编码「一串序号 + 各自的到达时间差」,一个 RTCP 包就能报回几十上百个包的到达情况。
为什么把估计放在发送端
上一章提过 Transport-CC 相对老的 REMB 的关键转变——把带宽估计从接收端搬到发送端。这里再点透其深意:
只有发送端同时知道「发送时间」和「到达时间」,才能算出真正的延迟变化。 接收端只知道包何时到,不知道它何时被发出,所以它算不出单向延迟的绝对变化——REMB 时代接收端只能用较粗的方式估。而 Transport-CC 让接收端只当忠实的记录员(报原始到达时间,不做判断),把估计的活儿交给信息最全的发送端。发送端有完整数据,能跑更精细的算法(trendline 等),估得更准、反应更快。
这是分布式系统一个反复出现的智慧:决策放在信息最完整的地方,其他节点只提供原始观测。 Transport-CC 把它用在了拥塞控制上,效果是 WebRTC 拥塞控制的一次代际提升。代价是每个包多带几字节的序号头扩展、以及周期性的反馈包——但相比它带来的精度,非常划算。
一张反馈闭环图
这是一个持续运转的闭环:发包 → 报到达 → 估带宽 → 调速率 → 再发包……每隔几十毫秒转一圈,让发送速率始终贴着网络的实时容量。
小结与第 4 部分回顾
Transport-CC 是现代拥塞控制的信号源:发送端给每个包打全局序号,接收端如实报回每个包的到达时间(TransportFeedback RTCP),发送端据此算延迟变化——在丢包前就预警拥塞。把估计放在信息最全的发送端,是它相对 REMB 的代际提升。它是一个持续的反馈闭环,让发送速率贴着网络容量。
第 4 部分「RTP/RTCP」到此完整:RTP 包 → 头扩展 → PT 分配 → 模块中枢 → 发送路径 → RTCP 报告 → 反馈 → NACK/RTX → FEC → Transport-CC。还差接收侧的分流和帧变换钩子——下一章补上,再进入拥塞控制。👉 RtpDemuxer 与帧变换。
参考资料
- [1] libwebrtc 源码.
modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h、rtp_header_extensions.h(transport-cc 序号)。 - [2] IETF「RTP Extensions for Transport-wide Congestion Control」草案。
- [3] 关联第 5 部分拥塞控制——本反馈的消费者。