RtpRtcp 模块 · 每条流的收发中枢
modules/rtp_rtcp 的核心是 ModuleRtpRtcpImpl2——每条媒体流一个,统管这条流的 RTP 发送与 RTCP 收发。这一章讲清它在收发管线里的位置、它把 RtpSender 与 RtcpSender/RtcpReceiver 捆在一起的角色,以及一条流为什么需要这么一个中枢。
RtpRtcp 模块 · 每条流的收发中枢
包结构有了,谁来实际收发、并处理反馈?是 modules/rtp_rtcp/ 的核心类——ModuleRtpRtcpImpl2。它是每条媒体流的收发中枢,把这条流的 RTP 发送和 RTCP 收发统管起来。这一章认识它。
一条流,一个模块
ModuleRtpRtcpImpl2(modules/rtp_rtcp/source/rtp_rtcp_impl2.h)实现 RtpRtcpInterface:
// modules/rtp_rtcp/source/rtp_rtcp_impl2.h(节选)
class ModuleRtpRtcpImpl2 final : public RtpRtcpInterface, ... {
void IncomingRtcpPacket(std::span<const uint8_t> incoming_packet) override;
void RegisterSendRtpHeaderExtension(absl::string_view uri, int id) override;
// 统管:发 RTP、发 RTCP、收 RTCP
};它捆着哪些零件
ModuleRtpRtcpImpl2 本身是个「协调者」,真正干活的是它持有的几个子组件:
| 子组件 | 干什么 | 本教程 |
|---|---|---|
RTPSender / RtpSenderEgress | 打包并发送 RTP | 下一章 |
RTCPSender | 生成并发送 RTCP 报告 / 反馈 | 第 4 部分 |
RTCPReceiver | 解析收到的 RTCP | 第 4 部分 |
把「发媒体」「发反馈」「收反馈」三条线捆在一个模块里,是有道理的:它们围绕同一条流(同一个 SSRC),要共享这条流的状态(发了哪些包、序号到哪了、收到的丢包报告对应哪些包)。放一起,状态才好协同。
「2」是什么意思
你可能注意到类名带个 2——ModuleRtpRtcpImpl2。这是 WebRTC 演进的痕迹:它是旧 ModuleRtpRtcpImpl 的重写版,主要为了适配新的线程 / 任务队列模型(更贴合 TaskQueue,减少锁)。读 WebRTC 常见这种带版本号的类(VideoReceiveStream2 等)——看到 2 就知道它是某个组件的现代重写,老版本可能还在但正被淘汰。这也提醒我们「api/ 稳定、实现常重构」的约定。
在管线里的位置
把它放进发送管线看:
上层编码器把媒体喂给模块,模块打包、发送、并接收对端反馈,反馈又驱动重传与码率调整——一条流的收发闭环,就以 ModuleRtpRtcpImpl2 为中心转起来。
小结与下一章
ModuleRtpRtcpImpl2(modules/rtp_rtcp/source/rtp_rtcp_impl2.h,实现 RtpRtcpInterface)是每条流(一个 SSRC)的收发中枢,统管三件事:发 RTP、发 RTCP、收 RTCP(IncomingRtcpPacket)。它捆着 RTPSender/RtpSenderEgress、RTCPSender、RTCPReceiver,让围绕同一条流的状态好协同。类名的 2 表示它是适配新线程模型的现代重写。
发送这条线最值得细看——打包、发送、以及为重传保留历史。下一章深入发送侧。👉 RtpSender 与发送路径。
参考资料
- [1] libwebrtc 源码.
modules/rtp_rtcp/source/rtp_rtcp_impl2.h/.cc(ModuleRtpRtcpImpl2、IncomingRtcpPacket)。 - [2] libwebrtc 源码.
modules/rtp_rtcp/source/rtp_rtcp_interface.h(接口)。 - [3] IETF RFC 3550「RTP/RTCP」。