RTP 头扩展 · 每个包捎带的元数据
标准 RTP 头就那几个字段,但拥塞控制、音视频同步、分流都需要更多信息——靠头扩展捎带。这一章讲清头扩展的机制(URI 经 SDP 协商成本地 ID)、one-byte/two-byte 格式,以及几个关键扩展:transport-cc 序号、abs-send-time、mid。
RTP 头扩展 · 每个包捎带的元数据
上一章说 RTP 标准头就 SSRC、序号、时间戳等固定几个字段。但实时通信需要更多每包元数据——发送的绝对时间(给带宽估计用)、这个包属于哪条媒体(给分流用)、音量、视频朝向……这些靠 RTP 头扩展(header extensions) 捎带。别小看它:WebRTC 的拥塞控制和同步都离不开它。
机制:URI ⟷ 本地 ID
头扩展是一套可扩展机制:每种扩展由一个 URI 标识(如 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time),但塞进 RTP 包时用一个紧凑的本地 ID(1~14 或更大的数字)代表它。URI 和 ID 的映射,在 SDP 里协商:
a=extmap:2 http://www.webrtc.org/.../abs-send-time
a=extmap:3 http://www.ietf.org/id/.../transport-wide-cc-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid头扩展的启用是协商出来的——双方用 a=extmap: 约定「ID 2 代表 abs-send-time」,之后每个 RTP 包里那个 2 号扩展,收端就知道怎么解读。 这和编解码器 payload type 的协商一个道理:用一个小数字代表一个长 URI,省字节。ModuleRtpRtcpImpl2 上有 RegisterSendRtpHeaderExtension / DeregisterSendRtpHeaderExtension 之类的接口来登记这些映射。没协商上的扩展不会被发送 / 解析——扩展是「双方都同意才用」。
格式上,RTP 扩展有 one-byte(ID 1-14,每个扩展 ≤16 字节)和 two-byte(ID 更多、数据更长)两种编码。WebRTC 按需选用,对读者而言知道「有这两种、按空间自动选」即可。
几个关键扩展
头扩展种类不少,但有几个是 WebRTC 的命脉:
| 扩展 | 捎带什么 | 给谁用 |
|---|---|---|
| transport-wide-cc 序号 | 一个跨所有流的全局发送序号 | Transport-CC 拥塞控制(第 5 部分) |
| abs-send-time | 包发送的绝对时间 | 带宽估计(算单向延迟变化) |
| mid | 这个包属于哪条 m-line | BUNDLE 分流 |
| audio-level | 音频音量 | 会议里的「谁在说话」 |
| video-orientation | 视频旋转角度 | 手机横竖屏正确显示 |
| playout-delay | 期望的播放延迟范围 | 低延迟 / 同步场景 |
最重要的两个,是 transport-cc 序号和 mid。
- transport-cc 序号是 WebRTC 现代拥塞控制的基石:它给每一个发出的包(跨所有流)打一个连续的全局序号,接收端记录每个序号包的到达时间,通过 RTCP 反馈报回发送端;发送端据此精确掌握「哪些包到了、什么时候到的、延迟怎么变」,这是 GCC 带宽估计的输入。没有它,现代 WebRTC 的拥塞控制无从谈起。
- mid 让接收端在 BUNDLE(多流挤一条传输)时,靠包里的 mid 就能知道它属于哪条 m-line / 收发器,从而正确分流——比单靠 SSRC 更稳健(SSRC 可能在信令到达前就先收到包)。
一个包的真实样子
综合上一章和这一章,一个真实的 WebRTC RTP 包大致是:
[RTP 固定头: PT | seq | timestamp | SSRC]
[头扩展: transport-cc 序号=1234 | abs-send-time=... | mid=0]
[负载: SRTP 加密的编码媒体数据]固定头给出「哪条流、第几个包、什么时刻」,头扩展给出「拥塞控制与分流的元数据」,负载是加密的媒体。小小一个包,信息密度极高——这是几十年实时传输经验的结晶。
小结与下一章
RTP 头扩展给每个包捎带标准头之外的元数据。机制是 URI ⟷ 本地 ID,经 SDP a=extmap 协商(one-byte / two-byte 两种编码)。最关键的两个:transport-cc 序号(全局发送序号 + 接收端记到达时间,是现代拥塞控制的基石)和 mid(BUNDLE 下的可靠分流);还有 abs-send-time、audio-level、video-orientation 等。
一个包要标明用哪种编解码器,靠 PayloadType 字段——而这个数字怎么分配,竟有不少讲究(范围、冲突、BUNDLE)。下一章讲。👉 Payload Type 分配。
参考资料
- [1] libwebrtc 源码.
modules/rtp_rtcp/source/rtp_header_extensions.h、rtp_header_extension_map.h、rtp_rtcp_impl2.h(注册扩展)。 - [2] IETF RFC 8285「A General Mechanism for RTP Header Extensions」。
- [3] IETF「transport-wide-cc」草案、RFC 内的 abs-send-time / mid 扩展定义。