三者关系

RTSP是一个实时的传输协议,是一个应用层的协议,包RTSP协议,RTP协议,RTCP协议。

  • RTSP协议主要是负责建立服务器和客户端之间的请求和相应,建立通信链路。
  • RTP协议是负责在服务器和客户端进行传输数据,
  • RTCP协议四负责提供RTP传输质量的反馈,确保RTP传输的质量。

三者都处于应用层RTSP不会发送媒体数据,知识完成服务器和客户端之间的信令交互,RTP协议负责媒体数据传输,RTCP负责RTP数据包的监视和反馈,RTP和RTCP并没有规定传输层的类型,可以选择UDP或者是TCP,RTSP则要求最好是基于TCP。总体来说,RTSP是建立在RTP和RTCP之上的。

RTP

首先要明确一点,RTP是架构在UDP之上的。在TCP协议中由于严格的重传机制,以及可靠协议特性,使其难以成为一个实时音视频领域协议。而UDP是一个不可靠协议,它并不严格要求包到达的顺序以及可靠到达,因此实时性最好。但是如何处理网络抖动以及丢包就成了难题,本部分重点在于RTP是如何解决这些问题的。

RTP协议头

UDP 数据报的结构

一个UDP数据报非常简单,它由两部分组成:

  • UDP头 (UDP Header):8个字节,包含源端口、目标端口、长度和校验和。
  • UDP数据区 (UDP Payload/Data):用来存放需要传输的数据。
1
[ UDP头 | UDP数据区 (用来放东西的地方) ]

基于UDP的RTP

  1. RTP协议首先构建好自己的数据包:
  • RTP头 (RTP Header):12字节或更多,包含序列号、时间戳等。
  • RTP载荷 (RTP Payload):实际的音视频数据,比如一小段H.264编码的视频帧。
1
[ RTP头 | RTP载荷 (音视频数据) ]  <-- 这整个是一个完整的RTP包
  1. RTP把整个RTP包(RTP头 + RTP载荷)不加改变地,“塞”进了上面提到的 UDP数据区。

  2. 最终形成的数据包结构

所以,当数据包在网络中传输时,它的嵌套结构是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
+-------------------------------------------------------------------+
| IP头 (网络层) |
| +---------------------------------------------------------------+ |
| | UDP头 (传输层) | |
| | +-----------------------------------------------------------+ | |
| | | 这整个部分是 UDP 的“数据区” / “Payload” | | |
| | | +----------------------+--------------------------------+ | | |
| | | | RTP头 (应用层) | RTP载荷 (真正的音视频数据) | | | |
| | | +----------------------+--------------------------------+ | | |
| | +-----------------------------------------------------------+ | |
| +---------------------------------------------------------------+ |
+-------------------------------------------------------------------+

丢包问题

在RTP头中会对每个数据包进行编号,因此接收端很容易就可以判断哪些包丢失了,这个字段是sequence number

RTP扩展头

通过设置RTP头中的X字段为1可开启扩展头

RTP扩展头

其中profile是为了区分不同的配置,{0x10,0x0X}和{0xBE,0xDE}分别代表two-byte-header或者one-byte-header节来解析数据。length表示有几个header_extension。

在header-extension中,one-byte-header表示在he中的数据由一个字节的header和N字节的Body组成。而header中有4位的ID和4位的len。

RTP中的填充数据

通过设置RTP头的P位可开启填充数据

当RTP中包含填充数据时数据包最后一个字节记录包中填充数据字节个数(包括自己),解包的时候从后往前去掉即可。

端口数据类型区分

在一个 RTP 会话中,可能会有多个参与者发送媒体流。每个发送者都会选择一个唯一的 SSRC 值来标识自己产生的流。这使得接收端能够区分来自不同发送者的 RTP 包(即使在同一个端口输入或输出)。SSRC 字段是一个 32 位的数值,用于标识产生 RTP 包的源端系统或设备。对于任何给定的 RTP 会话,由同一个源产生的所有 RTP 包都应该具有相同的 SSRC 值。另外需要注意以下两种情况:

  • 当一个混音器接收到来自多个源的 RTP 包并将它们混合成一个单一的流时,混音器会作为新的源产生 RTP 包,并且会使用它自己的 SSRC 值。原始的源 SSRC 值可能会被记录在 RTP 扩展头中。

  • 一个转发器可能会在不同的网络之间转发 RTP 包,它通常会保持原始的 SSRC 值不变。

RTCP

RTCP与RTP一样都是属于应用层的协议,其是RTP的控制协议。包括丢包控制;发送或者接受报告,其中包括上次报告到本次报告中间丢包率,延时等信息。

