Catalog
  1. 1. rtcp (RTP control protocol)
    1. 1.1. 协议分析
    2. 1.2. 字段说明
    3. 1.3. PT 分类
    4. 1.4. PT=205 payload 说明
  2. 2. rtp
    1. 2.1. 协议分析
    2. 2.2. 字段说明
    3. 2.3. round-trip time 计算
  3. 3. 参考
rtp协议-WebRTC系列NO.3

webrtc 使用 rtp/rtcp 作为通信协议。rtp 是数据传输协议,rtcp 是 rtp 的扩展,发送一些控制信息,提供会话质量、通信性能等信息。rtp和rtcp可以共用一个通道,虽然头部略有不同,不过标准通过对 payloadtype 进行规划以区分两者,这样可以节省一个通道资源。

rtcp (RTP control protocol)

rtcp 定期向会话中的参与者发送控制包。他的主要用途有这些:

  1. 提供反馈包,反映媒体数据传输的质量 (sender report / receiver report)。
  2. 传输 CNAME
  3. 控制 RTCP 发包频率
  4. 传输会话信息, 比如应用需要展示的参会人员标识。

协议分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//  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 | header
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC of packet sender |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// RECEIVER REPORT // 接收者报告
// | SSRC_1 (SSRC of first source) | report
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
// | fraction lost | cumulative number of packets lost | 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | extended highest sequence number received |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | interarrival jitter |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | last SR (LSR) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | delay since last SR (DLSR) |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | SSRC_2 (SSRC of second source) | report
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
// : ... : 2
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | profile-specific extensions |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// SENDER REPORT // PT = 200 // 发送者报告
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | NTP timestamp, most significant word NTS |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | NTP timestamp, least significant word |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | RTP timestamp RTS |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | sender's packet count SPC |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | sender's octet count SOC |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 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 | header
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | SSRC/CSRC_1 | chunk 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SDES items |
// | ... |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | SSRC/CSRC_2 | chunk 2
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SDES items |
// | ... |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
//
//
// 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| FMT=15 | PT=206 | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC of packet sender |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC of media source |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Unique identifier 'R' 'E' 'M' 'B' |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Num SSRC | BR Exp | BR Mantissa | max= mantissa*2^exp
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC feedback |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ...


// Generic NACK RTCP_RTP_FB + (FMT 1)rfc4585
// 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=205 | length | header
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC of packet sender |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ssrcsource |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | PID | BLP |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public:
uint32_t blockcount :5;
uint32_t padding :1;
uint32_t version :2;
uint32_t packettype :8; // 包类型, 看下面的 PT 说明。
uint32_t length :16;
uint32_t ssrc;

union report_t {
// RR 接受者报告内容
struct receiverReport_t {
uint32_t ssrcsource;
/* RECEIVER REPORT DATA*/
uint32_t fractionlost:8;
int32_t lost:24;
uint32_t seqnumcycles:16;
uint32_t highestseqnum:16;
uint32_t jitter;
uint32_t lastsr;
uint32_t delaysincelast;
} receiverReport;

// SR 发送者报告内容
struct senderReport_t {
uint64_t ntptimestamp;
uint32_t rtprts;
uint32_t packetsent;
uint32_t octetssent;
struct receiverReport_t rrlist[1];
} senderReport;

// 丢包信息
struct genericNack_t {
uint32_t ssrcsource;
NackBlock nack_block;
} nackPacket;

struct remb_t {
uint32_t ssrcsource;
uint32_t uniqueid;
uint32_t numssrc:8;
uint32_t brLength :24;
uint32_t ssrcfeedb[50];
} rembPacket;

struct pli_t {
uint32_t ssrcsource;
uint32_t fci;
} pli;

struct fir_t {
uint32_t ssrcsource;
uint32_t mediasource;
uint32_t seqnumber:8;
uint32_t reserved:24;
} fir;
} report;

字段说明

length: 占两个字节,存放了整个 RTCP 包的长度值减 1,单位是 4 字节。 如果length=10,那么实际的长度是 (10+1)*4 字节。
ssrc: 占 4 字节, 表示信源,可以看作是用户标识。

PT 分类

