RTCP
基本概念
RTCP 是 RTP 的控制协议,用于监控媒体传输质量和参与者状态,并与 RTP 一起工作。RTP 用于传输媒体数据(如音视频),RTCP 则用于传输控制信息。
RTCP 通常和 RTP 同时使用,并通过 不同端口(通常 RTP 使用偶数端口,RTCP 使用其下一个奇数端口)。
主要用于:
- 传输质量反馈:丢包率、时延、抖动等统计信息。
- 媒体源身份识别:包括 CNAME(Canonical Name)标识每个参与者。
- 带宽控制:用于避免 RTCP 消息对带宽占用过大(典型限制为 5%)。
- 多方会话控制:尤其适用于多点会议。
基本结构
每个 RTCP 包由一个公共头部 + 特定类型的负载数据组成。基本的 RTCP 报文格式如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| RC | PT=SR=200 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- V:版本,通常为2
- P:填充位(padding)
- RC:Reception Report Count,表示包含多少个 reception report block(在 SR/RR 包中)
- PT:Payload Type,表明 RTCP 包类型
- length:包长度(以 32 位字为单位,不包括头部)
RTCP包类型(Payload Type)
类型 | 名称 | PT 值 | 用途 |
---|---|---|---|
SR | Sender Report | 200 | 发送端统计信息 |
RR | Receiver Report | 201 | 接收端反馈信息 |
SDES | Source Description | 202 | 源描述(包括 CNAME) |
BYE | Goodbye | 203 | 终止会话 |
APP | Application-defined | 204 | 自定义扩展 |
Sender Report (SR) — PT=200
结构
一个完整的 RTCP SR 包结构如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| RC | PT=SR=200 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of sender |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NTP timestamp, most significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NTP timestamp, least significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's packet count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's octet count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Report block 1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Report block 2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段解释
字段 | 说明 |
---|---|
V (2 bits) | RTP 版本,固定为 2 |
P (1 bit) | 填充位,最后是否有填充字节 |
RC (5 bits) | 下面附带的 Reception Report 数量(最多 31 个) |
PT = 200 | Payload Type,200 表示 SR |
Length | 整个 RTCP 包长度(以 32 位字为单位,减1) |
SSRC of sender | 当前发送者的同步源标识 |
NTP timestamp | NTP 格式的时间戳(64 位),用于同步 |
RTP timestamp | 与 NTP 时间同步的 RTP 时间戳(32 位) |
Sender’s packet count | 发送的 RTP 包总数 |
Sender’s octet count | 发送的 RTP 字节总数 |
Report blocks | 针对接收端的报告,最多 31 个,每个包含丢包率、抖动、延迟等统计信息 |
Report Block 格式(每个 24 字节)
包含如下字段:
- SSRC of source
- Fraction lost
- Cumulative number of packets lost
- Extended highest sequence number received
- Interarrival jitter
- Last SR timestamp (LSR)
- Delay since last SR (DLSR)
Receiver Report (RR) — PT=201
结构
RR 包结构和 SR 类似,但没有发送者统计字段,仅包含一组或多组接收统计报告:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| RC | PT=RR=201 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of packet sender |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Report block 1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Report block 2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段解释
字段 | 说明 |
---|---|
V (2 bits) | RTP 版本号,固定为 2 |
P (1 bit) | 填充标志 |
RC (5 bits) | Report Count,表示下面有几个 report block(最多 31 个) |
PT = 201 | Payload Type,201 表示 RR |
Length | RTCP 包长度(32bit 字为单位,减去1) |
SSRC of sender | 当前报告者(接收端)的 SSRC |
Report blocks | 一个或多个 24 字节的 report block,描述对应源的接收质量 |
Report Block 格式(每个 24 字节)
每个 Report Block 针对一个 RTP 源(发送者)统计信息:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC_1 (源 SSRC) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| fraction lost | cumulative number of packets lost |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extended highest sequence number received |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| interarrival jitter |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| last SR (LSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| delay since last SR (DLSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段 | 说明 |
---|---|
SSRC_n | 被监视的发送者(源) SSRC |
fraction lost | 自上次报告后丢失的 RTP 包比例(0-255) |
cumulative number of packets lost | 接收到当前为止丢失的总包数 |
extended highest seq no received | 接收的最大序列号(扩展 32 位) |
interarrival jitter | 包到达间隔抖动 |
last SR (LSR) | 上次收到的 SR 报告的 NTP 时间戳中间 32 位(即 SR 的发送时间) |
delay since last SR (DLSR) | 自从收到上一个 SR 以来的时间(单位为 1/65536 秒) |
SDES
结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| SC | PT=SDES=202 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC/CSRC_1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SDES items (可变长) |
| ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC/CSRC_n |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SDES items |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段解释
字段 | 说明 |
---|---|
V (2 bits) | RTP 版本号,固定为 2 |
P (1 bit) | 填充位 |
SC (5 bits) | Source Count,本包中包含多少个源(SSRC/CSRC) |
PT = 202 | Payload Type,202 表示 SDES |
length | RTCP 包长度(单位是 32bit 字,减 1) |
SSRC/CSRC | 与该描述项相关的源的 ID |
SDES items | 描述此源的项 |
SDES Item
每个 SDES item 的格式如下:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| item type | length | user data (variable length) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
常见 item types(1 字节):
Type | 名称 | 说明 |
---|---|---|
1 | CNAME | 参与者唯一标识(必选) |
2 | NAME | 用户名/显示名 |
3 | 电子邮件地址 | |
4 | PHONE | 电话号码 |
5 | LOC | 地理位置 |
6 | TOOL | 使用的工具名(如 FFmpeg) |
7 | NOTE | 备注 |
8 | PRIV | 私有扩展项 |
0 | END | 结束标记,标志该 SDES 项结束 |
示例:
| 1 (CNAME) | 9 | "user@host" |
| 2 (NAME) | 4 | "John" |
| 0 (END) | | |
BYE
结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| SC | PT=BYE=203 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC/CSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: ... :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| length | optional reason for leaving... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段解释
字段 | 说明 |
---|---|
V (2 bits) | RTP 协议版本,固定为 2 |
P (1 bit) | 填充标志 |
SC (5 bits) | Source Count,本包中包含多少个 SSRC/CSRC |
PT = 203 | Payload Type,203 表示 BYE |
length | 包长度,以 32bit 字为单位(不含 header 自身) |
SSRC/CSRC | 要离开的同步源(可以多个) |
可选 Reason 字段 | 一个字符串,表示离开原因(可选) 格式为:1字节长度 + UTF-8 字符串 |
示例
一个 BYE 包可能如下:
- SSRC:
0x87654321
- Reason:
"stream ended"
在 Wireshark 中可看到:
RTCP: Goodbye (BYE)
SSRC: 0x87654321
Reason: stream ended
APP
结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| Subtype | PT=APP=204 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC/CSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| name (ASCII) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| application-dependent data |
| ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段解释
字段 | 含义 |
---|---|
V (2 bits) | RTP 版本号,固定为 2 |
P (1 bit) | Padding 标志位 |
Subtype (5 bits) | 应用自定义子类型(0~31) |
PT (8 bits) | Payload Type,204 表示 APP 包 |
Length (16 bits) | 包长度(以 32bit 字为单位,减 1) |
SSRC | 应用定义者的 SSRC |
Name (32 bits) | ASCII 字母组成的 4 字节标识符(如 "TEST" ) |
Application-dependent data | 由应用定义的任意内容(可变长) |
SRTCP(Secure RTCP)
基本概念
SRTCP 是 RTCP 的 安全扩展协议,用于 加密、消息认证(MAC)以及重放保护,与 SRTP(Secure RTP) 相对,主要用于保障 RTCP 报文的保密性和完整性。
功能 | 描述 |
---|---|
加密(可选) | 加密 RTCP payload(如 Sender Report) |
完整性验证 | 使用 HMAC(通常为 HMAC-SHA1) |
防重放攻击 | 使用 SRTCP Index(31 bit 计数器) |
基本结构
原始的RTCP报文:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| RC | PT=SR=200 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of sender |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... (RTCP payload)
SRTCP 的格式是在 RTCP 基础上加入加密、认证和重放保护:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|E| SRTCP index |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Authentication tag (可选,MAC) |
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段说明:
字段 | 长度 | 描述 |
---|---|---|
E(Encryption Flag) | 1 bit | 表示 RTCP payload 是否被加密(1 为加密) |
SRTCP index | 31 bits | 单调递增的计数器(防重放攻击、同步) |
Authentication tag | 可选,通常 10/20 字节 | 用于认证的 HMAC,防止篡改 |
示例:SRTCP 报文结构图(含加密)
+-------------------------------+
| RTCP 原始报文(明文/密文) |
+-------------------------------+
| E | SRTCP index |
+-------------------------------+
| Authentication tag |
+-------------------------------+
如果 E=0:RTCP payload 是明文;
如果 E=1:RTCP payload 是密文;
Authentication tag 总是对前面部分进行 HMAC 计算,用于完整性校验与认证。
标准文档
https://datatracker.ietf.org/doc/html/rfc3711
WebRTC中的RTCP和SRTCP
WebRTC中的RTCP
- 默认开启 RTCP 复用(RTCP-MUX,RFC 5761):音视频和控制数据共用同一个 UDP 端口
- 使用 RTCP 扩展报文(如 RTP Feedback)实现自适应码率与拥塞控制
- 可以携带统计反馈,供算法调整使用(如 Google Congestion Control)
WebRTC中的SRTCP
- 防止中间人查看控制信令(如 SSRC、网络状态)
- 防止伪造控制指令(如虚假 NACK、PLI、BYE)
- 防止重放攻击干扰会话状态
DTLS-SRTP
WebRTC 使用如下流程保护媒体:
[RTP/RTCP] -> SRTP/SRTCP 加密 -> 通过 UDP 发送
↑
DTLS 协议协商密钥
DTLS 协议运行在媒体端口上(UDP),协商密钥;
协商结果用于派生 SRTP/SRTCP 的加密密钥;
然后媒体通过 SRTP 和 SRTCP 加密发送;
不会单独发送明文 RTP/RTCP。