报文分类

  1. SR和RR报文,分别用于发送和接收报文
  2. SDES,用于描述音视频媒体源。
  3. BYE报文用于说明哪些媒体源已经不可用,应该删除
  4. APP报文,自定义报文
  5. RTPFB,PSFB报文,未搞清楚什么作用。

需要注意这里的报文概念,与SDP,json、xml这类消息概念易混。

其中很重要的一个区别就是RTCP报文是二进制的。

RTCP协议头

重点是count字节,对于不同的报文类型,其含义是不同的。length字节表示整个的RTCP大小。

PT即payload Type

RTSP

RTSP的组成

  1. OPTIONS:
  • 用途: 客户端用 OPTIONS请求服务器支持的 RTSP 方法。

  • 请求示例: OPTIONS rtsp://example.com/media.mp4 RTSP/1.0\r\nCSeq: 1\r\nUser-Agent: MyClient\r\n\r\n

  • 响应: 服务器会回复一个包含 Public:OPTIONS 头部的响应,列出它支持的方法: DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN

  1. DESCRIBE:
  • 用途: 客户端使用 请求服务器上媒体文件的描述信息。这个描述信息通常以 SDP (Session Description Protocol) 格式提供,包含了媒体的类型(例如音频、视频)、编码格式、传输方式等。

  • 请求示例: DESCRIBE rtsp://example.com/media.mp4 RTSP/1.0\r\nCSeq: 2\r\nAccept: application/sdp\r\nUser-Agent: MyClient\r\n\r\n

  • 响应: 服务器会回复一个包含媒体描述信息的 SDP 内容。

  1. SETUP:
  • 用途: 客户端在播放媒体之前,需要使用 SETUP 命令为每个媒体流组件(例如音频和视频轨道)建立传输会话。客户端会指定它希望使用的传输协议(例如 RTP/UDP 或 RTP/TCP)以及接收数据的端口。

  • 请求示例 (RTP/UDP): SETUP rtsp://example.com/media.mp4/trackID=1 RTSP/1.0\r\nCSeq: 3\r\nTransport: RTP/AVP;unicast;client_port=12345-12346\r\nUser-Agent: MyClient\r\n\r\n

  • 请求示例 (RTP/TCP): SETUP rtsp://example.com/media.mp4/trackID=1 RTSP/1.0\r\nCSeq: 3\r\nTransport: RTP/AVP/TCP;unicast;interleaved=0-1\r\nUser-Agent: MyClient\r\n\r\n

  • 响应: 服务器会回复确认所选的传输参数,并分配一个会话。

  1. PLAY:
  • 用途: 客户端使用 命令指示服务器开始发送流媒体数据。客户端可以指定播放的时间范围。

  • 请求示例 (从头开始播放): PLAY rtsp://example.com/media.mp4 RTSP/1.0\r\nCSeq: 4\r\nSession: 1234567890\r\nRange: npt=0.000-\r\nUser-Agent: MyClient\r\n\r\n

  • 请求示例 (播放特定时间段): PLAY rtsp://example.com/media.mp4 RTSP/1.0\r\nCSeq: 4\r\nSession: 1234567890\r\nRange: npt=10.5-25.0\r\nUser-Agent: MyClient\r\n\r\n

  • 响应: 服务器会回复确认开始播放。

  1. PAUSE:
  • 用途: 客户端使用 PAUSE 命令暂停流媒体的播放。客户端可以指定暂停的时间。

  • 请求示例: PAUSE rtsp://example.com/media.mp4 RTSP/1.0\r\nCSeq: 5\r\nSession: 1234567890\r\nUser-Agent: MyClient\r\n\r\n

  • 响应: 服务器会回复确认已暂停播放。

  1. TEARDOWN:
  • 用途: 客户端使用 TEARDOWN 命令通知服务器终止流媒体会话并释放相关资源。

  • 请求示例: TEARDOWN rtsp://example.com/media.mp4 RTSP/1.0\r\nCSeq: 6\r\nSession: 1234567890\r\nUser-Agent: MyClient\r\n\r\n

  • 响应: 服务器会回复确认会话已终止。

  1. 其他不太常用但仍然重要的命令:

GET_PARAMETER: 用于查询服务器或会话的参数。

SET_PARAMETER: 用于设置服务器或会话的参数。

REDIRECT: 服务器可以发送 响应,指示客户端连接到另一个服务器。REDIRECT

RTSP的过程

一次基本的RTSP操作过程是,首先,客户端线连接到流媒体服务器,并发送i个(DESCRIBE)。流服务器通过一个SDP描述来进行反馈,反馈信息包括流数量,媒体类型等信息,客户端在分析描述符后 ,并为每个流发送SETUP命令,这个命令来告诉服务器,客户端用于接收媒体数据的端口,流媒体连接建立完成后,客户端发送i个播放命令PLAY服务器就可以在UDP上传送媒体流,RTP包到客户端,在播放过程中客户端还可进行快进,快退,等操作。

