本文未经允许,不得转发!!!
目录
🎄一、概述
rtsp,全称时 real time streaming protocol
,实时流媒体协议,是tcp/ip协议体系中的一个应用层协议,由哥伦比亚大学、网景和realnetworks公司提交的 ietf rfc 标准。
关于 rtsp 协议的官方文档是 rfc2326,文档链接 :rfc2326-real time streaming protocol (rtsp)。
rtsp 协议的语法和操作参考了 http/1.1
,基于文本的协议,采用iso10646字符集,使用utf-8编码;承载rtsp的传输层协议为tcp
,默认端口554
;如果是rtsp-over-http tunneling,则默认tcp端口为8080;一般与rtp/rtcp协议搭配使用,由rtp协议传输实时流数据,rtcp协议完成数据流和控制命令的传输。
🎄二、rtsp 方法
rtsp常用的方法包括:options、describe、setup、play、pause、teardown、announce、get_parameter和set_parameter等。详细使用介绍如下:
options
:客户端向服务器获取服务器支持的方法。它不影响服务器的状态;describe
:客户端向服务器获取url指定的媒体对象的描述,其中accept
字段指定了描述格式;setup
:客户端向服务器请求建立会话并准备传输。请求信息主要包括传输协议和客户端的端口号;play
:客户端主动通知服务器以setup指定的机制开始发送数据。其中range
字段指定了播放的起止时间(实时流range一般为range: npt=0.000-
),当多个play请求到达时,服务器会将play请求排成队列,顺序执行,即必须等待第一个play的时间完成后,才会继续处理第二个play消息。pause
:客户端请求服务器的媒体流传输临时暂停。可以通过range
参数在指定时间点暂停,也可以指定某股流暂停,例如,如果指定音频流暂停,则播放将是无音状态record
:record通知服务器,客户端将会根据之前的描述开始记录媒体数据。 其中timestamp
字段反映开始和结束时间 (utc)。如果该字段不存在,则会使用媒体描述中的开始或结束时间。 如果会话已经开始,则立即开始录制。
服务器决定是将记录的数据存储在request-uri
下还是另一个 uri 下。 如果服务器不使用 request-uri,则响应应该是 201(已创建)并包含描述请求状态并引用新资源的实体和 location 标头。teardown
:客户端请求停止指定url流发送,释放相关资源。redirect
:重定向请求,服务端通知客户端它必须连接到另一个服务器位置。 它包含强制标头 location,它指示客户端应该发出对该 url 的请求。 它可能包含参数range,表示重定向何时生效。 如果客户端想要继续发送或接收此 uri 的媒体,客户端必须为当前会话发出 teardown 请求,并在指定主机上为新会话发出 setup。announce
:当客户端向服务器发送时,表示的是将通过请求 url 识别的表示描述或者媒体对象提交给服务器
当服务器向客户端发送时,表示的是通知客户端更新会话信息get_parameter
:get_parameter 请求检索 uri 中指定的表示或流的参数值。 回复和响应的内容留给实现。 没有实体主体的 get_parameter 可用于测试客户端或服务器的活跃度(“ping”)。set_parameter
:这个方法请求设置演示或url指定流的参数值。请求仅应包含单个参数,允许客户端决定某个特殊请求为何失败。如请求包含多个参数,所有参数可成功设置,服务器必须只对该请求起作用。服务器必须允许参数可重复设置成同一值,但不让改变参数值。注意:媒体流传输参数必须用setup命令设置。将设置传输参数限制为setup有利于防火墙。
上面总共介绍了 11 个rtsp方法,其中,setup
、play
、teardown
三个命令是 rtsp 流程中必须的,其他方法非必须。而announce
、get_parameter
、set_parameter
三个命令既可以是客户端发给服务端,也可以是服务端发给客户端,其他命令都是客户端发给服务端的。
🎄三、rtsp 的 请求报文 与 响应报文
rtsp有两类报文:请求报文和响应报文。请求报文是指从客户向服务器发送请求报文,响应报文是指从服务器到客户的应答。
✨3.1 、rtsp 的 请求报文
rtsp请求报文由请求行、请求头部和请求体三个部分组成。其中,请求行是必须的,而请求头部和请求体则根据具体情况可选。
- 请求行:请求行包含一个方法、一个请求uri和一个协议版本,它们之间以空格分隔,并以crlf(即:
\r\n
)结束。
方法
:就是上面介绍的rtsp方法。包括options、describe、setup、play、pause、teardown等。
请求uri
:标识要操作的媒体资源,格式通常为rtsp://example.com/path/to/stream。
协议版本
:表示请求遵循的rtsp协议版本,一般为rtsp/1.0
或rtsp/2.0
。
下面是一个完整的请求行的示例:options rtsp://192.168.3.225:554/wbc rtsp/1.0
- 请求头部:请求头部包含一些附加信息,比如:cseq(用于标识请求的序列号)、session id(会话标识符)、transport(传输协议)等。每个头部字段由字段名、冒号和字段值组成,各头部字段之间以crlf分隔。
下面是一个完整的请求头部的示例:cseq: 2 user-agent: libvlc/3.0.19 (live555 streaming media v2016.11.28)
- 请求体:请求体是用于传输额外的数据。请求体的具体内容,取决于请求行中所使用的rtsp方法。注意:在请求头部之后,需要插入一个空行(crlf),用于区分请求头部与请求体。大部分请求报文是没有请求体的。
✨3.2 、rtsp 的 响应报文
rtsp请求报文由状态行、响应头部和响应体三个部分组成。其中,状态行是必须的,而响应头部和响应体则根据具体情况可选。
- 状态行:状态行包含一个协议版本、一个状态码和一个状态文本,它们之间由空格分隔,并以crlf(即:“\r\n”)结束。
协议版本
:表示响应遵循的rtsp协议版本,一般为rtsp/1.0或rtsp/2.0。
状态码
:三位数字,比如:200、401、500等,用于指示请求的处理结果。第一位数字代表响应类别:2xx表示成功,4xx表示客户端错误,5xx表示服务器错误。
状态文本
:简短的文字描述,解释对应状态码的具体含义,比如:ok、unauthorized等。
下面是响应行例子:rtsp/1.0 200 ok
- 响应头部:响应头部包含与请求头部类似的信息,比如:cseq(用于标识请求的序列号)、session id(会话标识符)、transport(传输协议)等。每个响应头部字段的格式与请求头部相同,故这里不再赘述。
cseq: 2 date: wed, feb 04 1970 03:25:10 gmt public: options, describe, setup, teardown, play, pause, get_parameter, set_parameter
- 响应体:某些rtsp响应(比如:describe)可能包含响应体,用于传输额外的数据。注意:在响应头部之后,需要插入一个空行(crlf),用于区分响应头部与响应体。
下面是一个完整的响应体的示例。v=0 o=- 8913478 1 in ip4 192.168.3.91 s=live555 streaming media v2016.07.19 i=1080 t=0 0 a=tool:live555 streaming media v2016.07.19 a=type:broadcast a=control:* a=range:npt=0- a=x-qt-text-nam:live555 streaming media v2016.07.19 a=x-qt-text-inf:1080 m=video 0 rtp/avp 96 c=in ip4 0.0.0.0 b=as:5000 a=rtpmap:96 h264/90000 a=fmtp:96 packetization-mode=1;profile-level-id=64002a;sprop-parameter-sets=z2qakq2eaqwgcgeaqwgcgeaqwgceo1a8arpyoa==,ao48sa== a=control:track1 m=audio 0 rtp/avp 97 c=in ip4 0.0.0.0 b=as:768 a=rtpmap:97 pcma/48000/2 a=control:track2
🎄四、rtsp 报文的常用字段
rtsp报文的响应头会包含一些字段,下面是一些常用的字段:
- accept: 用于指定客户端通知服务器自己可以接受的实体数据结构类型。例如: accept: application/sdp,之后服务器通过content-type字段返回其实体数据结构类型;
- accept-encoding:用于客户端通知服务器自己可以接受的数据压缩格式,例如:accept-encoding: gzip, compress, br,之后服务器将通过content-encoding字段通知客户端它的选择。
- accept-language: 用于客户端通知服务器自己可以理解的语言及其接受度,例如:accept-language: fr-ch, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5 ,之后服务器将通过content-language字段通知客户端它的选择
- authorization:客户端请求消息头含有服务器用于验证用户代理身份的凭证
- bandwidth: 用于描述客户端可用的带宽值。例如: bandwidth: 4000
- blocksize:此字段由客户端发送到媒体服务器,要求服务器提供特定的媒体包大小,服务器可以自由使用小于请求的块大小。 此数据包大小不包括 ip、udp 或 rtp 等低层标头
- cseq: 指定了rtsp请求响应的序列号,每个rtsp请求都必须包含一个唯一的cseq值,以便服务器能够正确地识别和处理请求。这个序列号随着请求消息递增。服务器响应必须有cseq值,指明响应哪个请求。
- cache-control:通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中
- conference:通知服务器不得更改同一 rtsp 会话的会议 id
- connection:该字段决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成或者connection: close。
- content-length:该字段指明在rtsp协议最后一个标头之后的双 crlf 之后的内容长度。例如在服务器响应describe中,指明sdp信息长度
- content-type:告诉客户端实际返回的内容的内容类型
- date:提供服务器生成响应的日期和时间,有助于客户端判断响应的新鲜度或进行时间同步。date字段的格式符合rfc 1123,比如:sat, 06 apr 2024 11:15:00 gmt。
- user-agent: 该字段用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。
- expires:指明过期的时间
- rang: 用于指定一个时间范围,可以使用smpte、ntp或clock时间单元。
- session: session头字段标识了一个rtsp会话。session id 是由服务器在
setup
的回应中选择的,客户端一当得到session id后,在以后的对session 的操作请求消息中都要包含session id.例如:session: 4581e0ae;timeout=65 - transport: transport头字段包含客户端可以接受的传输选项列表,包括传输协议,地址端口,ttl等。服务器端也通过这个头字段返回实际选择的具体选项。如: transport: rtp/avp/tcpunicast;destination=192.168.31.222;source=192.168.31.222;interleaved=0-1
🎄五、rtsp 流程抓包解析
使用wireshark抓取rtsp流媒体的网络包,可以看到其大概流程如下:
1、客户端发送options
方法,服务端回复;
2、客户端发送describe
方法,服务端回复;
3、客户端发送setup
方法,服务端回复;
2、客户端发送play
方法,服务端回复;
2、客户端发送teardown
方法,服务端回复;
完整的取流报文如下:
options rtsp://192.168.3.225:554/wbc rtsp/1.0
cseq: 2
user-agent: libvlc/3.0.19 (live555 streaming media v2016.11.28)
rtsp/1.0 200 ok
cseq: 2
date: wed, jul 03 2024 14:42:11 gmt
public: options, describe, setup, teardown, play, pause, get_parameter, set_parameter
describe rtsp://192.168.3.225:554/wbc rtsp/1.0
cseq: 3
user-agent: libvlc/3.0.19 (live555 streaming media v2016.11.28)
accept: application/sdp
rtsp/1.0 200 ok
cseq: 3
date: wed, jul 03 2024 14:42:11 gmt
content-base: rtsp://192.168.3.225/wbc/
content-type: application/sdp
content-length: 472
v=0
o=- 1720014950032000 1 in ip4 192.168.3.225
s=live555 streaming media v2016.07.19
i=wbc
t=0 0
a=tool:live555 streaming media v2016.07.19
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:live555 streaming media v2016.07.19
a=x-qt-text-inf:wbc
m=video 0 rtp/avp 96
c=in ip4 0.0.0.0
b=as:5000
a=rtpmap:96 h264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=640029;sprop-parameter-sets=z2qakawsaohgcj+wbgoccgq=,ao4xshs=
a=control:track1
setup rtsp://192.168.3.225/wbc/track1 rtsp/1.0
cseq: 4
user-agent: libvlc/3.0.19 (live555 streaming media v2016.11.28)
transport: rtp/avp;unicast;client_port=55320-55321
rtsp/1.0 200 ok
cseq: 4
date: wed, jul 03 2024 14:42:11 gmt
transport: rtp/avp;unicast;destination=192.168.2.180;source=192.168.3.225;client_port=55320-55321;server_port=6970-6971
session: 4581e0ae;timeout=65
play rtsp://192.168.3.225/wbc/ rtsp/1.0
cseq: 5
user-agent: libvlc/3.0.19 (live555 streaming media v2016.11.28)
session: 4581e0ae
range: npt=0.000-
rtsp/1.0 200 ok
cseq: 5
date: wed, jul 03 2024 14:42:11 gmt
range: npt=0.000-
session: 4581e0ae
rtp-info: url=rtsp://192.168.3.225/wbc/track1;seq=7880;rtptime=3548171463
teardown rtsp://192.168.3.225/wbc/ rtsp/1.0
cseq: 6
user-agent: libvlc/3.0.19 (live555 streaming media v2016.11.28)
session: 4581e0ae
rtsp/1.0 200 ok
cseq: 6
date: wed, jul 03 2024 14:42:19 gmt
下面将解析上个这段报文中用到的各个rtsp方法和响应。
✨5.1、option 方法
向服务器获取可用的方法:
客户端发送 options 方法,并使用 cseq
指明请求序列号,使用 user-agent
指明自己的代理;
服务端会响应请求,使用 cseq
指明响应的是哪个请求,使用date
指明日期,public
指明提供的方法。
✨5.2、describe 方法
向服务器获取rtsp://192.168.3.225:554/wbc
的媒体对象的描述,其中accept
字段指定了描述格式:
客户端发送 describe 方法,并使用 cseq
指明请求序列号,使用 user-agent
指明自己的代理,accept
字段指定了描述格式为sdp;
服务端会响应这个请求,使用 cseq
指明响应的是哪个请求,使用date
指明日期,content-type
指明内容类型是sdp,content-length
指明内容长度。
注意:
1、有些需要用户名、密码的,服务器会在处理 describe 方法进行鉴权。如果未携带authorization鉴权信息,或者认证失败,服务器会返回错误号为401的响应,客户端接收到401响应时,需要根据已知的用户鉴权信息,生成authorization,再次发送describe,如果认证成功,服务器返回携带有sdp的响应信息。
2、服务器返回的sdp信息,会在之后的文章进行解析。
✨5.3、setup 方法
客户端向服务器请求建立会话并准备传输。请求信息主要包括传输协议和客户端的端口号;
客户端发送 setup 方法,并使用 cseq
指明请求序列号,使用 user-agent
指明自己的代理,transport
字段指定了可以接受的传输协议rtp/avp、端口(这里指定了rtp端口为55320,rtcp端口为55321);
服务端会响应这个请求,使用 cseq
指明响应的是哪个请求,使用date
指明日期,transport
指明传输协议rtp/avp、目标地址、源地址、客户端端口(rtp为55320,rtcp为55321)、服务端端口(rtp为6970,rtcp为6971),session
指明会话id。
注意:
这个例子的rtp是通过udp协议传输的,有些时候,rtp会通过tcp进行传输,那么transport
字段会有所差异。可能如下:
客户端请求:transport: rtp/avp/tcp;unicast;interleaved=0-1
服务器响应:transport: rtp/avp/tcp;unicast;interleaved=0-1;ssrc=24e4e500;mode="play"
rtp/avp/tcp
表示rtp流通过tcp传输,当此值出现时,报文没有client_port字段;
interleaved=0-1
表示streamid,标识rtp的streamid=0;rtcp的streamid=1;
当码流通过tcp传输时,与rtsp共用一个tcp链路,所以其不需要建立新的连接,为了区分rtp、rtcp及rtsp协议,需要增加包头标识,这里采用tcphead头字段,tcphead为四个字节,格式如下:
| magic number | channel number | embedded data length | data |
magic number
: 1个字节,固定为0x24
,是字符$
,标识传输的是数据不是rtsp协议;
channel number
: 1个字节,信道id,标识流的类型,就是前面说的streamid;
embedded data length
:2个字节,表示流长度
data
:表示rtp/rtcp包数据
✨5.4、play 方法
客户端主动通知服务器以setup指定的机制开始发送数据。
客户端发送 play 方法,并使用 cseq
指明请求序列号,使用 user-agent
指明自己的代理,session
字段指定会话id,range
字段指定了播放的起止时间。
服务端会响应这个请求,使用 cseq
指明响应的是哪个请求;使用date
指明日期;range
字段指定了播放的起止时间;session
字段指定会话id;rtp-info
字段描述将要发送码流的rtp信息,比如第一包rtp的seq和rtptime,客户端可以根据此字段进行解复用。
✨5.5、teardown 方法
客户端请求停止指定url流发送,释放相关资源。
客户端发送 teardown 方法,并使用 cseq
指明请求序列号,使用 user-agent
指明自己的代理,session
字段指定会话id。
服务端会响应这个请求,使用 cseq
指明响应的是哪个请求;使用date
指明日期。
🎄六、rtsp 响应错误码
rtsp的响应内容通常包含3位整数响应码以及一个原因短语,短语的目的是给出状态代码的简短文本描述,客户端不需要检查或显示原因短语。 按照响应码的首位数字区别,可以分为以下五个类别:
- 1xx: 提示- 请求已经收到,正在处理中
- 2xx: 成功- 请求已经被成功处理
- 3xx: 重定向- 必须采取进一步行动才能完成请求
- 4xx: 客户端错误 - 请求中包含错误的参数或语法导致请求无法被满足
- 5xx: 服务器错误 - 服务器无法满足客户端正确的请求
当然,rtsp的错误码和rtsp方法是强相关的,某些错误可能只会在特定方法中才会触发,详细错误码信息如下:
错误码 | 原因短语 | 响应的方法 |
---|---|---|
100 | continue | all |
200 | success | all |
201 | created | record |
250 | low on storage space | record |
300 | multiple choices | all |
301 | moved permanently | all |
302 | moved temporarily | all |
303 | see other | all |
305 | use proxy | all |
400 | bad request | all |
401 | unauthorized | all |
402 | payment required | all |
403 | forbidden | all |
404 | not found | all |
405 | method not allowed | all |
406 | not acceptable | all |
407 | proxy authentication required | all |
408 | request timeout | all |
410 | gone | all |
411 | length required | all |
412 | precondition failed describe | setup |
413 | request entity too larg | all |
414 | request-uri too long | all |
415 | unsupported media type | all |
451 | invalid parameter | setup |
452 | illegal conference identifier | setup |
453 | not enough bandwidth | setup |
454 | session not found | all |
455 | method not valid in this state | all |
456 | header field not valid | all |
457 | invalid range | play |
458 | parameter is read-only | set_parameter |
459 | aggregate operation not allowed | all |
460 | only aggregate operation allowed | all |
461 | unsupported transport | all |
462 | destination unreachable | all |
500 | internal server error | all |
501 | not implemented | all |
502 | bad gateway | all |
503 | service unavailable | all |
504 | gateway timeout | all |
505 | rtsp version not supported | all |
551 | option not support | all |
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
发表评论