RTSP连接的建立过程
RTSPServer
用类DynamicRTSPServer::CreateNew(* env, rtspServerPortNum, authDB)
实现,建立Socket(ourSocket)
在TCP的554端口进行监听,然后把连接处理函数句柄RTSPServer::incomingConnectionHandler
和socket
句柄传给任务调度器taskScheduler
。
这里,使用了linux
下有名的select
模型,taskScheduler
把554的socket
放到了readset
中,同时将socket
句柄和incomingConnectionHandler
句柄相关联,然后main
函数进入env.taskScheduler.doEventLoop
。
select
函数只是返回此时是否有socket
准备好读写,然后遍历handlerset
用FD_ISSET
判断是否handler
所掌管的socket
可以用了,如前面提到的incomingConnectionHandler
了,在incomingConnectionHandler
中创建了RTSPClientSession
,开始对这个客户端的会话进行处理。
DESCRIBE请求消息处理过程
RTSP
服务器收到客户端的DESCRIBE
请求后,根据请求URL(rtsp://192.168.1.109/1.mpg)
找到对应的流媒体资源,返回响应消息。live555
中的ServerMediaSession
类用来处理会话中描述,它包含多个音频或视频的子会话描述ServerMediaSubsession
。
创建的RTSPClientSession
会有一个新的socket
在新的port
上监听,同时也会有 incomingConnectionHandler
,就是说类似于554
的处理过程 ,不过这个incomingConnectionHandler
是属于RTSPClientSession
的,在这个 incomingConnectionHandler
中,就有根据cmdName
执行不同的Handler
,如 handleCmd_DESCRIBE
。此时,通过url
去确定产生哪种类型的subsession
,在一个Session
下可以有多个subsession
,且它们形成链表,比如在看mpg
文件的时候,mpg
既包括一个video
的subsession
, 又包括一个audio
的subsession
(这样也就不难解决h.264
视频编码和g.711
音频编码同时播放的问题,它们在一个ServerMediaSession
中的subSession
中)。
这里,还需要提一下ServerMediaSession
和RTSPClientSession
的关系,RTSPClientSession
与socket
、handler
关联 ,标记一次rtsp
的过程,而在该链接处理DESCRIBE
信令时 ,产生ServerMediaSession
,标记Server
端所能提供的媒体会话。
SETUP
前面已经提到RTSPClientSession
类,用于处理单独的客户会话,其类成员函数handleCmd_SETUP
处理客户端的SETUP
请求,调用parseTransportHeader
对SETUP
请求的传输头解析,调用子会话,这里具体实现类为 OnDemandServerMediaSubsession
的getStreamParameters
函数获取流媒体发送传输参数,将这些参数组装成响应消息返回给客户端。
获取发送传输参数的过程:调用子会话,具体实现类MPEG1or2DemuxedServerMediaSubsession
的createNewStreamSource
创建MPEG1or2VideoStreamFramer
,选择发送传输参数,并调用子会话的 createNewRTPSink
创建MPEG1or2VideoRTPSink
,同时将这些信息保存在StreamState
类对象中,用于记录流的状态。
客户端发送两个SETUP
请求,分别用于建立音频和视频的RTP
接收。
PLAY请求消息处理过程
RTSPClientSession
类成员函数handleCmd_PLAY()
处理客户端的播放请求。首先调用子会话的startStream()
,内部调用MediaSink::startPlaying(...)
,然后是 MultiFramedRTPSink::continuePlaying()
,接着调用 MultiFramedRTPSink::buildAndSendPacket(...)
。
buildAndSendPacke
内部先设置RTP包头,内部再调用MultiFramedRTPSink::packFrame()
填充编码帧数据。
packFrame
内部通过FramedSource::getNextFrame()
, 接着MPEGVideoStreamFramer::doGetNextFrame()
,再接着经过 MPEGVideoStreamFramer::continueReadProcessing()
, FramedSource::afterGetting(...)
, MultiFramedRTPSink::afterGettingFrame(...)
, MultiFramedRTPSink::afterGettingFrame1(...)
等一系列繁琐调用,最后到了 MultiFramedRTPSink::sendPacketIfNecessary()
, 这里才真正发送RTP
数据包。然后是计算下一个数据包发送时间,把MultiFramedRTPSink::sendNext(...)
函数句柄传给任务调度器,作为一个延时事件调度。
在主循环中,当MultiFramedRTPSink::sendNext()
被调度时,又开始调用 MultiFramedRTPSink::buildAndSendPacket(...)
开始新的发送数据过程,这样客户端就可以源源不断的收到服务器传来的RTP
包了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。