3. RTP负载类型与编码映射:PT值与编码格式对应关系
RTP头里有个字段叫 PT(Payload Type),7 个比特,取值范围 0–127。说白了,它就是告诉接收端:「我这包里装的是 H.264 还是 Opus,你拿什么解码器来解。」
我刚开始接触 RTP 时,总觉得 PT 就是个编号,后来踩过坑才明白——PT 值背后牵涉到编码协商、动态映射、甚至整个流媒体系统的兼容性。这一节,咱们就把 PT 和编码格式的映射关系彻底讲透。
3.1 静态 PT 值:RFC 定义的固定映射
早期的 RTP 规范(RFC 3551)为一些经典编码分配了固定的 PT 值。这些值被称为「静态 PT」,范围是 0–95。接收端看到这些 PT 值,不需要额外协商就知道该用什么解码器。
| PT 值 | 编码格式 | 时钟频率 (Hz) | 声道数 | 典型应用 |
|---|---|---|---|---|
| 0 | PCMU (G.711 μ-law) | 8000 | 1 | VoIP 电话 |
| 3 | GSM | 8000 | 1 | 早期移动通信 |
| 4 | G.723 | 8000 | 1 | 低码率语音 |
| 8 | PCMA (G.711 A-law) | 8000 | 1 | VoIP 电话(欧洲) |
| 9 | G.722 | 8000 | 1 | 宽带语音 |
| 10 | L16 (线性 PCM, 2 声道) | 44100 | 2 | CD 音质传输 |
| 11 | L16 (线性 PCM, 1 声道) | 44100 | 1 | 单声道高保真 |
| 14 | MPA (MPEG-1/2 Audio) | 90000 | 1 | MPEG 音频流 |
| 26 | JPEG | 90000 | — | MJPEG 视频 |
| 31 | H.261 | 90000 | — | 早期视频会议 |
| 32 | MPV (MPEG-1 Video) | 90000 | — | MPEG-1 视频 |
| 34 | H.263 | 90000 | — | 视频通话 |
3.2 动态 PT 值:SDP 协商的核心
静态 PT 只覆盖了 0–95 中的一小部分,而且很多编码(比如 H.264、VP9、Opus)是后来才出现的。RFC 3551 规定,96–127 这 32 个值留给「动态 PT」——说白了,就是让通信双方通过 SDP 协议自己商量:「我用 PT=96 代表 H.264,你同意吗?」
为什么会这样设计?你想想看,如果每出一个新编码就要 IANA 分配一个固定 PT,那 RFC 得改到猴年马月。动态 PT 给了系统极大的灵活性。
SDP 中的 PT 映射示例
下面是一个典型的 SDP 片段,展示了动态 PT 的映射方式:
m=video 5004 RTP/AVP 96 97 98
a=rtpmap:96 H264/90000
a=rtpmap:97 VP8/90000
a=rtpmap:98 H265/90000
a=fmtp:96 packetization-mode=1;profile-level-id=42e01f
这段 SDP 的意思是:
- 视频流在端口 5004 上传输,支持三种编码
- PT=96 对应 H.264,时钟频率 90000 Hz
- PT=97 对应 VP8,时钟频率 90000 Hz
- PT=98 对应 H.265,时钟频率 90000 Hz
a=fmtp行进一步描述了 H.264 的参数(打包模式、profile 等级)
3.3 常用音视频编码的 PT 值速查
我把实际项目中常见的编码及其 PT 值整理成了一张速查表。静态 PT 直接查表,动态 PT 是业界约定俗成的常用值(实际以 SDP 协商为准)。
| 编码格式 | 类型 | PT 值 | 时钟频率 | 备注 |
|---|---|---|---|---|
| PCMU | 音频 | 0 (静态) | 8000 | G.711 μ-law |
| PCMA | 音频 | 8 (静态) | 8000 | G.711 A-law |
| Opus | 音频 | 动态 (常用 111) | 48000 | WebRTC 首选 |
| AAC | 音频 | 动态 (常用 97) | 44100/48000 | 需配合 LATM/ADTS |
| G.722 | 音频 | 9 (静态) | 8000 | 实际编码是 16000 Hz |
| iLBC | 音频 | 动态 (常用 98) | 8000 | 旧版 WebRTC |
| H.264 | 视频 | 动态 (常用 96) | 90000 | 最广泛使用的视频编码 |
| H.265 | 视频 | 动态 (常用 98) | 90000 | 4K/8K 视频 |
| VP8 | 视频 | 动态 (常用 97) | 90000 | WebRTC 默认 |
| VP9 | 视频 | 动态 (常用 99) | 90000 | Google 新一代 |
| AV1 | 视频 | 动态 (常用 100) | 90000 | 开放媒体联盟 |
| JPEG | 视频 | 26 (静态) | 90000 | MJPEG 监控流 |
3.4 PT 值与时钟频率的关系
你可能注意到了,视频编码的时钟频率几乎都是 90000 Hz,而音频编码则五花八门(8000、16000、44100、48000)。
为什么视频统一用 90000?
- 90000 是 25 fps、30 fps、50 fps、60 fps 的公倍数
- 它能让 RTP 时间戳以整数步长递增,避免浮点误差
- 这是 MPEG 系统标准(ISO/IEC 13818-1)定下来的,RTP 沿用了这个约定
音频就不一样了。音频的采样率直接决定了 RTP 时间戳的步长。比如 Opus 用 48000 Hz,每帧 20 ms,时间戳步长就是 960。如果用 8000 Hz,同样 20 ms 的帧,步长只有 160。
3.5 动态 PT 协商的完整流程
为了让你更直观地理解动态 PT 的协商过程,我画了一张流程图。它展示了一个典型的 WebRTC 或 SIP 场景中,发送端和接收端如何通过 SDP 交换 PT 映射信息。
这个流程看起来简单,但实际项目中经常出问题。我遇到过最典型的情况是:接收端没有正确解析 SDP 中的 a=rtpmap 行,导致 PT 映射表建立失败。结果就是 RTP 包到了,解码器却不知道用什么格式解。
3.6 实战建议:PT 值处理的最佳实践
- 永远不要硬编码动态 PT 值——哪怕你只在内部系统用,也请通过 SDP 协商。我见过太多因为硬编码导致对接失败的血泪史。
- 静态 PT 值也要验证——虽然 RFC 定义了静态映射,但有些老旧设备可能不按规范来。收到 PT=0 时,最好还是确认一下是不是真的 PCMU。
- PT 值变化要能动态适应——在同一个 RTP 会话中,发送端可以切换 PT 值(比如从 H.264 切到 H.265)。接收端必须能根据 PT 值的变化动态切换解码器。
- 日志里一定要打印 PT 映射表——排查问题时,第一件事就是看 SDP 协商出来的 PT 映射是否正确。我习惯在初始化阶段把映射表完整打印出来。