3. RTSP协议详解:RTSP请求方法、SDP描述、与RTP/RTCP的关系
好,咱们进入第三个章节。RTSP这个协议,说白了就是视频流的「遥控器」。你想想看,我们要看一个实时视频,总不能直接把数据流硬塞过来吧?总得有个「播放」、「暂停」、「快进」的操作。RTSP干的就是这个活。
我记得刚入行那会儿,有个项目需要对接海康的NVR。我拿着文档看了半天,发现RTSP的交互流程其实比想象中简单。但坑也不少。今天我就把这块掰开了讲清楚。
3.1 RTSP请求方法
RTSP的请求方法,我习惯把它类比成VCR的按键。常用的就那么几个:
- OPTIONS:客户端问服务器「你支持哪些操作?」。服务器会回复一个列表。
- DESCRIBE:客户端问「这个流长什么样?」。服务器返回SDP描述。
- SETUP:客户端说「我要开始接收数据了,咱们把传输通道建好」。这一步会协商端口和传输协议。
- PLAY:客户端说「开始播放」。服务器开始推送RTP流。
- PAUSE:暂停播放。注意,有些设备不支持暂停。
- TEARDOWN:断开连接,释放资源。
核心要点:RTSP本身不传输视频数据。它只负责控制。真正的视频数据走的是RTP。
我在项目中遇到过一个问题:有些低端摄像头对OPTIONS请求的回复不完整。你发OPTIONS过去,它可能只回一个空列表。这时候我建议你直接发DESCRIBE试试。嗯,这算是个小技巧。
3.2 SDP描述
SDP,全称是Session Description Protocol。它不负责传输,只负责描述。说白了就是一份「视频流说明书」。
一个典型的SDP长这样:
v=0
o=- 123456 789012 IN IP4 192.168.1.100
s=Live Stream
c=IN IP4 0.0.0.0
t=0 0
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; profile-level-id=42E01E; sprop-parameter-sets=Z0IACpZUBQFs, aMljiA==
我来拆解一下关键字段:
| 字段 | 含义 | 我的经验 |
|---|---|---|
| v=0 | 版本号,固定为0 | 别改它,改了设备不认 |
| o= | 会话发起者和会话ID | 有些设备会校验这个ID,乱填可能被拒 |
| m=video | 媒体类型和端口 | 端口填0表示由服务器分配 |
| a=rtpmap | 编码格式和时钟频率 | H264的时钟频率固定是90000 |
| a=fmtp | 编码参数 | 这里藏着SPS/PPS,解码的关键 |
避坑指南:我曾经在解析SPS/PPS时踩过坑。有些设备会把sprop-parameter-sets字段的base64编码搞错。如果你发现画面花屏,先检查这个字段。
你想想看,如果没有SDP,客户端根本不知道视频是H264还是H265,分辨率是多少,帧率是多少。所以DESCRIBE这一步是必须的。
3.3 与RTP/RTCP的关系
这三者的关系,我打个比方:
- RTSP:是导演,负责喊「开始」、「停」。
- RTP:是快递员,负责把视频数据一包一包送过去。
- RTCP:是监工,负责反馈「这包丢了」、「那包延迟了」。
在实际项目中,RTP和RTCP通常是成对出现的。RTP走偶数端口,RTCP走下一个奇数端口。比如RTP用5000,RTCP就用5001。
我记得有一次调试一个NVR项目,画面总是卡顿。我抓包一看,发现RTCP的反馈包被防火墙拦截了。服务器收不到丢包信息,就一直重传,导致网络拥堵。嗯,这个问题排查了整整一个下午。
重要提醒:RTCP的反馈机制在某些场景下可以关闭。但我不建议这么做。没有RTCP,你就等于闭着眼睛开车。丢包了也不知道,画面花了也不知道。
RTP的头部结构也很关键。我简单说一下:
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
这里面的sequence number和timestamp,是保证视频流畅播放的关键。sequence number用来排序,timestamp用来控制播放节奏。
为什么会丢包?说白了就是网络不稳定。但有了RTP的序列号,接收端可以判断哪些包丢了,然后通过RTCP告诉发送端。发送端可以选择重传,也可以选择忽略。
我个人习惯在项目中把RTCP的间隔设短一点。默认是5秒一次报告,我一般改成1秒。这样能更快发现网络问题。但代价是多了些带宽开销。你根据实际情况权衡。
最后总结一下:RTSP负责控制,SDP负责描述,RTP负责传输,RTCP负责反馈。四者配合,才能实现一个稳定的实时视频流系统。
下一章我会讲RTSP的交互流程和状态机。到时候咱们用Wireshark抓包看看,这些协议到底是怎么跑的。