3、RTP负载类型(PT)详解:PT值的定义与范围、静态负载类型与动态负载类型、常见音视频编码的PT映射

RTP 头里有个 7 比特的字段,叫 Payload Type(PT)。说白了,它就是告诉接收端:「这包数据是啥编码格式」。我刚开始调 RTP 流的时候,总觉得 PT 就是个编号,后来踩了几次坑才发现——PT 要是配错了,解码器根本认不出数据,画面直接花掉。

核心要点:PT 值决定了接收端用什么解码器来处理 RTP 负载。一个错误的 PT 映射,会导致整个流媒体会话失败。

3.1 PT 值的定义与范围

PT 字段占 7 位,取值范围是 0–127。但实际使用中,这个范围被分成了两段:

范围 类型 说明
0–95 静态负载类型 由 IANA 分配,编码格式固定
96–127 动态负载类型 通过 SDP 协商,编码格式可变

你可能会问:为什么要有静态和动态之分?嗯,早期 RTP 设计时,音视频编码种类不多,静态分配就够了。后来 H.264、VP8、Opus 这些编码陆续出现,静态范围不够用,才有了动态范围。

我的习惯:静态 PT 值尽量别改,那是行业约定。动态 PT 值我一般从 96 开始分配,避免和已有标准冲突。

3.2 静态负载类型

静态 PT 值 0–95 里,真正被 IANA 分配的大概只有前 34 个。剩下的保留未用。我列几个最常用的:

PT 值 编码名称 时钟频率 (Hz) 声道数
0 PCMU 8000 1
3 GSM 8000 1
4 G723 8000 1
8 PCMA 8000 1
9 G722 8000 1
10 L16 (2 声道) 44100 2
11 L16 (1 声道) 44100 1
13 CN (舒适噪声) 8000 1
26 JPEG 90000 —
31 H.261 90000 —
34 H.263 90000 —

注意看,音频的时钟频率大多是 8000 Hz,视频统一用 90000 Hz。为什么视频用 90000?因为 90000 能被 25、30、50、60 这些常见帧率整除,时间戳精度够用。

我曾经踩过的坑:有一次把 PCMU 的 PT 值写成了 8(PCMA 的值),结果接收端用 A-law 解码 μ-law 数据,出来的声音全是噪音。排查了半小时才发现是 PT 映射错了。

3.3 动态负载类型

动态 PT 值 96–127 没有固定编码格式。发送端和接收端通过 SDP 协商,告诉对方「我用 PT 96 代表 H.264」。举个例子:

m=video 5004 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; profile-level-id=42e01f

这段 SDP 的意思是:视频流用 PT 96,编码是 H.264,时钟频率 90000 Hz,打包模式是 1(NAL 单元模式)。

动态 PT 的分配没有硬性规定,但业界有一些不成文的习惯:

  • 96–100:常用 H.264
  • 101–105:常用 Opus 或 AAC
  • 106–110:常用 VP8 或 VP9
  • 111–127:留给自定义编码或扩展

我建议:同一个会话里,不同编码的 PT 值不要重复。我曾经见过一个系统,音频和视频都用 PT 100,结果解码器全乱了。

3.4 常见音视频编码的 PT 映射

我把实际项目中最常用的 PT 映射整理成了一张表。这张表我调了不下 50 次流,基本覆盖了 90% 的场景:

编码 PT 值 类型 时钟频率 备注
PCMU 0 静态 8000 μ-law,VoIP 标配
PCMA 8 静态 8000 A-law,欧洲常用
G.722 9 静态 8000 宽带音频,7 kHz
Opus 动态 (通常 96–100) 动态 48000 WebRTC 首选
AAC 动态 (通常 101–105) 动态 44100/48000 MPEG-4 音频
H.264 动态 (通常 96–100) 动态 90000 视频编码主流
H.265 动态 (通常 106–110) 动态 90000 4K/8K 视频
VP8 动态 (通常 106–110) 动态 90000 WebRTC 视频
JPEG 26 静态 90000 老式监控设备

这里有个细节:Opus 的时钟频率是 48000 Hz,不是 8000。因为 Opus 支持 20 kHz 以上的全频带音频,采样率必须高。我刚开始用 Opus 时,把时钟频率写成了 8000,结果时间戳计算全错,音频播放一顿一顿的。

实战要点:动态 PT 值必须在 SDP 中明确声明。接收端收到 RTP 包后,先查 PT 值,再查 SDP 映射,最后选解码器。缺了任何一步,流都解不出来。

3.5 PT 映射的完整流程

我画了一张图,把 PT 映射的完整流程串起来。你一看就明白:

PT 映射完整流程 发送端编码数据 选择 PT 值 静态 PT (0–95) 动态 PT (96–127) SDP 协商映射 封装 RTP 包 (PT 字段) 网络传输 接收端解析 PT → 解码 说明: 静态 PT:编码格式固定 动态 PT:需 SDP 协商 接收端根据 PT 选解码器 PT 错误 → 解码失败

流程其实不复杂:发送端先选好编码,再根据编码类型选 PT 值(静态或动态)。动态 PT 需要先通过 SDP 告诉接收端映射关系。然后封装 RTP 包,把 PT 值填进头部。接收端收到包后,根据 PT 值找到对应的解码器,开始解码。

我曾经遇到的一个典型案例:有一次调试 WebRTC 视频通话,H.264 的 PT 值在 SDP 里写的是 96,但实际 RTP 包里 PT 字段是 100。接收端查不到映射,直接丢弃了所有视频包。排查了整整一天,才发现是发送端代码里硬编码了 PT 100,没读 SDP 的配置。

3.6 调试 PT 映射的实用技巧

调了这么多年 RTP 流,我总结了几条经验,分享给你:

  • 用 Wireshark 抓包验证:过滤 rtp,看每个包的 PT 字段。如果 PT 值和 SDP 声明的不一致,那就是问题。
  • 检查 SDP 的 rtpmap 行:确保编码名称、时钟频率写对了。我见过有人把 H264 写成 H.264(带点),结果解析失败。
  • 动态 PT 值不要跨会话复用:不同媒体流(音频、视频)的 PT 值最好分开。音频用 96–100,视频用 101–105,避免混淆。
  • 注意 fmtp 参数:H.264 的 packetization-mode、profile-level-id 这些参数,直接影响解码器行为。漏了任何一个,画面都可能出问题。

我的调试习惯:每次改 PT 映射后,先用 ffplay 或 VLC 拉流测试。如果能正常播放,说明 PT 映射没问题。如果花屏或没声音,先查 PT 值。

PT 这个字段,看起来简单,但它是 RTP 会话的「翻译官」。翻译错了,再好的编码数据也白搭。你想想看,接收端拿到一个 PT=96 的包,它得先查 SDP 才知道这是 H.264 还是 Opus。如果 SDP 没配好,或者 PT 值写错了,整个流就断了。

嗯,PT 映射这块,我建议你多动手抓包看看。看多了,自然就熟了。