開源流媒體處理庫live555服務器端、客戶端源代碼分析總結


RTSP服務器端流程:

1. RTSP連接的建立過程

      RTSPServer類用於構建一個RTSP服務器,該類同時在其內部定義了一個RTSPClientSession類,用於處理單獨的客戶會話。

      首先創建RTSP服務器(具體實現類是DynamicRTSPServer),在創建過程中,先建立Socket(ourSocket)在TCP的554 端口進行監聽,然后把連接處理函數句柄(RTSPServer::incomingConnectionHandler)和socket句柄傳給任務調度器(taskScheduler)。

      任務調度器把socket句柄放入后面select調用中用到的socket句柄集(fReadSet)中,同時將socket句柄和 incomingConnectionHandler句柄關聯起來。 接着,主程序開始進入任務調度器的主循環(doEventLoop),在主循環中調用系統函數select阻塞,等待網絡連接。

      當RTSP客戶端輸入(rtsp://192.168.0.1/1.mpg)連接服務器時,select返回對應的scoket,進而根據前面保存的對應關系,可找到對應處理函數句柄,這里就是前面提到的incomingConnectionHandler了。在 incomingConnectionHandler中創建了RTSPClientSession,開始對這個客戶端的會話進行處理。


2. DESCRIBE請求消息處理過程

      RTSP服務器收到客戶端的DESCRIBE請求后,根據請求URL(rtsp://192.168.0.1/1.mpg),找到對應的流媒體資源,返回響應消息。live555中的ServerMediaSession類用來處理會話中描述,它包含多個(音頻或視頻)的子會話描述 (ServerMediaSubsession)。

      RTSP服務器收到客戶端的連接請求,建立了RTSPClientSession類,處理單獨的客戶會話。在建立RTSPClientSession的過程中,將新建立的socket句柄(clientSocket)和RTSP請求處理函數句柄 RTSPClientSession::incomingRequestHandler傳給任務調度器,由任務調度器對兩者進行一對一關聯。

      當客戶端發出RTSP請求后,服務器主循環中的select調用返回,根據socket句柄找到對應的incomingRequestHandler,開始消息處理。先進行消息的解析,如果發現請求是DESCRIBE則進入handleCmd_DESCRIBE函數。根據客戶端請求URL的后綴(如 1.mpg),調用成員函數DynamicRTSPServer::lookupServerMediaSession查找對應的流媒體信息 ServerMediaSession。如果ServerMediaSession不存在,但是本地存在1.mpg文件,則創建一個新的 ServerMediaSession。在創建ServerMediaSession過程中,根據文件后綴.mpg,創建媒體MPEG-1or2的解復用器(MPEG1or2FileServerDemux)。再由MPEG1or2FileServerDemux創建一個子會話描述 MPEG1or2DemuxedServerMediaSubsession。最后由ServerMediaSession完成組裝響應消息中的SDP信息(SDP組裝過程見下面的描述),然后將響應消息發給客戶端,完成一次消息交互。

SDP消息組裝過程:

      ServerMediaSession負責產生會話公共描述信息,子會話描述由 MPEG1or2DemuxedServerMediaSubsession產生。 MPEG1or2DemuxedServerMediaSubsession在其父類成員函數 OnDemandServerMediaSubsession::sdpLines()中生成會話描述信息。在sdpLines()實現里面,創建一個虛構(dummy)的FramedSource(具體實現類為MPEG1or2AudioStreamFramer和 MPEG1or2VideoStreamFramer)和RTPSink(具體實現類為MPEG1or2AudioRTPSink和 MPEG1or2VideoRTPSink),最后調用setSDPLinesFromRTPSink(...)成員函數生成子會話描述。


3. SETUP請求消息處理過程

        RTSPClientSession類用於處理單獨的客戶會話。其類成員函數handleCmd_SETUP()處理客戶端的SETUP請求。調用 parseTransportHeader()對SETUP請求的傳輸頭解析,調用子會話(這里具體實現類為 OnDemandServerMediaSubsession)的getStreamParameters()函數獲取流媒體發送傳輸參數。將這些參數組裝成響應消息,返回給客戶端。

        獲取發送傳輸參數的過程:調用子會話(具體實現類MPEG1or2DemuxedServerMediaSubsession)的 createNewStreamSource(...)創建MPEG1or2VideoStreamFramer,選擇發送傳輸參數,並調用子會話的 createNewRTPSink(...)創建MPEG1or2VideoRTPSink。同時將這些信息保存在StreamState類對象中,用於記錄流的狀態。

        客戶端發送兩個SETUP請求,分別用於建立音頻和視頻的RTP接收。

4. 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包了。

openRTSP客戶端流程:

1、創建TaskScheduler和BasicUsageEnvironment類;

  

2、命令行解析,獲取流媒體地址和其他選項;  

 

3、創建RTSPClient對象;  

 

4、如果需要,RTSPClient對象發送OPTIONS命令並解析服務端響應,獲取可以使用命令集。 

 

5、RTSPClient對象發送DESCRIBE命令,並從獲服務端反饋中獲取流媒體相關描述SDP字串。 

 

6、創建MediaSession對象,解析SDP字串,創建了相應的子會話對象。在這個過程中還完成了RTP和RTCP通信使用的GroupSock對象的創建,包括協議和端口的選擇。 

 

7、根據流媒體不同類型,實例化具體的RTP會話的Source和Sink對象。 

 

8、RTSPClient對象發送SETUP和PLAY命令,服務端開始傳輸流媒體數據。  

 

9、TaskScheduler開始事件處理循環,通過select監聽數據包到達並調用注冊函數進行處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM