Payload Type 分配 · 一个数字的讲究
RTP 包用 payload type 这个数字标明「负载是哪种编解码器」。它怎么分配竟大有讲究:动态范围 96-127、回退 35-63、避开 64-95,还有 BUNDLE 下的冲突消解。这一章读 g3doc/rtp.md 与 PayloadTypePicker,把这个小数字讲透。
Payload Type 分配 · 一个数字的讲究
RTP 包的 PayloadType 字段是个数字,指明负载用哪种编解码器。看似小事,分配起来却颇有讲究——范围、回退、避让、冲突消解,每一条都有原因。这一章依据 g3doc/rtp.md,把这个数字讲透。
静态 vs 动态
Payload type(PT)只有 7 位,取值 0-127。分两类(g3doc/rtp.md):
- 静态分配 —— 一些老编解码器(如 PCMU)的 PT 由 RFC 3551 固定规定,人人皆知。
- 动态分配 —— 其余编解码器的 PT 通过 SDP 协商时临时指定(
a=rtpmap:96 VP8/90000就是把 96 分给 VP8)。
g3doc/rtp.md 特意警告:动态 PT 的分配不保证稳定——同一个编解码器,不同通话、不同实现,可能分到不同的数字。所以代码里永远不能把 PT 数字写死,必须以协商结果为准。
范围:96-127,回退 35-63,避开 64-95
动态 PT 的取值范围有一套规矩(g3doc/rtp.md):
动态 payload type 优先用 96-127,用完了回退到 35-63,而 64-95 刻意避开。
- 96-127 —— 首选的动态范围。音视频编解码器默认在这里分配。
- 35-63 —— 回退范围。当 96-127 用尽(编解码器 + 它们的重传 / FEC 格式太多),就用这里。一些较新的格式(如 flexfec-03、AV1)默认就放这个低范围。
- 64-95 —— 刻意不用。因为这个范围会和 RTCP 的包类型混淆(RFC 5761,rtcp-mux 让 RTP 和 RTCP 共用一个端口,靠这个字节区分)。避开它,才能在同一条流上区分「这是 RTP 媒体包还是 RTCP 反馈包」。
一个小数字的分配,竟要照顾「和 RTCP 不冲突」「给新格式留位置」「兼容老版本 WebRTC」——实时协议的工程,魔鬼全在这种细节里。g3doc/rtp.md 还提到,老版本 WebRTC 认不出低范围的 PT,所以新格式往低范围放也是一种「不打扰老版本」的照顾。
谁来分:PayloadTypePicker
具体分配由几个组件负责(g3doc/rtp.md):
- 音频:
PayloadTypePicker(call/payload_type_picker.h)从一张表里分配,音频编解码器倾向用高范围 96-127(兼容老版本),而 RED 这类冗余格式放低范围 35-63(从 63 往下,减少和视频 PT 撞车)。 - 视频:由媒体引擎的
GetPayloadTypesAndDefaultCodecs(media/engine/webrtc_video_engine.cc)分配,从 96 起升序分给视频编解码器及其重传格式。
BUNDLE 下的冲突消解
BUNDLE带来一个新麻烦:音频和视频挤一条传输,它们的 PT 必须全局唯一(否则收到一个包,PT=96 到底是音频还是视频?)。但音频、视频是各自分配 PT 的,难免撞车。
解法是 PayloadTypeSuggester(call/payload_type.h)接口:检测到冲突时,从 127 往下重新分配冲突的 PT,直到全局无重复(g3doc/rtp.md)。于是 BUNDLE 一条流上,每个 PT 都能唯一映射到一种编解码器,分流才不会错。
一个副产品:探测用的 PT
顺带一提(g3doc/rtp.md 后半讲的),带宽估计有时要主动发包探测可用带宽(bitrate probing),用两种手段:纯 padding 包(RTP 填充,收端可丢弃)和 RTX 包(重发旧包,兼做冗余)。它们也带 PT——padding/RTX 有各自的流和 PT。探测是拥塞控制第 5 部分的话题,这里知道「探测包也是 RTP 包、也占 PT」即可。
小结与下一章
Payload type 标明编解码器,分静态(RFC 3551 固定)和动态(SDP 协商,不保证稳定,别写死)。动态范围优先 96-127、回退 35-63、避开 64-95(避与 RTCP 混淆)。音频用 PayloadTypePicker、视频用引擎方法分配;BUNDLE 下的冲突由 PayloadTypeSuggester 从 127 往下重分保证全局唯一。
包结构、扩展、PT 都清楚了。现在看谁在收发这些包——modules/rtp_rtcp/ 的核心模块 ModuleRtpRtcpImpl2。下一章。👉 RtpRtcp 模块。
参考资料
- [1] libwebrtc 源码.
g3doc/rtp.md(PT 分配规则)、call/payload_type_picker.h、call/payload_type.h。 - [2] libwebrtc 源码.
media/engine/webrtc_video_engine.cc(视频 PT 分配)。 - [3] IETF RFC 3551(静态 PT)、RFC 5761(避开 64-95)。