流媒体学习1
一、RTSP/RTP/RTCP的区别
RTP/RTSP/RTCP的区别 用一句简单的话总结: RTSP发起/终结流媒体、RTP传输流媒体数据、RTCP对RTP进行控制,同步。
RTP:实时传输协议(Real-time Transport Protocol)
RTP/RTCP是实际传输数据的协议
RTP传输音频/视频数据。如果是PLAY,Server发送到Client端;如果是RECORD,可以由Client发送到Server
整个RTP协议由两个密切相关的部分组成:RTP数据协议和RTP控制协议(即RTCP)
RTSP:实时流协议(Real Time Streaming Protocol,RTSP)
RTSP的请求主要有DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN,OPTIONS等,顾名思义可以发起对话和控制作用
RTSP的对话过程中SETUP可以确定RTP/RTCP使用的端口,PLAY/PAUSE/TEARDOWN可以开始或者停止RTP的发送,等等
RTCP:
RTP/RTCP是实际传输数据的协议
RTCP包括Sender Report、Receiver Report和Source Description,用来进行音频/视频的同步以及其他用途,是一种控制协议
1. RTP数据协议
RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部前12个字节的含义是固定的,而负载则可以是音频或者视频数据。RTP数据报的头部格式如图1所示:
图 1
其意义如下:
- CSRC记数(CC):表示CSRC标识的数目。CSRC标识紧跟在RTP固定头部之后,用来表示RTP数据报的来源,RTP协议允许在同一个会话中存在多个数据源,它们可以通过RTP混合器合并为一个数据源。例如,可以产生一个 CSRC列表来表示一个电话会议,该会议通过一个RTP混合器将所有讲话者的语音数据组合为一个RTP数据源。
- 负载类型(PT):标明RTP负载的格式,包括所采用的编码算法、采样频率、承载通道等。例如,类型2表明该RTP数据包中承载的是用ITU G.721算法编码的语音数据,采样频率为8000Hz,并且采用单声道。
- 序列号:用来为接收方提供探测数据丢失的方法,但如何处理丢失的数据则是应用程序自己的事情,RTP协议本身并不负责数据的重传。
- 时间戳:记录了负载中第一个字节的采样时间,接收方能够根据时间戳能确定数据的到达是否受到了延迟抖动的影响,但具体如何来补偿延迟抖动则是应用程序自己的事情。
从RTP数据报的格式不难看出,它包含了传输媒体的类型、格式、序列号、时间戳以及是否有附加数据等信息,这些都为实时的流媒体传输提供了相应的基础。RTP协议的目的是提供实时数据(如交互式的音频和视频)的端到端传输服务,因此在RTP中没有连接的概念,它可以建立在底层的面向连接或面向非连接的传输协议之上;RTP也不依赖于特别的网络地址格式,而仅仅只需要底层传输协议支持组帧(Framing)和分段(Segmentation)就足够了;另外RTP本身还不提供任何可靠性机制,这些都要由传输协议或者应用程序自己来保证。在典型的应用场合下,RTP一般是在传输协议之上作为应用程序的一部分加以实现的,如图2所示:
图2
2、RTCP控制协议
RTCP控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占用两个端口,分别供RTP和RTCP使用。RTP本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完成。通常RTCP会采用与RTP相同的分发机制,向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参与者的相关资料,以及网络状况、分组丢失概率等反馈信息,从而能够对服务质量进行控制或者对网络状况进行诊断。
RTCP协议的功能是通过不同的RTCP数据报来实现的,主要有如下几种类型:
- SR:发送端报告,所谓发送端是指发出RTP数据报的应用程序或者终端,发送端同时也可以是接收端。
- RR:接收端报告,所谓接收端是指仅接收但不发送RTP数据报的应用程序或者终端。
- SDES:源描述,主要功能是作为会话成员有关标识信息的载体,如用户名、邮件地址、电话号码等,此外还具有向会话成员传达会话控制信息的功能。
- BYE:通知离开,主要功能是指示某一个或者几个源不再有效,即通知会话中的其他成员自己将退出会话。
- APP:由应用程序自己定义,解决了RTCP的扩展性问题,并且为协议的实现者提供了很大的灵活性。
RTCP数据报携带有服务质量监控的必要信息,能够对服务质量进行动态的调整,并能够对网络拥塞进行有效的控制。由于RTCP数据报采用的是多播方式,因此会话中的所有成员都可以通过RTCP数据报返回的控制信息,来了解其他参与者的当前情况。
在一个典型的应用场合下,发送媒体流的应用程序将周期性地产生发送端报告SR,该RTCP数据报含有不同媒体流间的同步信息,以及已经发送的数据报和字节的计数,接收端根据这些信息可以估计出实际的数据传输速率。另一方面,接收端会向所有已知的发送端发送接收端报告RR,该RTCP数据报含有已接收数据报的最大序列号、丢失的数据报数目、延时抖动和时间戳等重要信息,发送端应用根据这些信息可以估计出往返时延,并且可以根据数据报丢失概率和时延抖动情况动态调整发送速率,以改善网络拥塞状况,或者根据网络状况平滑地调整应用程序的服务质量。
3.RTSP实时流协议
作为一个应用层协议,RTSP提供了一个可供扩展的框架,它的意义在于使得实时流媒体数据的受控和点播变得可能。总的说来,RTSP是一个流媒体表示协议,主要用来控制具有实时特性的数据发送,但它本身并不传输数据,而是必须依赖于下层传输协议所提供的某些服务。 RTSP可以对流媒体提供诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作(RFC2326) 。
RTSP在制定时较多地参考了HTTP/1.1协议,甚至许多描述与HTTP/1.1完全相同。RTSP之所以特意使用与HTTP/1.1类似的语法和操作,在很大程度上是为了兼容现有的Web基础结构,正因如此,HTTP/1.1的扩展机制大都可以直接引入到RTSP中。
由RTSP控制的媒体流集合可以用表示描述(Presentation Description)来定义,所谓表示是指流媒体服务器提供给客户机的一个或者多个媒体流的集合,而表示描述则包含了一个表示中各个媒体流的相关信息,如数据编码/解码算法、网络地址、媒体流的内容等。
虽然RTSP服务器同样也使用标识符来区别每一流连接会话(Session),但RTSP连接并没有被绑定到传输层连接(如TCP等),也就是说在整个 RTSP连接期间,RTSP用户可打开或者关闭多个对RTSP服务器的可靠传输连接以发出RTSP 请求。此外,RTSP连接也可以基于面向无连接的传输协议(如UDP等)。
RTSP协议目前支持以下操作:
- 检索媒体:允许用户通过HTTP或者其它方法向媒体服务器提交一个表示描述。如表示是组播的,则表示描述就包含用于该媒体流的组播地址和端口号;如果表示是单播的,为了安全在表示描述中应该只提供目的地址。
- 邀请加入:媒体服务器可以被邀请参加正在进行的会议,或者在表示中回放媒体,或者在表示中录制全部媒体或其子集,非常适合于分布式教学。
- 添加媒体:通知用户新加入的可利用媒体流,这对现场讲座来讲显得尤其有用。与HTTP/1.1类似,RTSP请求也可以交由代理、通道或者缓存来进行处理。
二、RTMP/WebRTC/HLS
1.RTMP(Real Time Messaging Protocol)
Macromedia开发的一套视频直播协议,现在属于Adobe。和HLS一样都可以应用于视频直播,基于TCP不会丢失。
实时消息传送协议是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的开放协议.
区别是RTMP基于flash无法在iOS的浏览器里播放,但是实时比HLS要好。
iOS代码里面一般常用的是使用RTMP推流,可以使用第三方库librtmp-iOS进行推流,librtmp封装了一些核心的API供使用者调用.
RTMP协议也要客户端和服务器通过"握手"来建立RTMP Connection,然后在Connection上传输控制信息。RTMP协议传输时会对数据格式化,而实际传输的时候为了更好地实现多路复用、分包和信息的公平性,发送端会把Message划分为带有Message ID的Chunk,每个Chunk可能是一个单独的Message,也可能是Message的一部分,在接受端会根据Chunk中包含的data的长度,message id和message的长度把chunk还原成完整的Message,从而实现信息的收发。
2.WebRTC
web端实现流媒体的协议。google刚推出WebRTC的时候巨头们要么冷眼旁观,要么抵触情绪很大。使用RTP协议传输。
3.HLS:HTTP Live Streaming(HLS)
是苹果公司(Apple Inc.)实现的基于HTTP的流媒体传输协议,可实现流媒体的直播和点播 ,主要应用在iOS系统为iOS设备(如iPhone、iPad)提供音视频直播和点播方案。
HLS 点播,基本上就是常见的分段HTTP点播,不同在于它的分段非常小。相对于常见的流媒体直播协议,例如RTMP协议、RTSP 协议、MMS 协议等,HLS 直播最大的不同在于直播客户端获取到的并不是一个完整的数据流。
HLS 协议在服务器端将直播数据流存储为连续的、很短时长的媒体文件(MPEG-TS格式),而客户端则不断的下载并播放这些小文件,因为服务器端总是会将最新的直播数据生成新的小文件,这样客户端只要不停的按顺序播放从服务器获取到的文件,就实现了直播。
由此可见,基本上可以认为,HLS 是以点播的技术方式来实现直播。由于数据通过 HTTP 协议传输,所以完全不用考虑防火墙或者代理的问题,而且分段文件的时长很短,客户端可以很快的选择和切换码率,以适应不同带宽条件下的播放。不过HLS的这种技术特点,决定了它的延迟一般总是会高于普通的流媒体直播协议。
iOS和 Android 都天然支持这种协议,配置简单,直接使用 video 标签即可。
三、RTSP详解
1、Rtsp基本流程
1)OPTIONS
C--->S(request)
OPTIONS一般为RTSP客户端发起的第一条请求指令,该指令的目的是得到服务端提供了哪些方法。
我们来详细说下各个字段:
OPTIONS:标识请求命令的类型;
RTSP URI:请求的服务端的URI,以rtsp://开头的地址,一般为rtsp://ip:554(rtsp默认端口号);
RTSP VER:标识RTSP 版本号,一般常见RTSP/1.0;
CSeq:数据包序列号,由于OPTIONS一般而言为RTSP请求的第一条指令,一般而言,针对OPTIONS,该值为1;
User-Agent:用户代理;
S--->C(response)
服务器端回复客户端,消息中包含当前可用的方法。
OPTIONS的回复遵循RTSP response消息的格式,第一行回复RTSP的版本,状态码,状态描述;然后是序列号,与OPTION请求中的序列号相同;之后是Public字段,用于描述服务器当前提供了哪些方法;最后是Date字段,表示日期。
回复的消息中RTSP版本为RTSP/1.0;
状态码为200, 表示正常;
状态描述字符为OK;
CSeq的值为1,与OPTIONS请求中的序列号一致;
Public表示了服务端支持的方法,此处有OPTIONS,DESCRIBE,PLAY,PAUSE,SETUP,TEARDOWN,SET_PARAMERTER,GET_PARAMETER,表示RTSP服务器支持这些方法;
Date表示日期和时间。
多数还带服务器的信息,如ZLMediaKit:
OPTION example
请求
OPTIONS rtsp://192.17.1.63:554 RTSP/1.0\r\n
CSeq: 1\r\n
User-Agent: Lavf58.42.100\r\n
\r\n
================================================
回复
RTSP/1.0 200 OK\r\n
CSeq: 1\r\n
Public: OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER\r\n
Date: Fri, Apr 10 2020 19:07:19 GMT\r\n
\r\n
2)DESCRIBE/ANNOUNCE
向服务器请求会话描述信息(SDP),客户端推流时用ANNOUNCE。
C--->S(request)
客户端向服务器请求媒体描述文件,一般通过rtsp开头的url来发起请求,格式为sdp。
描述:
首先用DESCRIBE描述请求类型;然后在URI中请求的服务器端地址;RTSP_VER表示RTSP的版本号,在加入\r\n消息头结束;
消息体包含以下字段:
Accept:指明接收数据的格式,如application/sdp表示接收sdp信息,之后加入\r\n表示此条目结束;
CSeq:RTSP序列号,一般DESCRIBE包在RTSP请求过程中的序列号为2,之后加入\r\n表示此条目结束;
UserAgent : 指明用户代理,由于是最后一个条目,加入两组\r\n表示结束。
S--->C(respone)
服务器回复客户端sdp文件,该文件告诉客户端服务器有哪些音视频流,有什么属性,如编解码器信息,帧率等。
对于DESCRIBE消息,服务端的回复有两种可能!如果需要认证,则首先返回401,并要求客户端认证,客户端再次发送包含认证信息的DESCRIBE指令,服务端收到带认证信息的DESCRIBE请求,返回sdp信息给客户端;如果不需要认证,则直接返回sdp。
服务端发送回复消息,状态码为401,状态描述为Unauhtorized(未认证);包序列号与DESCRIB请求中的序号相同;发回 WWW-Authenticate消息,告诉客户端认证所需信息;发回日期。
客户端收到该消息之后,需要再次向服务器发送DESCRIBE请求,这一次消息体要增加Authorization字段,realm和nonce填上一步服务器返回的WWW-Authenticate消息,如下图:
服务端收到带认证信息的DESCRIBE请求之后,如果信息正确,则会回复200 ok的消息,同时返回sdp信息!格式如下图:
此时返回的状态码为200,状态描述为OK,包序列号与DESCRIBE请求的序号相同,表示对该请求的回复;
Content-type表示回复内容类型,值为application/sdp;
Cotent-Base:一般用RTSP URI表示;
Content-length表示返回的sdp信息的长度 。
接下来是sdp,具体的描述见SDP章节。
DESCRIBE example
第一次DESCRIBE请求:
DESCRIBE rtsp://192.17.1.63:554 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf58.42.100
=================================================================
服务端回复的401消息:
RTSP/1.0 401 Unauthorized
CSeq: 2
WWW-Authenticate: Digest realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", stale="FALSE"
Date: Fri, Apr 10 2020 19:07:19 GMT
第二次DESCRIBE请求
DESCRIBE rtsp://192.17.1.63:554 RTSP/1.0
Accept: application/sdp
CSeq: 3
User-Agent: Lavf58.42.100
Authorization: Digest username="admin", realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", uri="rtsp://192.17.1.63:554", response="8f1987b6da1aeb3f3744e1307d850281"
验证OK消息
RTSP/1.0 200 OK
CSeq: 3
Content-Type: application/sdp
Content-Base: rtsp://192.17.1.63:554/
Content-Length: 712
v=0
o=- 1586545639954157 1586545639954157 IN IP4 192.17.1.63
s=Media Presentation
e=NONE
b=AS:5100
t=0 0
a=control:rtsp://192.17.1.63:554/
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:5000
a=recvonly
a=x-dimensions:1920,1080
a=control:rtsp://192.17.1.63:554/trackID=1
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z01AKI2NQDwBE/LgLcBAQFAAAD6AAAw1DoYACYFAABfXgu8uNDAATAoAAL68F3lwoA==,aO44gA==
m=audio 0 RTP/AVP 8
c=IN IP4 0.0.0.0
b=AS:50
a=recvonly
a=control:rtsp://192.17.1.63:554/trackID=2
a=rtpmap:8 PCMA/8000
a=Media_header:MEDIAINFO=494D4B48010300000400000111710110401F000000FA000000000000000000000000000000000000;
a=appversion:1.0
3)SETUP
SETUP请求的作用是指明媒体流该以什么方式传输;每个流PLAY之前必须执行SETUP操作;发送SETUP请求时,客户端会指定两个端口,一个端口用于接收RTP数据;另一个端口接收RTCP数据,偶数端口用来接收RTP数据,相邻的奇数端口用于接收RTCP数据!
C--->S(request)
客户端向服务器端发起建立连接请求,请求建立会话连接,准备开始接收音视频数据,请求信息描述了期望音视频数据包基于UDP还是TCP传输,指定了RTP,RTCP端口,以及是单播还是组播等信息!
SETUP表明消息类型;
URI表示请求的RTSP服务器的地址;
RTSP_VER表明RTSP的版本;
TRANSPORT表明媒体流的传输方式,具体包括传输协议如RTP/UDP;指出是单播,组播还是广播;声明两个端口,一个奇数,用于接收RTCP数据,一个偶数,用于接收RTP数据;
CSeq数据包请求序列号;
User-Agent指明用户代理;
Session标识会话ID;
Authorization标识认证信息;
该SETUP请求中,Transport字段声明了两个端口,26968和26969,同时指明了通过UDP发送RTP数据,26968端口用来接收RTP数据,26969端口用来接收RTCP数据,unicast表示传输方式为单播!ZLMedia实际字段一般为interleaved。
S--->C(response)
请求之后,如果没有异常情况,RTSP服务器的回复比较简单,回复200 OK消息,同时在Transport字段中增加sever_port,指明对等的服务端RTP和RTCP传输的端口,增加ssrc字段,增加mode字段,同时返回一个session id,用于标识本次会话连接,之后客户端发起PLAY请求的时候需要使用该字段,回复消息大概结构如下图:
抓包文件:
通过该抓包文件,我们可以看出,服务端对应SETUP请求的RTP和RTCP的传输端口分别为8284和8285;ssrc的值为4a7fb757;mode="play"表示当前rtsp连接是播放模式!
ZLMedia实际回复的信息为:
SETUP example
Request
SETUP rtsp://192.17.1.63:554/trackID=1 RTSP/1.0
Transport: RTP/AVP/UDP;unicast;client_port=26968-26969
CSeq: 4
User-Agent: Lavf58.42.100
Authorization: Digest username="admin", realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", uri="rtsp://192.17.1.63:554/trackID=1", response="e29ca030062df6022faa77fefde40b28"
Response
RTSP/1.0 200 OK
CSeq: 4
Session: 337474243;timeout=60
Transport: RTP/AVP/UDP;unicast;client_port=26968-26969;server_port=8284-8285;ssrc=4a7fb757;mode="play"
Date: Fri, Apr 10 2020 19:07:19 GMT
4)PLAY
PLAY消息是客户端发送的播放请求,发送播放请求的时候可以指定播放区间!发起播放请求后,如果连接正常,则服务端开始播放,即开始向客户端按照之前在TRASPORT中约定好的方式发送音视频数据包!播放流程便这样开始了!
C--->S(request)
客户端向服务端请求播放媒体。
RTSP URI表明请求的RTSP 地址;
RTSP version表明版本号;
CSeq 表示请求的序列号;
User-Agent表示用户代理;
Session 表示会话id,值为SETUP请求之后,服务端返回的session id的值;
Authorizatiuon表示认证信息;
Range是PLAY消息特有的,代表请求播放的时间段,使用ntp时间来表示。
抓包文件:
通过抓包文件,我们可以看到,该请求是第6条交互指令,会话id是之前setup请求的回复消息返回的session id,Range的值为"npt=0.0000-",表示从开始播放,默认一直播放!
S--->C(response)
服务器回复客户端200 OK! 之后开始通过SETUP中指定的端口开始发送数据!
Rtsp Version表示RTSP的版本;
状态码表示当前消息的状态,没有异常的情况下一般为200;
状态描述是针对状态码的描述,如200对应的描述为OK;
CSeq表示RTSP包的序号;
Session表示会话ID,SETUP返回时确定的ID;
RTP-Info表示RT;
Date表示日期;
抓包文件:
RTP-info:
第一个url表示视频播放的地址,第一个seq表示第一个rtp视频数据包开始的序列号,第一个rtptime表示视频开始播放的时间戳,后面的一组表示音频播放相关的信息,同样也包括url,seq,rtptime!实际服务器并不一定回这么多。
PLAY example
RTSP PLAY (requst)
PLAY rtsp://192.17.1.63:554/ RTSP/1.0\r\n
Range: npt=0.000-\r\n
CSeq: 6\r\n
User-Agent: Lavf58.42.100\r\n
Session: 337474243\r\n
Authorization: Digest username="admin", realm="IP Camera(23306)", nonce="a946c352dd3ad04cf9830d5e72ffb11e", uri="rtsp://192.17.1.63:554/", response="9ea6c2659d3bce8d129ca3549ecc7fbf"\r\n\r\n
RTSP PLAY (response)
RTSP/1.0 200 OK\r\n
CSeq: 6\r\n
Session: 337474243\r\n
RTP-Info: url=rtsp://192.17.1.63:554/trackID=1;seq=3658;rtptime=1710363406,url=rtsp://192.17.1.63:554/trackID=2;seq=6598;rtptime=4065225152\r\n
Date: Fri, Apr 10 2020 19:07:20 GMT\r\n\r\n
5)TEARDOWN
TEARDOWN是拆卸的意思,对于RTSP而言,就是结束流传输,同时释放与之相关的资源,TEARDWON之后,整个RTSP连接也就结束了。
C---->S(request)
结束播放的时候,客户端向服务器端发起结束请求
如图中,TEARDOWN消息中,指定了URI,不用多说了;RTSP版本号也是我们的老朋友了;CSeq表示序列号;Authorization表示认证信息;User-Agent是用户代理;Session表示会话ID(SETUP消息请求之后RTSP sever返回的会话id)。
该TREADOWN消息中,消息序列号为10,用户代理为LibVLC/3.0.11,这是我们使用VLC播放器rtsp流的一个代理,消息序列号为10, Session为之前SETUP请求后服务端返回的session字段的值,用于表示此次会话连接!
S--->C(response)
服务端收到消息后,向客户端发送200 OK,之后断开连接
回复消息中包含RTSP 版本号,状态码以及针对状态码的描述;同时返回消息的序列号(对应请求序列号)以及session id;另外还返回日期信息!服务端正常返回该消息,则此次RTSP连接消息结束!
从抓包文件中可以看出,服务端回复200 Ok的消息,表示正常回复;同时也返回CSeq和Session,CSeq和Session的值与TEARDOWN请求中的值是一致的;另外返回了结束的日期和时间!
TEARDOWN example
TEARDOWN请求
TEARDOWN rtsp://192.17.1.73:554/Streaming/Channels/101/?transportmode=unicast&profile=Profile_1 RTSP/1.0\r\n
CSeq: 10\r\n
Authorization: Digest username="admin", realm="bcad28138995", nonce="a1a5b9d3865180dccbaffb1cb2eb2a27", uri="rtsp://192.17.1.73:554/Streaming/Channels/101/", response="c5c005ef16638dfa326dcfc0c3f54aab"\r\n
User-Agent: LibVLC/3.0.11 (LIVE555 Streaming Media v2016.11.28)\r\n
Session: 1659421772\r\n\r\n
TEARDOWN的回复
RTSP/1.0 200 OK\r\n
CSeq: 10\r\n
Session: 1659421772\r\n
Date: Thu, Aug 27 2020 18:31:13 GMT\r\n\r\n
6 ) GET_PARAMETER
GetParameret用作向服务器获取参数,一般用于获取时间范围。当发送的请求中没有相关请求参数时,则用作保持RTSP连接!
C---->S(request)
RTSP URI表示请求的rtsp地址,RTSP version表示版本号;
CSeq表示消息序列号;
Authorization表示认证信息;
User-Agent表示用户代理;
Session表示会话ID,SETUP请求时server发回的SESSION id。
从抓包文件中看并没有任何参数的信息,所以我们认为这是一个空的 RTSP请求,其作用是保持RTSP连接,类似于ping的作用,类似于RTMP协议中的ping request消息。如果有实际的参数请求,则在增加请求的参数对应的字段就可以了!
S--->C(response)
请求发出去以后,接下来我们来看一下对于该消息的回复,格式如下:
RTSP Version表示RTSP的版本号;
状态码表示服务器返回的状态,正常为200;
状态描述为对状态码的描述,如对200状态码的描述为OK;
Date为消息发送的日期。
由于GET_PARAMETER的请求为“空”,所以回复的消息中也没有参数相关的字段。如果GET_PARAMTER请求中有请求不同类型的参数,则回复消息的时候需要将对应的该参数的相关信息返回
GET Parameter示例
GET_PARAMETER请求
GET_PARAMETER rtsp://192.17.1.73:554/Streaming/Channels/101/?transportmode=unicast&profile=Profile_1 RTSP/1.0\r\n
CSeq: 7\r\n
Authorization: Digest username="admin", realm="bcad28138995", nonce="a1a5b9d3865180dccbaffb1cb2eb2a27", uri="rtsp://192.17.1.73:554/Streaming/Channels/101/", response="4764a1f2772821f5528ebbb2ad18c3f9"\r\n
User-Agent: LibVLC/3.0.11 (LIVE555 Streaming Media v2016.11.28)\r\n
Session: 1659421772\r\n\r\n
GET_PARAMETER回复
RTSP/1.0 200 OK\r\n
CSeq: 7\r\n
Date: Thu, Aug 27 2020 18:29:00 GMT\r\n
7) RTSP_SET_PARAMETER
SET_PARAMETER方法用于给URI指定的流地址设置参数。当客户端想要确定为什么某一个特定的请求失败时,请求应该只包含一个参数。如果请求中包含多个参数值,则服务器只有在所有的参数被成功设置的情况下,才会生效。服务器允许某个参数被重复设置成相同的值,但不允许改变参数的值!
C---->S(request)
URI表示rtsp的地址;
Rtsp Version表示版本号;
CSeq表示序列号;
Content-length表示内容长度
Content-type表示内容类型;
之后跟着1个或多个参数及对应的值!
S--->C(response)
RtspVersion表示Rtsp的版本号;
状态码和状态描述给出了对于设置某个参数的请求的回复状态,如状态码451,表示无效参数(Invalid Parameter)!
CSeq的值与请求消息的序列号一一对应;
Content-length、Content-type,以及各参数均与SET_PARAMETER的请求是一致的!
2、Rtsp消息格式
RTSP消息分为两大类,一类是请求消息(request),一类是回应消息(ressponse)。
1)请求消息(request)
请求消息的格式如下:
说明:
请求消息由方法+URI+RTSP版本开头,之后跟一条或多条消息!
URI:表示接收方的地址,如rtsp://192.168.1.201:554
CR:表示回车
LF:表示换行
RTSP使用消息类型和消息体来表示不同类型的消息。
最后一条消息要使用两个CR LF。
通过wireshark的抓包来实际看一个RTSP的请求消息:
如图中所示,该RTSP请求消息的方法为OPTIONS,请求的目标地址为rtsp://192.17.1.63:554,RTSP的版本为1.0;
接下来包含两种类型的消息,第一种为CSeq表示序列号,本次请求的序列号为1(服务器端回复此请求的数据包的序列号也是1);
第二种为User-Agent,表示用户代理,值为 “Lavf58.42.100”;
由于User-Agent为最后一条消息,其后要跟两组回车和换行!
2)回应消息(response)
回应消息由RTSP版本+状态码+解释开头,之后跟一条或多条消息!
说明:
状态码:表示状态,同http的返回状态,如200,表示OK
解释:针对状态码的文本解释
同样:最后一条消息也是需要 跟两个回车和换行!
来看抓包文件:
回复消息以Response标识,该消息中RTSP的版本号为1.0;
服务器回复的状态码为401;
针对状态码401的解释为Unauthorized(未授权);
包含两种类型的消息:
一是WWW-Authenticate:告诉请求端授权认证需要的信息;
二是Date:表示当前日期和时间!
3、sdp格式详解
1)介绍
sdp,英文全称Session Description Protocol,会话描述协议,对应RFC2327。我们在此介绍,是因为RTSP协议中使用sdp进行媒体信息的描述,不过,sdp的应用不止于此,语音通话SIP协议,监控安防GB28181国标, 当下比较火热的webRtc都用到了sdp,可谓应用广泛!
sdp的目的就是在媒体会话中,传递媒体流信息,允许会话描述的接收者去参与会话,定义了会话描述的统一格式!
sdp信息由多行"<type>=<value>"组成,其中<type>是一个字符串,<value>是一个字符串,type表示类型,value的格式视type而定,整个协议区分大小写,"="两侧不允许有空格!
sdp会话描述包含一个会话级描述(session_level_description)和多个媒体级描述(media_level description)组成!会话级描述的作用域是整个会话,其位置从"v="行开始到第一个媒体描述为止;媒体级描述是对单个的媒体流进行描述,如传输过程中的视频流信息,从m=开始到下一个媒体描述为止,如下图所示!
会话级描述主要包含以下字段
媒体级描述主要包含以下字段
2)各字段描述
version(必选)
格式: v=<version>
描述: 表示sdp的版本号,不包含次版本号
一个实际的抓包文件
origin(必选)
格式:o=<username> <sessionid> <version> <network type> <address type> <address>
描述:o=选项对会话的发起者进行了描述;
<username>:是用户的登录名, 如果主机不支持<username>,则用"-"代替,<username> 不能包含空格;
<session id>:是一个数字串,在整个会话中,必须是唯一的,建议使用个NTP 时间戳;
<version>: 该会话公告的版本,供公告代理服务器检测同一会话的如果多个公告哪个是最新公告,基本要求是会话数据修改后该版本值递增,建议使用NTP时间戳
<networktype>: 网络类型,一般为"IN",表示internet
<addresstype>: 地址类型,一般为IP4
<adress>:地址
来看一个实际的抓包文件:
Session Name(必选)
格式:s=
会话名称,在整个会话中有且只有1个"s="
来看一个实际的抓包文件:
Connection Data(可选)
格式: c=<networktype> <address type> <connection address>描述:表示媒体连接信息;一个会话级描述中必须有"c="或者在每个媒体级描述中有一个"c="选项,也可能在会话级描述和媒体级描述中都有"c="选项;
network type表示网络类型,一般为IN,表示internet;
address type,地址类型,一般为IP4;
connection address,地址,可能为域名或ip地址两种形式
来看一个实际的抓包文件:
Bandwidth(可选)
格式: b=<modifier>:<bandwidth-value>
描述:该选项描述了建议的带宽,单位 kbs/s,可选,modifier包括两种类型,CT和AS,CT表示总带宽,AS表示单个媒体带宽的最大值;bandwidth-value表示具体的带宽。
来看一个实际的抓包文件:
从抓包文件看出,表示单个媒体带宽的最大值为5100 kb/s。
Times(必选)
格式:t=<start time> <stop time>
描述:t字段描述了会话的开始时间和结束时间,<start time> <stop time>为NTP时间,单位是秒;如果<stop time>为0表示过了<start time>之后,会话一直持续;当<start time> 和<stop time>都为0的时候,表示持久会话;建议两个值不设为0,如果设为0,不知道开始时间和结束时间,增大了调度的难度
来看一个实际的抓包文件:
start time和stop time均为0,表示一个持久的会话。
email(可选)
格式:e=<email address>
描述:用来描述邮件地址
来看一个实际的抓包文件:
phone number(可选)
格式:p=<phone number>
描述:比较简单,用来描述电话号码
URI(可选)
格式:u=<uri>
描述:类似于url的一个值,这里不过多介绍了
a=(*) (可选)
格式 :a=<*>
描述:表示一个会话级别或媒体级别下的0个或多个属性
来看一个抓包文件
会话级别中有一个属性a,a=control:rtsp://192.17.1.63:554,表示新增的属性的类型为control,值为rtsp://192.17.1.63:554
media information(必选)
格式:m=<media> <port> <transport type> <fmt list>
描述:
<media>表示媒体类型
有"audio","video","application","data"(不向用户显示的数据),"control"(描述额外的控制通道);
<port>表示媒体流发往传输层的端口,对于RTP,偶数端口用来传输数据,奇数端口用来传输RTCP;
<transport>表示传输协议,与"c="一行相关联,一般用RTP/AVP表示,即 Realtime Transport Protocol using the Audio/Video profile over udp,即我们常说的RTP over udp;
<fmt list>表示媒体格式,分为静态绑定和动态绑定
静态绑定:媒体编码方式与RTP负载类型有确定的一一对应关系,如: m=audio 0 RTP/AVP 8
动态绑定:媒体编码方式没有完全确定,需要使用rtpmap进行进一步的说明: 如:
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
rtpmap(可选)
格式:a=rtpmap:<payload typee> <encoding name>/<clock rate>
描述:
payload type表示动态负载类型,如 98表示h264
encoding name表示编码名称,如H.264
clock rate表示时钟频率,如90000
fmtp
定义指定格式的附加参数
a=fmtp:<payload type> <format specific parameters>
<payload type>:负载类型
<format specific parameters>:具体参数.
3)实际举例
v=0
o=- 1586545639954157 1586545639954157 IN IP4 192.17.1.63
s=Media Presentation
e=NONE
b=AS:5100
t=0 0
a=control:rtsp://192.17.1.63:554/
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:5000
a=recvonly
a=x-dimensions:1920,1080
a=control:rtsp://192.17.1.63:554/trackID=1
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z01AKI2NQDwBE/LgLcBAQFAAAD6AAAw1DoYACYFAABfXgu8uNDAATAoAAL68F3lwoA==,aO44gA==
m=audio 0 RTP/AVP 8
c=IN IP4 0.0.0.0
b=AS:50
a=recvonlya=control:rtsp://192.17.1.63:554/trackID=2
a=rtpmap:8 PCMA/8000
a=Media_header:MEDIAINFO=494D4B48010300000400000111710110401F000000FA000000000000000000000000000000000000;
a=appversion:1.0
v=0
o=34020000001320000010 0 0 IN IP4 192.17.1.202
s=Play
c=IN IP4 192.17.1.202
t=0 0
m=video 5500 RTP/AVP 96 97 98
a=rtpmap:96 PS/90000
a=rtpmap:97 MPEG4/90000
a=rtpmap:98 H264/90000
a=recvonly
4.RTP包格式
rtsp传输本质上涉及三种协议,RTSP、RTP以及RTCP。RTSP主要负责连接建立,销毁及一些其他的控制。而实际涉及媒体数据传输使用的是RTP协议。
1)RTP概览
RTP是一种应用层协议,传输层协议可以是TCP或者UDP(UDP多一些)!RTP数据包由两部分组成,一部分是RTP Heaeder,一部分是RTP body,RTP Header占用最少12个字节,最多72个字节;另一部分是RTP Payload,用来封装实际的数据负载,如封装h264编码的视频数据!下面我们来仔细看下RTP Header和RTP Body的组织形式!
RTP包格式示意图
2) RTP Header格式 ![https://img2020.cnblogs.com/blog/2293816/202112/2293816-20211228112407029-1154329894.png](https://img2023.cnblogs.com/blog/2525040/202312/2525040-20231208134201923-1252416683.png)
V: 2bits,表示版本号,
P: 1bit,表示是否支持填充,置为1的时候,表示在packet的末尾进行填充,方便一些针对固定长度算法的封装
X: 1bit, 表示是否支持Rtp头扩展,置为1的时候,RtpHeader之后会跟1个header extension
CC(CSRC count): 4bits,表示头部之后contributing sources identifiers的个数
M: 1bit; 该值为1时,表示该数据包是一帧数据的最后一个数据包。
PT: 7bits,表示传输的多媒体类型(标识了RTP载荷的类型)。常用的的96表示h264,97 表示ACC。
sequence number:16bits(2字节),表示RTP包序号 。
timestamp:32bits(4字节),表示时间戳, 必须使用90 kHz 时钟频率
SSRC:32bits(4字节),用于标识同步信源,参加同一视频会议的两个同步信源不能有相同的SSRC.
CSRC:特约信源标识符,每个CSRC占用4个字节,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源
4) Rtp 数据包拆解
根据PT类型的不同,Payload有不同的组织方式。
红色框中的部分为RTP Header;绿色框中的部分为RTP Payload! 我们来详细来看下:
该数据包中RtpHeader的16进制表示为:
将其用二进制表示如下:
Version
值为10,版本号为2,我们与wireshark的抓包解析对比一下:
Padding
值为0,表示不填充。wireshark的抓包如下:
X(扩展)
值为0。表示不支持扩展RTP头!wireshark的抓包如下
CC(CSRC计数)
CSRC计数器,值为00,表示没有RTP头信息中没有CSRC!wireshark的解析:
M(marker)
值为0,表示该数据包非一帧数据的最后一帧!wireshark的解析:
当该值为1时,表示该数据包是一帧数据的最后一个数据包!
PT(payload type)
PT值为96,RTP载荷的类型为h264.
sequence number
值为0x 12 ed,十进制为4845,表示rtp包的序列号为4845。
wireshark的解析如下:
Timestamp
值为0x4b cf fa 46, 表示时间戳,wireshark解析为:
SSRC
同步信源标识符,此数据包的值为0x6b 2f dd 87,wireshark的解析为:
CSRC
由于RTP Header中CC的值为0,所以表示CSRC在本数据包中的个数为0,在此处没有,RTP HEADER中允许有0-15个CSRC。
RTP Payload
蓝色阴影部分为Rtp Payload,我们可以看到第一个字节为0x67,比较容易想到该数据为视频帧的SPS,也说明了RTP Payload中的数据就是传输的媒体数据。
5. rtp over tcp/rtsp解析
摘自:https://www.cnblogs.com/iFrank/p/15434438.html
1)rtp over tcp的RTP/RTCP包格式的前四个字节说明
RTP/RTCP Socket和RTSP Socket共享TCP Socket,所以必须要有一个标识来区别三个数据。
RTP和RTCP数据会以 "$"符号 + 一个字节的通道编号 + 2个字节的数据长度,共四个字节的前缀开始,RTSP数据没有四个字节的前缀;RTP和RTCP数据的区别在于第二个字节的通道编号。
所以第一个字节’$'用于与RTSP区分,第二个字节用于区分RTP和RTCP(RTP和RTCP的channel是在RTSP的SETUP过程中,客户端发送给服务端的------一般情况下 RTP通道编号是偶数,RTCP通道编号是奇数)。RTP/RTCP的前缀四个字节如下所示:(在rtp over tcp发送协议下)
2)rtp over tcp的包格式
根据前面的说明,现在RTP的打包方式要在之前的每个RTP包前面加上四个字节。
3)RTP包格式--:RTP头+RTP载荷
6. RTCP协议
RTSP用于建立连接及发送请求等,RTP用于实际的媒体数据传输。整个RTSP的流程中,还有一种不可或缺的协议, 那就是RTCP。RTCP的全称是RTP Control Protocol,从英文名称可以看出,其是针对RTP的控制协议!RTCP主要用于提供数据分发质量反馈信息。
1)数据包格式
RTCP的数据包格式,如下图:
对照示意图,可以看到如下字段,下面做详细解释:
V(2bit)
Version,表示RTCP版本号,当前规范定义的版本号为2,需要注意的是RTP数据包中的版本号与RTCP数据包的中的版本号是一致的。
P(1bit)
填充位,表示是否需要填充,0表示不填充,其不属于控制信息。在某些情况下(如加密)需要进行填充,在填充的情况下,Padding的最后一个字节用于计算应该忽略多少个字节!
RC(5bit)
接收方报告计数,表示在该数据包中的接收方报告块的数量,该字段0值是有效的,但没有实际意义!
PT(8bit)
RTCP的数据包的分组类型,RTCP包含的分组类型如下:
BYE分组为结束分组,表示关闭一个数据流;
APP分组为特定应用分组,使应用程序能够自定义新的分组类型;
SDES分组为源描述分组,其作用是给出参加会话者的描述;
SR分组为发送端报告分组:发送端每发送一个RTP数据包,就要发送个一个发送端报告分组SR;
RR为接收端分组报告,接收端分组报告 ,每收到一个RTP流,就产生一个RR分组。
length(16bit)
RTCP数据包的大小。该字段中大小的表示比较有意思,使用4个字节为1组,长度共有几个4个字节的组,然后用该长度减去1,即为RTCP包中的长度!举个例子:假设RTCP数据包的长度为32个字节,32/4=8,总共有8组4个字节,8-1=7,此时RTCP数据包中length的值为7。
SSRC(32bit)
同步源标识
RR
Recevier Report,接受端报告。
SS
Source Description,源描述。
通过抓包文件我们可以看到,RTCP包是应用层协议,截图中的RTCP包是基于UDP协议的!抓包中红色部分为RTCP数据包的头部分,蓝色部分为Receive Report的具体内容,绿色部分为源描述的具体内容!
2)SS(Send Report)
通过结构图,可以看到Sender Report有以下字段:
NTP时标
NTP时间戳
RTP时标
RTP时间戳
发送者包计数
从开始传输到当前SR包生成的时间段内,发送端发送的RTP数据包的总个数!如果发送者更改其SSRC,则该计数要被重置
发送者数据8位组计数
从开始传输到当前SR包生成的时间段内,发送端发送的总的数据的大小的八位组计数,不包含头信息以及填充信息!如果发送者更改可SSRC,需要重置该值!该字段可以用来估计平均码率!
抓包
SSRC(32bit)
发送端的信源标识符,与发送端的SSRC一致。
丢包数8(8bit)
前一个SR或RR包发送后,到当前的SR包或RR包的间隔内,来自源(用源SSRC标识)发送的数据包的丢失个数
累积丢包数(24bit)
自开始接受源(用源SSRC标识)发送的数据开始,累积丢失的数据包的个数
扩展包序号(32bit)
低16位为当前接收到的来自源的(用源SSRC标识)数据包的最大序列号;高16位表示RT包序列号的循环计数!我们都知道RTP数据包中,表示序列号的长度为2个字节,即最大的RTP序列号为65536,如果序列号超了65536,假设为655537,这个时候RTCP在扩展包序号中对其说明,如果没有超过65536,则高16位为0,如果超过65536,则为1,如果再来一圈,则为3。做个不恰当的比喻,我们跑步一圈为65536,高16位表示我们当前正在跑第几圈,从0开始计数!
间隔抖动(32bit)
RTP数据包间隔时间的统计估计,以时间戳为单位,用无符号整数表示!
LSR(32bit)
last SR timestamp,表示上一个SR数据包的NTP时间戳!由于NTP时间戳为64bit,LSR为32bit,LSR取上一个SR的NTP时间戳的中间32位:如上一个SR数据包的NTP时间戳为“0x 00 01 7d 6e 3b 64 5a 1c ”,则LSR为0x 7d 6e 3b 64!
DLSR(32bit)
发送当前RR包的时间与上一个SR之间的时间间隔,以1/65536为单位,如,本次RR包与上一次SR的时间间隔为264ms,则本字段的值为0.264*65536=17301.54。
抓包文件
该抓包文件中的丢包数为0,累积丢包数为57,扩展的包序号为7070,间隔抖动为26,SR和DLSR均为0。
3)RR(Receiver report)
与Sender Report相比,少了sender info。
4)SS(source description)
通过结构图,我们可以看到Source Description分组,也可以叫做SDES的组织结构是按照KLV的格式组织的,key表示具体的类型,length为长度,value为具体的值, key占用1个字节, length占用1个字节!RTCP中可选的KEY如结构图中所列,有如下几种:
CNAME(值为1)
规范终端标识,像SSRC标识,CNAME标识在RTP连接的所有参加者中应是唯一的;
NAME(值为2)
用户名称,用于描述源的用户名;
E-mail(值为3)
电子邮件地址,用于描述源的邮件地址,格式如 John.Deo@megacorp.com;
PHONE(值为4)
用于描述源的电话号码;
LOC(值为5)
用于描述源的地理位置;
TOOL(值为6)
用于描述应用或工具的名称,表示产生流的应用的名称与版本,如"videotool 1.2";
NOTE(值为7)
用于描述源当前状态的过渡信息;
PRIV(值为8)
用于描述针对源的扩展项;
抓包
通过抓包,我们可以看到该描述中包含一个CNAME的字段,长度为7,值为“DELL-PC”。
RTCP中通过Sender Report和Receive Report在RTP数据传输中提供当前连接中RTP包发送的情况,RTP包接收的情况,RTP包丢失的情况,通过这些信息反馈,我们可以实现对网络传输做一些调整和控制!这就是RTCP的主要功能!
结语
到这里,关于RTSP传输的三大协议就都熟悉了!RTSP发起或停止连接,以及在连接的过程中控制流媒体数据的行为,如play,scale等,RTP负责数据传输,RTCP负责信息反馈!如此,基于RTSP的流媒体传输就完整建立起来了!那么关于rtsp的专题也可以告一段落了!期待下一个专题吧!感谢朋友们的支持!