类型 范围
rtcp 大于等于194,小于等于223
feedback 201,205, 206
  • SR 200
  • RR 201
  • SDES 202
  • BYE 203
  • APP 204

RCTP PT 来源参考附件

PT=205 payload 说明

RTPFB Transport layer FB message

1
2
3
4
5
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ssrcsource |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | PID | BLP |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

PID(Packet ID ): 16 bits, PID 字段填充了丢失的 RTP 包的序号。
BLP(bit mask of following lost packets): 16 bits, BLP 用户表示 PID 指定序号之后的 16 个包是否有丢包。 BLP 的第 i 为为 1 表示 PID + 1 序号的包丢包了。

rfc4585
The BLP allows for reporting losses of any of the 16 RTP packets
immediately following the RTP packet indicated by the PID. The
BLP’s definition is identical to that given in [6]. Denoting the
BLP’s least significant bit as bit 1, and its most significant bit
as bit 16, then bit i of the bit mask is set to 1 if the receiver
has not received RTP packet number (PID+i) (modulo 2^16) and
indicates this packet is lost; bit i is set to 0 otherwise. Note
that the sender MUST NOT assume that a receiver has received a
packet because its bit mask was set to 0. For example, the least
significant bit of the BLP would be set to 1 if the packet
corresponding to the PID and the following packet have been lost.
However, the sender cannot infer that packets PID+2 through PID+16
have been received simply because bits 2 through 15 of the BLP are
0; all the sender knows is that the receiver has not reported them
as lost at this time.

rtp

协议分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//    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|X| CC |M| PT | sequence number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | timestamp |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | synchronization source (SSRC) identifier |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | contributing source (CSRC) identifiers |
// | .... |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | defined by profile | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | header extension |
// | ....
1
2
3
4
5
6
7
8
9
10
11
12
13
static const int MIN_SIZE = 12;
uint32_t cc :4;
uint32_t hasextension :1;
uint32_t padding :1;
uint32_t version :2;
uint32_t payloadtype :7; //PT
uint32_t marker :1;
uint32_t seqnum :16;
uint32_t timestamp;
uint32_t ssrc;
uint32_t extensionpayload:16;
uint32_t extensionlength:16;
uint32_t extensions;

字段说明

V (version): 2 bits, 版本号, 固定值 2
P (padding): 1 bit, 如果该位被设置了,那么包体末尾会包含多个8位字节的填充。填充内容的最后一个字节表示填充内容数据的长度(包括他自己)。在加密场景下,需要填充字节以做到块对齐。
X (extension): 1 bit, 如果该值被设置了,那么紧随 rtp 头之后(CSRC 之后)的应该是一个扩展头。
CC (CSRC count): 4 bits, 表示了 rtp header 中包含 CSRC 标识的数量(SSRC 之后是 CSRC 列表)。
M (marker): 标志着一个 rtp 分包的结束。比如视频的 I 帧可能很大,就会分片发送。(或还有其他定义)
PT: payload type, 存放媒体类型的值,比如 opus 值是 111 (PS: 待查阅映射关系,补全这里的文档)
sequence number: 16 bits , 每发送一个 rtp 包, 该值增加 1,可用来做丢包检测,方丢包。初始值为随机值。
timestamp: 32 bits
SSRC: 32 bits, 标识媒体源,每个媒体源的值不同。
CSRC 列表: 0 ~ 15 个, 每个 32 bits。

RTP PT 来源参考附件

round-trip time 计算

1
2
//公式
rtt = A - LSR - DLSR

这里说明一下, 假设有两个peer, 一个是 S, 一个是 R。现在 S 给 R 发了一个 RR 包。RR 包中包含了两个数值,如下:

  1. LSR, 这个值表示 S 收到 SR 包的时间。
  2. DLSR, 这个值表示 S 发送 RR 包时,距离 LSR 的时间长度。
    最后 A 表示 R 收到 RR 包的时间。所以rtt计算公式如上所示。

参考

rfc3550 RTP: A Transport Protocol for Real-Time Applications
rfc5761 Multiplexing RTP and RTCP
rtp parameters

Author: 42
Link: http://blog.ikernel.cn/2019/11/13/rtp%E5%92%8Crtcp%E5%8D%8F%E8%AE%AE/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment