RSTP、RTP、RTCP

RTSP RTP RTCP

RTP(Real-time Transport Protocol),即实时传输协议,是一个应用层的协议,定义了在网络上传输音频和视频的标准数据包的格式。通常说的 RTSP 包括 RTSP 协议、RTP 协议、RTCP 协议,对于这些协议的作用简单的理解如下:

  • RTSP协议:负责服务器与客户端之间的请求与响应

    一般RTSP服务器会从设备(如摄像头)中获取媒体流,并提供一个 RTSP URL 供客户端进行连接,客户端通过 RTSP URL 向服务器发起连接请求,服务器响应,两者开始交换数据,最后建立连接。

  • RTP协议:负责服务器与客户端之间传输媒体数据

    RTP 的端口号通常为偶数,在连接建立后,客户端请求媒体数据,之后服务器通过将媒体流封装为 RTP 包发送给客户端。通常 RTP 的端口为偶数。可以使用 TCP 或者 UDP,一般使用 UDP 并使用 RTCP 协议保证流媒体音视频质量。仅仅是发包。

  • RTCP 协议:负责提供有关RTP传输质量的反馈,就是确保RTP传输的质量

    RTCP 的端口号通肠为对应的 RTP 端口号加1。通过 RTCP 协议来对 RTP 包进行控制。

  • 三者的关系:rtsp 并不会发送媒体数据,只是完成服务器和客户端之间的信令交互,rtp 协议负责媒体数据传输,rtcp 负责 rtp 数据包的监视和反馈。rtp 和 rtcp 并没有规定传输层的类型,可以选择 udp 和 tcp。Rtsp 的传输层则要求是基于 tcp。

RTSP 协议

嵌入式设备(如摄像头)通过服务器生成一个 RTSP URL,客户端通过这个 URL 与服务器建立连接传输媒体流,建立连接的过程用 RTSP(传输层用 TCP )来完成信令的交互。连接建立后通过 RTP 协议来传输媒体流数据包,通过 RTCP 协议来负责 RTP 数据包的监视和反馈。两者可以选择使用 UDP 或者 TCP。

RTSP URL

bash
1
2
3
4
rtsp_URL = "rtsp://" host [":" port] [ abs_path ]
host: 有效的域名或 IP 地址
port: 端口号,缺省为 554,若为缺省可不填写,否则必须写明
例如:rtsp://media.example.com:554/twister/audiotrack

以海康摄像机为例,其 RTSP URL 格式为:

bash
1
2
3
4
rtsp://[username]:[password]@[ip]:[port]/[channel]/[subtype]/av_stream
例如:
rtsp://admin:12345@192.168.1.67:554/h264/ch1/main/av_stream
rtsp://admin:12345@192.168.1.67/mpeg4/ch1/sub/av_stream

RTSP 报文

RTSP 是一种基于文本的协议,用 CRLF (回车换行) 作为每一行的结束符,其好处是,在使用过程中可以方便地增加自定义参数,也方便抓包分析。从消息传送方向上来分,RTSP 的报文有两类:请求报文和响应报文。请求报文是指从客户端向服务器发送的请求 (也有少量从服务器向客户端发送的请求),响应报文是指从服务器到客户端的回应。

RTSP 请求报文的常用方法:

方法 方向 对象 是否必要 作用
DESCRIBE C->S P, S 推荐 得到会话描述信息
ANNOUNCE C->S, S->C P, S 可选
GET_PARAMETER C->S, S->C P, S 可选
OPTIONS C->S, S->C P, S 必须 (S->C: 可选) 获得服务器提供的可用方法
PAUSE C->S P, S 推荐 客户端发起暂停播放请求
PLAY C->S P, S 必须 客户端发起播放请求
RECORD C->S P, S 可选
REDIRECT S->C P, S 可选
SETUP C->S S 必须 客户端请求建立会话
SET_PARAMETER C->S, S->C P, S 可选
TEARDOWN C->S P, S 必须 客户端发起关闭会话

通过 VLC 播放 RTSP 网络流,经抓包得以下内容:

bash
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
90
OPTIONS rtsp://192.168.199.152:554/live/test RTSP/1.0
CSeq: 2
User-Agent: LibVLC/3.0.8 (LIVE555 Streaming Media v2016.11.28)

