1. RTP协议基础回顾:头部结构、Payload Type、SSRC与CSRC、时间戳与序列号
各位好,咱们开始第一讲。RTP 协议,说白了就是实时传输的“快递员”。你想想看,视频会议、直播推流、VoIP 通话,哪样离得开它?我做了这么多年音视频,见过太多人上来就调参数、改代码,结果连 RTP 头部都没搞明白——嗯,这其实是个坑。
今天咱们就把 RTP 的底裤扒干净。从头部结构到那几个关键字段,一个一个过。你把这些吃透了,后面调优和排错才能有的放矢。
1.1 RTP 头部结构:12 字节的“身份证”
RTP 头部固定 12 字节。不多不少,刚刚好。我习惯把这 12 字节分成三块来看:
- 版本号(V, 2 bits):目前只有 v2,值是 2。见到别的版本?那八成是抓包抓错了。
- 填充位(P, 1 bit):为 1 时表示尾部有填充字节。我在项目中遇到过某些老旧编码器,为了对齐包长会设这个位——解码时得小心,别把填充当数据。
- 扩展位(X, 1 bit):为 1 时头部后面跟着扩展头。有些厂商会用它传私有信息,比如摄像头 ID。我个人不建议滥用,容易造成互操作问题。
- CSRC 计数(CC, 4 bits):后面 CSRC 列表的长度。最多 15 个。
- 标记位(M, 1 bit):应用自定义。比如视频帧边界、音频 talkspurt 开始。我习惯用它标记关键帧。
- Payload Type(PT, 7 bits):下面单独讲。
- 序列号(Sequence Number, 16 bits):下面单独讲。
- 时间戳(Timestamp, 32 bits):下面单独讲。
- SSRC(32 bits):下面单独讲。
- CSRC 列表(每个 32 bits,可选):混音场景才用。
核心要点:12 字节固定头 + 可选扩展。抓包时先看前两个字节,就能知道版本、填充、扩展和 CSRC 数量。这是排查问题的第一步。
1.2 Payload Type:告诉接收方“这是什么货”
PT 字段 7 位,取值范围 0–127。其中 0–95 是静态分配(比如 PT=0 是 PCMU,PT=8 是 PCMA,PT=96–127 是动态分配)。
我记得有一次排查一个视频卡顿问题,发现发送端设了 PT=98,但接收端期待的是 PT=96。两边没对齐,解码器直接罢工。你想想看,这多冤枉。
| PT 值 | 编码格式 | 时钟频率 (Hz) | 备注 |
|---|---|---|---|
| 0 | PCMU | 8000 | G.711 μ-law |
| 8 | PCMA | 8000 | G.711 A-law |
| 96 | H.264 | 90000 | 动态分配,常见值 |
| 97 | OPUS | 48000 | 动态分配,常见值 |
避坑指南:我曾经见过一个项目,动态 PT 值在 SDP 协商里写的是 96,但实际 RTP 包里发的是 97。接收端按 96 解码,全是噪音。所以,一定要用抓包工具验证实际 PT 值,别光看 SDP。
1.3 SSRC 与 CSRC:谁在说话?谁在混音?
SSRC(同步源标识符):32 位随机数,唯一标识一个 RTP 流。每个发送端必须有一个唯一的 SSRC。如果两个流 SSRC 冲突,接收端会乱套——我遇到过,画面和声音对不上,排查了半天才发现是 SSRC 撞了。
CSRC(贡献源标识符):当有混音器时,CSRC 列表记录原始源的 SSRC。比如一个会议有 3 个人在说话,混音器生成的 RTP 包里,SSRC 是混音器自己的,CSRC 列表里是那 3 个人的 SSRC。接收端看到 CSRC 就知道“哦,这包是混了张三、李四、王五的声音”。
注意:CSRC 列表只在 CC > 0 时才存在。如果 CC=0,头部就 12 字节,没有 CSRC。别多解析。
1.4 时间戳与序列号:RTP 的“心跳”和“序号”
这两个字段是 RTP 最核心的同步机制。我习惯这么理解:
- 序列号:每个 RTP 包一个,递增 1。接收端用它检测丢包、重排序。比如收到序列号 100、101、103,就知道 102 丢了。
- 时间戳:反映媒体采样时刻,单位是时钟频率的倒数。比如音频 8kHz,时间戳每 1/8000 秒加 1。视频 90kHz,每 1/90000 秒加 1。
这里有个关键点:序列号递增,时间戳不一定递增。比如视频帧可能分多个 RTP 包发送,同一帧的所有包时间戳相同,但序列号递增。接收端靠时间戳做播放同步,靠序列号做丢包检测。
实战经验:我在排查一个视频花屏问题时,发现接收端收到的序列号是连续的,但时间戳跳变很大。后来发现是发送端时间戳生成逻辑有 bug,导致接收端误以为发生了帧率变化,播放节奏全乱了。所以,时间戳的增量必须稳定,否则接收端会“晕”。
1.5 知识体系总览
下面这张图把 RTP 头部结构和关键字段的关系画出来了。你可以把它当作排查时的“地图”。
1.6 小结:这些字段怎么帮你排错?
好了,咱们过了一遍 RTP 的基础。你可能会问:“知道这些有什么用?” 我告诉你,排查问题时,这 12 字节就是你的“第一现场”。
- 花屏/卡顿:先看序列号有没有跳变。跳了就是丢包。
- 无法解码:看 Payload Type 对不对得上。对不上就是协商失败。
- 音画不同步:看时间戳增量是否稳定。不稳定就是发送端时钟有问题。
- 多流冲突:看 SSRC 是否唯一。重复了就是冲突。
个人习惯:我每次接手一个新系统,第一件事就是抓 100 个 RTP 包,手动解析头部。花 10 分钟,能省后面 10 小时的排查时间。你也试试。
这一章就到这儿。记住:RTP 头部不复杂,但每个字段都有它的使命。后面咱们会深入每个字段的调优技巧和常见坑。先把基础打牢,后面才能飞。