0. 简介
这里的分析都是基于源码的testRTSPClient为入口。
主要分为4个库:
1.UsageEnvironment:抽象了两个类UsageEnvironment和TaskScheduler,
a)UsageEnvironment:表示整个运行环境,同时提供错误记录和输出的功能。
b)TaskScheduler:表示任务调度中心,用于异步事件的读取和处理。
2.groupsock:网络接口的封装
3.liveMedia:基于基类Medium,实现各种流媒体和编解码类型结构,定义了source(生产者)和sink(消费者)操作。
4.BasicUsageEnvironment:UsageEnvironment和TaskScheduler的具体实现类。
1. RTSP Client的流程
流程图如下:
这里抓包分析一下,如下:
a) sendDescribeCommand:DESCRIBE消息,用来获取sdp信息
req: DESCRIBE rtsp://10.151.3.77:8554/test.264 RTSP/1.0 CSeq: 2 User-Agent: 1 (LIVE555 Streaming Media v2020.03.06) Accept: application/sdp rsp: RTSP/1.0 200 OK CSeq: 2 Date: Wed, Sep 08 2021 09:25:55 GMT Content-Base: rtsp://10.151.3.77:8554/test.264/ Content-Type: application/sdp Content-Length: 501 v=0 // <version> 协议版本 o=- 1631093155092004 1 IN IP4 10.151.3.77 // <username> <session id> <version> <network type> <address type> <address> 所有者/创建者和会话标识符 s=H.264 Video, streamed by the LIVE555 Media Server // <session name> 会话名称 i=test.264 // <session description> 会话信息 t=0 0 // <start time> <stop time> 会话活动时间 a=tool:LIVE555 Streaming Media v2021.08.24 a=type:broadcast a=control:* a=range:npt=now- a=x-qt-text-nam:H.264 Video, streamed by the LIVE555 Media Server a=x-qt-text-inf:test.264 // <attribute>:<value> 会话属性 m=video 0 RTP/AVP 96 // <media> <port> <transport> <fmt list> 媒体名称和传输地址 c=IN IP4 0.0.0.0 // <network type> <address type> <connection address> 连接信息— 如果包含在会话层则该字段可选 b=AS:500 // <modifier>:<bandwidth-value> 带宽信息 a=rtpmap:96 H264/90000 a=fmtp:96 packetization-mode=1;profile-level-id=640028;sprop-parameter-sets=Z2QAKKzMYCgPZA==,aOlKOLA= a=control:track1
b) sendSetupCommand:SETUP请求,建立会话和确定传输模式
req: SETUP rtsp://10.151.3.77:8554/test.264/track1 RTSP/1.0 CSeq: 3 User-Agent: 1 (LIVE555 Streaming Media v2020.03.06) Transport: RTP/AVP;unicast;client_port=54346-54347 rsp: RTSP/1.0 200 OK CSeq: 3 Date: Wed, Sep 08 2021 09:25:55 GMT Transport: RTP/AVP;unicast;destination=10.151.144.69;source=10.151.3.77;client_port=54346-54347;server_port=6970-6971 Session: 9F44F18F;timeout=65
c) sendPlayCommand:播放请求,服务器开始播放
req: PLAY rtsp://10.151.3.77:8554/test.264/ RTSP/1.0 CSeq: 4 User-Agent: 1 (LIVE555 Streaming Media v2020.03.06) Session: 9F44F18F Range: npt=0.000- rsp: RTSP/1.0 200 OK CSeq: 4 Date: Wed, Sep 08 2021 09:25:55 GMT Range: npt=0.000- Session: 9F44F18F RTP-Info: url=rtsp://10.151.3.77:8554/test.264/track1;seq=17205;rtptime=3614453685
2. RTSPClient客户端
可以看到,RTSPClient继承liveMedia,实现了RTSP协议,主要有两个部分:
1. 创建tcp连接
a) setupStreamSocket:创建tcp socket
b) connectToServer:连接服务器
c) 注册回调:连接成功以后,会向调度中心注册回调,用来接收TCP数据
2. 发送RTSP报文
a) sendRequest:主要是通过这个函数,发送RTSP报文
b) 注册响应回调:回调会缓存到fRequestsAwaitingResponse链表中,incomingDataHandler收到数据,最终调用 RTSPClient::handleResponseBytes(),在这里会调用注册的回调。
3. TaskScheduler调度中心
1. 在RTSP客户端最后,会调用任务调度,如下:
看一下实现,就是while循环,这里通过select循环读取socket事件,并调用注册的回调。
2. 注册回调函数:
fHandlers保存了回调函数和socket等相关信息,它也是基于链表保存的。
4. MediaSession
MediaSession主要用来创建RTP和RTCP客户端,以及相关数据处理。看上面的流程,发送DESCRIBE报文,收到200 OK响应,我们拿到SDP信息,就会创建相关Socket。
这些在MediaSubsession::initiate(int useSpecialRTPoffset)中实现,主要创建三个对象:
- fRTPSocket:RTP客户端
- fRTCPSocket:RTCP客户端
- fReadSource(H264VideoRTPSource):用来获取RTP数据,它会向调度中心注册回调
5. MediaSink消费者
MediaSink主要是用来获取RTP数据的,需要继承实现continuePlaying();SETUP成功以后,就可以创建MediaSink,并且调用startPlaying()。
最后会调用continuePlaying(),实现如下
我们看看getNextFrame()
到这里看到,doGetNextFrame会到TaskScheduler调度中心注册回调,异步读取RTP数据。