RTSP/1.0 200 OK
CSeq: 2
Date: Mon, Jul 27 2020 15:32:38 GMT
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, RECORD, SET_PARAMETER, GET_PARAMETER
Server: ZLMediaKit-5.0(build in Jul 12 2020 14:02:13)

DESCRIBE rtsp://192.168.199.152:554/live/test RTSP/1.0
CSeq: 3
User-Agent: LibVLC/3.0.8 (LIVE555 Streaming Media v2016.11.28)
Accept: application/sdp

RTSP/1.0 200 OK
Content-Base: rtsp://192.168.199.152:554/live/test/
Content-Length: 544
Content-Type: application/sdp
CSeq: 3
Date: Mon, Jul 27 2020 15:32:38 GMT
Server: ZLMediaKit-5.0(build in Jul 12 2020 14:02:13)
Session: hEu0JzMKcfK2
x-Accept-Dynamic-Rate: 1
x-Accept-Retransmit: our-retransmit

v=0
o=- 0 0 IN IP4 127.0.0.1
c=IN IP4 127.0.0.1
t=0 0
s=Streamed by ZLMediaKit-5.0(build in Jul 12 2020 14:01:57)
a=tool:libavformat 58.29.100
m=video 0 RTP/AVP 96
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAHqzZQNg95f/wFAAUEQAAAwABAAADADIPFi2W,aOvjyyLA; profile-level-id=64001E
a=rtpmap:96 H264/90000
a=control:streamid=0
m=audio 0 RTP/AVP 97
b=AS:128
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=121056E500
a=rtpmap:97 MPEG4-GENERIC/44100/2
a=control:streamid=1
SETUP rtsp://192.168.199.152:554/live/test/streamid=0 RTSP/1.0
CSeq: 4
User-Agent: LibVLC/3.0.8 (LIVE555 Streaming Media v2016.11.28)
Transport: RTP/AVP;unicast;client_port=60836-60837

RTSP/1.0 200 OK
CSeq: 4
Date: Mon, Jul 27 2020 15:32:38 GMT
Server: ZLMediaKit-5.0(build in Jul 12 2020 14:02:13)
Session: hEu0JzMKcfK2
Transport: RTP/AVP/UDP;unicast;client_port=60836-60837;server_port=41070-41071;ssrc=50E36E3B

SETUP rtsp://192.168.199.152:554/live/test/streamid=1 RTSP/1.0
CSeq: 5
User-Agent: LibVLC/3.0.8 (LIVE555 Streaming Media v2016.11.28)
Transport: RTP/AVP;unicast;client_port=60838-60839
Session: hEu0JzMKcfK2

RTSP/1.0 200 OK
CSeq: 5
Date: Mon, Jul 27 2020 15:32:38 GMT
Server: ZLMediaKit-5.0(build in Jul 12 2020 14:02:13)
Session: hEu0JzMKcfK2
Transport: RTP/AVP/UDP;unicast;client_port=60838-60839;server_port=58452-58453;ssrc=3463B21F

PLAY rtsp://192.168.199.152:554/live/test/ RTSP/1.0
CSeq: 6
User-Agent: LibVLC/3.0.8 (LIVE555 Streaming Media v2016.11.28)
Session: hEu0JzMKcfK2
Range: npt=0.000-

RTSP/1.0 200 OK
CSeq: 6
Date: Mon, Jul 27 2020 15:32:38 GMT
Range: npt=42535.41
RTP-Info: url=rtsp://192.168.199.152:554/live/test/streamid=0;seq=3889;rtptime=-466780396,url=rtsp://192.168.199.152:554/live/test/streamid=1;seq=1155;rtptime=-179511072
Server: ZLMediaKit-5.0(build in Jul 12 2020 14:02:13)
Session: hEu0JzMKcfK2

TEARDOWN rtsp://192.168.199.152:554/live/test/ RTSP/1.0
CSeq: 7
User-Agent: LibVLC/3.0.8 (LIVE555 Streaming Media v2016.11.28)
Session: hEu0JzMKcfK2

