RTSP服務器實例live555源代碼分析

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返回對應的socket,進而根據前面保存的對應關係,可找到對應處理函數句柄,這裏就是前面提到的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(...)成員函數生成子會話描述。

 

Live555庫是一個使用開放標準協議如RTP/RTCP、RTSP、SIP等實現多媒體流式傳輸的開源C 庫集。這些函數庫可以在Unix、Windows、QNX等操作系統下編譯使用,基於此建立RTSP/SIP服務器和客戶端來實現多媒體流的傳輸。下面給出具體實現過程[4]

(1)客戶端發起RTSP OPTION請求,目的是得到服務器提供什麼方法。RTSP提供的方法一般包括OPTIONS、DESCRIBE、SETUP、TEARDOWN、PLAY、PAUSE、SCALE、GET_PARAMETER。

(2)服務器對RTSP OPTION迴應,服務器實現什麼方法就回應哪些方法。在此係統中,我們只對DESCRIBE、SETUP、TEARDOWN、PLAY、PAUSE方法做了實現。

(3)客戶端發起RTSP DESCRIBE請求,服務器收到的信息主要有媒體的名字,解碼類型,視頻分辨率等描述,目的是爲了從服務器那裏得到會話描述信息(SDP)。

(4)服務器對RTSP DESCRIBE響應,發送必要的媒體參數,在傳輸H.264文件時,主要包括SPS/PPS、媒體名、傳輸協議等信息。

(5)客戶端發起RTSP SETUP請求,目的是請求會話建立並準備傳輸。請求信息主要包括傳輸協議和客戶端端口號。

(6)服務器對RTSP SETUP響應,發出相應服務器端的端口號和會話標識符。

(7)客戶端發出了RTSP PLAY的請求,目的是請求播放視頻流。

(8)服務器對RTSP PLAY響應,響應的消息包括會話標識符,RTP包的序列號,時間戳。此時服務器對H264視頻流封裝打包進行傳輸。

(9)客戶端發出RTSP TEARDOWN請求,目的是關閉連接,終止傳輸。

(10)服務器關閉連接,停止傳輸。

 


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

發送RTP數據包的間隔計算方法:

       Update the time at which the next packet should be sent, based onthe duration of the frame that we just packed into it.


高性能商業RTSP流發送庫


## 簡介 HiPF_RTSP_Server是商業級高性能RTSP流發送服務端,是針對嵌入式環境下高併發、高流量、多碼流、低延時實時RTSP發送服務器需求進行設計,在低性能ARM處理下有較高性能同時保持良好的兼容性。

高性能商業RTSP流接收庫


HiPF_RTSP_Client是商業級高性能RTSP流接收庫,是針對嵌入式環境下接收高併發、高流量RTSP流需求進行設計,在多種平臺下有超高接收性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章