RTSP与HTTP的关系

  1. RTSP引入了几种新的方法,比如DESCRIBE、PLAY、SETUP 等,并且有不同的协议标识符,RTSP为rtsp 1.0,HTTP为http 1.1;

  2. HTTP是无状态的协议,而RTSP为每个会话保持状态;

  3. RTSP协议的客户端和服务器端都可以发送Request请求,而在HTTPF协议中,只有客户端能发送Request请求。

  4. 在RTSP协议中,载荷数据一般是通过带外方式来传送的(除了交织的情况),及通过RTP协议在不同的通道中来传送载荷数据。而HTTP协议的载荷数据都是通过带内方式传送的,比如请求的网页数据是在回应的消息体中携带的。

  5. 使用ISO10646(UTF-8) 而不是ISO 8859-1,以配合当前HTML的国际化;

  6. RTSP使用URI请求时包含绝对URI。而由于历史原因造成的向后兼容性问题,HTTP/1.1只在请求中包含绝对路径,把主机名放入单独的标题域中;

RTSP协议格式

文章

在client和server的连接中,还需要使用SDP描述符,连接中有关于SDP的协议说明。

音视频同步(部分内容来自视频云技术公众号

一般音频的采样频率有 16KHz、44.1KHz、48KHz 等,而视频反映在采样帧率上,一般帧率有 25fps、29.97fps、30fps 等。

习惯上音频的时间戳的增速就是其采样率,比如 16KHz 采样,每 10ms 采集一帧,则下一帧的时间戳,比上一帧的时间戳,从数值上多 16 x10=160,即音频时间戳增速为 16/ms。而视频的采样频率习惯上是按照 90KHz 来计算的,就是每秒 90K 个时钟 tick,之所以用 90K 是因为它正好是上面所说的视频帧率的倍数,所以就采用了 90K。所以视频帧的时间戳的增长速率就是 90/ms。

时间戳生成

RTC中的音频时间戳增量=编码帧长*采样率/1000,初始包时间为0。而封装进入RTP包的时候又会添加一个随机增量并发送。而视频帧的生成较为复杂

首先获得timestamp_us_(当前时间),接下来获得ntp_time_ms_(NTP表示) = (timestamp_us_ / 1000) + delta,delta是一个 WebRTC 内部维护的“本地时钟与 NTP 主机时间的估计差值”,这样就可以获得一个跨设备的时间戳,接下来将其转换为RTP俄式即可timestamp_rtp_ = ntp_time_ms_ * 90。乘90是因为视频流的默认时钟频率是90kHz,将默认时间转换为90kHz的时间戳,即Timestamp = (Time_in_seconds) * 90000 = (ntp_time_ms_ / 1000) * 90000 = ntp_time_ms_ * 90。最后RTP也会向时间戳中加入一个偏移量并发送。

SR实现同步(发送端)

每个RTP包中仅包含各自的时间戳信息,音频和视频是相互独立的,无法只根据这个信息来进行同步,因为无法对两个流的时间进行关联,我们需要一种映射关系,将两个独立的时间戳关联起来。
在RTCP中的SR会指出NTP与每个流的RTP包的时间戳对应关系。NTP 时间和 RTP 时间戳是同一时刻的不同表示,只是精度和单位不一样。NTP 时间是绝对时间,以毫秒为单位,而 RTP 时间戳则和媒体的采样频率有关,是一个单调递增数值。

在计算过程中,首先获得NTP时间,解包即可。然后是RTP时间,根据上一个发送的 RTP 包的时间戳 last_rtp_timestamp_ 和它的采集时刻的系统时间 last_frame_capture_time_ms_,和当前媒体流的时间戳的每 ms 增长速率 rtp_rate,以及从 last_frame_capture_time_ms_ 到当前时刻的时间流逝,就可以算出来。注意,last_rtp_timestamp_ 是媒体流的原始时间戳,不是经过随机偏移的 RTP 包时间戳,所以最后又累加了偏移量 timestamp_offset_。
可以理解成,我们需要知道从上一帧到当前帧,到底过去了多久。time_elapsed_ms = current_frame_capture_time_ms - last_frame_capture_time_ms_。用流逝的物理时间乘以“速度” rtp_rate,把它转换成 RTP 时间轴上的增量。
rtp_timestamp_increment = time_elapsed_ms * rtp_rate。而对于视频(90 kHz 时钟),rtp_rate = 90000 / 1000 = 90。对于 48 kHz 的音频,rtp_rate = 48000 / 1000 = 48。当前帧在 RTP 时间轴上的新位置,
current_unoffset_rtp_timestamp = last_rtp_timestamp_ + rtp_timestamp_increment。


本站由 Edison.Chen 创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

undefined