RTSP/1.0 200 OK
CSeq: 7
Date: Mon, Jul 27 2020 15:32:41 GMT
Server: ZLMediaKit-5.0(build in Jul 12 2020 14:02:13)
Session: hEu0JzMKcfK2

从上述抓包中看出,VLC 在播放 RTSP 网络流时,客户端与服务端经过了 6 次交互:

序号 方向 方法 消息内容
1 C->S OPTIONS Client 询问 Server 有哪些方法可用
1 S->C OPTIONS Server 回应所有可用的方法
2 C->S DESCRIBE Client 请求得到 Server 提供的媒体初始化描述信息
2 S->C DESCRIBE Server 回应媒体初始化信息,主要是 SDP (会话描述协议)
3 C->S SETUP 设置视频会话属性以及传输模式,请求建立会话
3 S->C SETUP Server 建立会话,返回会话标识以及会话相关信息
4 C->S SETUP 设置音频会话属性以及传输模式,请求建立会话
4 S->C SETUP Server 建立会话,返回会话标识以及会话相关信息
5 C->S PLAY Client 请求播放
5 S->C PLAY Server 回应播放请求
6 C->S TEARDOWN Client 请求关闭会话
6 S->C TEARDOWN Server 回应关闭会话请求

下面我们一步一步了解 RTSP 会话建立流程:

OPTIONS

OPTIONS 请求可以在任何时间被发出,而且不会影响到 Server 的状态,例如:

bash
1
2
3
4
5
6
7
8
C->S:  OPTIONS * RTSP/1.0
CSeq: 1
Require: implicit-play
Proxy-Require: gzipped-messages

S->C: RTSP/1.0 200 OK
CSeq: 1
Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE

DESCRIBE

客户端向服务器请求媒体资源描述,服务器端通过 SDP (Session Description Protocol) 格式回应客户端的请求。资源描述中会列出所请求媒体的媒体流及其相关信息,典型情况下,音频和视频分别作为一个媒体流传输。例如:

bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
C->S: DESCRIBE rtsp://server.example.com/fizzle/foo RTSP/1.0
CSeq: 312
Accept: application/sdp, application/rtsl, application/mheg

S->C: RTSP/1.0 200 OK
CSeq: 312
Date: 23 Jan 1997 15:35:06 GMT
Content-Type: application/sdp
Content-Length: 376

v=0
o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4
s=SDP Seminar
i=A Seminar on the session description protocol
u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps
e=mjh@isi.edu (Mark Handley)
c=IN IP4 224.2.17.12/127
t=2873397496 2873404696
a=recvonly
m=audio 3456 RTP/AVP 0
m=video 2232 RTP/AVP 31
m=whiteboard 32416 UDP WB
a=orient:portrait

媒体流及其相关信息由 SDP (Session Description Protocol) 格式携带,关于 SDP 的详细说明,参见拓展阅读 5

SETUP

SETUP 请求确定了具体的媒体流如何传输,该请求必须在 PLAY 请求之前发送。SETUP 请求包含媒体流的 URL 和客户端用于接收 RTP 数据 (audio or video) 的端口以及接收 RTCP 数据 (meta information) 的端口。服务器端的回复通常包含客户端请求参数的确认,并会补充缺失的部分,比如服务器选择的发送端口。每一个媒体流在发送 PLAY 请求之前,都要首先通过 SETUP 请求来进行相应的配置。

bash
1
2
3
4
5
6
7
8
9
C->S: SETUP rtsp://example.com/foo/bar/baz.rm RTSP/1.0
CSeq: 302
Transport: RTP/AVP;unicast;client_port=4588-4589

S->C: RTSP/1.0 200 OK
CSeq: 302
Date: 23 Jan 1997 15:35:06 GMT
Session: 47112344
Transport: RTP/AVP;unicast;client_port=4588-4589;server_port=6256-6257

PLAY

客户端通过 PLAY 请求来播放一个或全部媒体流,PLAY 请求可以发送一次或多次,发送一次时,URL 为包含所有媒体流的地址,发送多次时,每一次请求携带的 URL 只包含一个相应的媒体流。PLAY 请求中可指定播放的 range,若未指定,则从媒体流的开始播放到结束,如果媒体流在播放过程中被暂停,则可在暂停处重新启动流的播放。

