4、RTCP协议详解:SR/RR报告、SDES、BYE、APP包类型及作用
聊完RTP,咱们得聊聊它的“好搭档”——RTCP。RTP负责把音视频数据扔出去,但扔得怎么样?对方收到了没?网络堵不堵?这些事儿RTP一概不管。这时候RTCP就登场了。
RTCP的全称是RTP Control Protocol,说白了就是RTP的控制面。它不传音视频数据,只传控制信息。我个人习惯把RTCP比作“快递回执”——你寄了个包裹,对方收到后给你回个条,告诉你“收到了,但箱子有点瘪”。
RTCP有几种核心包类型:SR、RR、SDES、BYE、APP。咱们一个一个拆开看。
4.1 SR(Sender Report)——发送端报告
SR包是发送端发的。谁在发RTP数据,谁就要定期发SR。它告诉接收端:“我发了多少数据,时间戳是多少,你拿这个去算同步。”
SR包里最重要的字段是NTP时间戳和RTP时间戳。NTP是绝对时间,RTP是采样时钟。有了这两个,接收端就能把音视频流对齐。我在项目中遇到过音画不同步的问题,查到最后就是SR包里的NTP时间戳没对齐。
- SSRC:发送端的同步源标识符
- NTP时间戳:绝对时间(秒+微秒)
- RTP时间戳:与NTP对应的RTP时钟
- 发送包计数:从会话开始到现在的总包数
- 发送字节计数:从会话开始到现在的总字节数
你想想看,如果没有SR,接收端只知道“我收到了一个RTP包”,但不知道这个包对应什么时间点。有了SR,接收端就能把RTP时间戳映射到真实时间,音视频同步才有基础。
4.2 RR(Receiver Report)——接收端报告
RR包是接收端发的。它告诉发送端:“我收到了多少包,丢了多少,抖动多大,延迟多少。” 说白了,这就是接收端给发送端的“反馈”。
RR包里最核心的是丢包率和往返时延(RTT)。发送端看到丢包率高了,就知道该降码率了;看到RTT大了,就知道网络拥塞了。WebRTC的拥塞控制算法,很大程度上依赖RR包里的这些数据。
| RR报告块字段 | 含义 | 我踩过的坑 |
|---|---|---|
| 丢包率 | 从上次报告到现在的丢包比例 | 注意是比例,不是绝对值 |
| 累计丢包数 | 从会话开始到现在的总丢包数 | 这个值会溢出,要处理回绕 |
| 到达时间抖动 | 包到达时间的统计方差 | 抖动大不代表丢包,但说明网络不稳定 |
| 最后SR时间戳(LSR) | 最近收到的SR中的NTP时间 | 用于计算RTT,必须精确 |
| 延迟自最后SR(DLSR) | 从收到SR到发送RR的延迟 | 这个值不准,RTT就算不准 |
4.3 SDES(Source Description)——源描述包
SDES包用来描述RTP源的“身份信息”。它不参与流控,但参与会话管理。最常见的SDES项是CNAME(规范名称)。
CNAME是每个RTP源的唯一标识。为什么需要CNAME?因为同一个用户可能有多个SSRC(比如音频一个、视频一个),但CNAME是同一个。这样接收端就知道“这两个流来自同一个人”。
SDES还有其他项:NAME(用户名)、EMAIL(邮箱)、TOOL(工具名)。不过说实话,我在实际项目中只用CNAME,其他项基本没用过。WebRTC的实现里也只强制要求CNAME。
- CNAME:规范名称,必须唯一
- NAME:用户显示名
- EMAIL:用户邮箱
- TOOL:生成RTP流的工具名
- NOTE:临时备注(很少用)
4.4 BYE(Goodbye)——离开通知
BYE包很简单,就是告诉对方:“我要走了,不发了。” 当参与者离开会话时,发送BYE包。接收端收到BYE后,就知道这个源不会再发数据了,可以清理资源。
BYE包里可以带一个可选的原因字段。比如“user left”或“session ended”。不过大多数实现里,原因字段都是空的。我建议至少填个简单的原因,方便调试时排查问题。
4.5 APP(Application-Defined)——应用自定义包
APP包是RTCP留给应用层的“扩展接口”。标准RTCP包不够用时,你可以用APP包定义自己的控制消息。APP包里有一个4字节的“名字”字段(ASCII字符),用来标识你的应用类型。
我在项目中用过APP包来传递自定义的QoS信息。比如发送端告诉接收端“当前编码器用了什么参数”,或者接收端告诉发送端“请切换到低分辨率”。这些信息标准RTCP包不提供,但APP包可以搞定。
不过要注意,APP包是应用层定义的,不同实现之间可能不兼容。如果你用了APP包,一定要在信令阶段协商好。
4.6 RTCP包结构总览
咱们用一张图来总结RTCP的包类型和它们之间的关系:
4.7 RTCP的发送间隔与带宽控制
RTCP不能发得太频繁,否则会占用太多带宽。标准规定RTCP带宽通常占会话总带宽的5%。其中SR/RR占75%,SDES占25%。BYE和APP不单独分配带宽。
发送间隔的计算公式是:间隔 = 平均RTCP包大小 / (RTCP带宽 / 参与者数量)。参与者越多,间隔越长。这就是为什么大会议里RTCP报告来得慢——人太多了,每个人都要排队发。
4.8 实际项目中的RTCP处理
在WebRTC里,RTCP的处理是自动的。你不需要手动构造SR或RR包,libwebrtc会帮你搞定。但理解这些包的含义,对排查问题非常有帮助。
我记得有一次线上会议频繁卡顿,抓包一看,RR包里的丢包率高达15%。但网络工程师说网络没问题。后来发现是接收端的缓冲区太小,导致包被丢弃了。RR报告里的“丢包”不一定是网络丢包,也可能是应用层丢包。
所以,当你看到RR报告里的丢包率异常时,别急着怪网络。先检查一下接收端的缓冲区设置、CPU负载、解码器状态。这些因素都可能导致“假丢包”。
| 包类型 | PT值 | 方向 | 核心作用 |
|---|---|---|---|
| SR | 200 | 发送端→接收端 | 报告发送统计和时间同步 |
| RR | 201 | 接收端→发送端 | 报告接收统计和QoS反馈 |
| SDES | 202 | 双向 | 源身份描述(CNAME) |
| BYE | 203 | 双向 | 通知离开会话 |
| APP | 204 | 双向 | 应用自定义控制消息 |
RTCP是WebRTC流控的“眼睛”。没有它,发送端就是盲人摸象,不知道网络状况如何。理解了SR和RR,你就掌握了流控的反馈回路;理解了SDES和BYE,你就掌握了会话管理的基础;理解了APP,你就有了扩展的余地。