bash
1
2
3
4
5
6
7
8
9
C->S: PLAY rtsp://example.com/media.mp4 RTSP/1.0
CSeq: 4
Range: npt=5-20
Session: 12345678

S->C: RTSP/1.0 200 OK
CSeq: 4
Session: 12345678
RTP-Info: url=rtsp://example.com/media.mp4/streamid=0;seq=9810092;rtptime=3450012

Server 处理 client 发来的 PLAY 请求后,就会开始向 client 发送媒体数据,一般采用 RTP 协议进行发送,关于 RTP 协议的相关说明,参见拓展阅读 6

TEARDOWN

结束会话请求,该请求会停止所有媒体流,并释放服务器上的相关会话数据。

bash
1
2
3
4
5
6
C->S: TEARDOWN rtsp://example.com/media.mp4 RTSP/1.0
CSeq: 8
Session: 12345678

S->C: RTSP/1.0 200 OK
CSeq: 8

RTP 协议

在 RTSP 的流媒体服务器中音视频的传输通过 RTP 封装将音视频帧封装为若干个 RTP 包。每个 RTP 包由 RTP Header 和音视频载荷(Payload)组成。RTP Header包含固定头和扩展头,RTP 固定头通常占 12 字节,扩展头大小可变通常不用。

RTP Header

bash
1
2
3
4
5
6
7
8
9
10
11
12
 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 |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

这 12 个字节组成的 RTP 固定头出现在每个 RTP 数据包中,这些字段具有的含义如下:

  • **版本 (V)**:2 位,该字段标识 RTP 的版本。RFC3550 定义的版本规范为 2.
  • **填充 (P)**:1 位,如果设置了填充位,则数据包包含一个或多个末尾的其他填充字节不属于有效载荷。
  • **扩展名 (X)**:1 位,如果扩展位被置位,则固定报头必须后跟一个扩展头部。
  • **CSRC 计数 (CC)**:4 位,CSRC 计数包含随后的 CSRC 标识符的数量固定头。
  • **标记 (M)**:1 位,由配置文件定义,它允许诸如框架边界之类的重要事件发生在数据包流中被标记。

**标记 (M)**:1 位,标识此 RTP 包携带了一组 NAL 数据的最后一个 NAL Unit。(RFC 6184)

  • **有效载荷类型 (PT)**:7 位,该字段标识 RTP 有效负载的格式并确定由应用程序对其进行解释。一个配置文件可以指定一个负载类型代码到负载格式的默认静态映射。
  • **序列号 (sequence number)**:16 位,每个 RTP 数据包的序列号加 1 发送,接收方可以使用它来检测丢包并恢复报文序列,序号的初始值应该是随机的。
  • **时间戳 (timestamp)**:32 位,时间戳记录了该包中数据的第一个字节的采样时刻。在一次会话开始时,时间戳初始化成一个初始值。即使在没有信号发送时,时间戳的数值也要随时间而不断地增加(时间在流逝嘛)。时间戳是去除抖动和实现同步不可缺少的。
  • **同步源标识符 (SSRC)**:32 位,同步源就是指 RTP 包流的来源。在同一个 RTP 会话中不能有两个相同的 SSRC 值。该标识符是随机选取的 RFC1889 推荐了 MD5 随机算法。
  • **贡献源列表 (CSRC List)**:0~15 项,每项 32 位,用来标志对一个 RTP 混合器产生的新包有贡献的所有 RTP 包的源。由混合器将这些有贡献的 SSRC 标识符插入表中。SSRC 标识符都被列出来,以便接收端能正确指出交谈双方的身份。

RTP 载荷

在 RTSP 等实时流传输中常见的编码格式是 H264/H265 以及音频 AAC。不同的编码格式在 RTP 包中的封装过程有所不同,比如 H264 和 H265 需要去掉码流中的启始码 (0x000001),音频 AAC 需要去掉 AAC 的头部字段 ADTS 数据,在 H264 封装 RTP 包过程需要去掉1个字节的 NAL Unit 头,在 H265 封装过程需要去掉2个字节的 NAL Unit 头。