(轉)基於live555的流媒體代理轉發服務器


對於並發量並不大而且對性能要求不是很高的流媒體傳輸模塊,live555還是很好的選擇,下面說一下我所實現的流媒體代理服務器(目前只能實現對H264單視頻的轉發)代理轉發主要

對於並發量並不大而且對性能要求不是很高的流媒體傳輸模塊,live555還是很好的選擇,下面說一下我所實現的流媒體代理服務器(目前只能實現對H264單視頻的轉發)

 

代理轉發主要分為對RTSP的轉發與對RTP的轉發(沒有實現對rtcp的轉發),盡量做到不破壞原有程序框架,所以還是要將整個代理過程融合於ServerMediaSubsession、Source、Sink的循環中,按照流程,RTSP OPTIONS不是必需進行轉發,直接轉到DESCRIBE的轉發過程。

 

DECRIBE轉發:在看過很多大型的流媒體服務器協議以后,會發現有一個相同點:前端設備在注冊到流媒體服務器以后會將其自身的無論是實時資源還是錄像資源都上報到流媒體服務器中集中管理,那么此處同理,在流媒體服務器上線(主動注冊與保活)后改為主動向前端請求資源,到此處也就是發送DESCRIBE請求,我實現的代理服務器中,專門定義了一個類,繼承自RTSPClient,向前端設備發送DESCRIBE請求,成功接收到攜帶SDP信息的反饋以后,根據SDP信息生成MediaSession,再執行其中每一個MediaSubsession的initiate(),這樣獲取由前端發送來數據的Source就已經准備就緒,同時,在每一個MediaSubsession建立以后,在對應流的ServerMediaSession中加入ServerMediaSubsession(此處ServerMediaSubsession繼承自OnDemandServerMediaSubsession),這樣就做到了一個ServerMediaSubsession對應一個MediaSubsession(這里一定要區分ServerMediaSubsession與MediaSubsession),兩路會話的連接,下面就是客戶端發起了DESCRIBE請求,轉到RTSPServer::RTSPClientSession::handleCmd_DESCRIBE(),再轉到ServerMediaSession::generateSDPDescription(),因為是轉發,而且不能讓客戶端知道是轉發,所以sdp信息在m字段前面的參數都是基於代理服務器本身,從m開始便是真正的媒體信息,原有的live555結構中,獲取每一個track的sdpLine是由virtual char const* OnDemandServerMediaSubsession::sdpLines();得到,於是,我們可以重寫此virtual函數,返回什么呢,返回的就是我們剛才傳入的MediaSubsession的savedSDPLines()返回值。這樣,SDP信息就可以在不破壞原有live555循環的基礎上構造出來,並實現轉發了。

 

SETUP轉發:同DESCRIBE一樣,原有框架已經形成,在收到SETUP請求以后,找RTSPServer::RTSPClientSession::handleCmd_SETUP(),再找到virtual void OnDemandServerMediaSubsession::getStreamParameters(),在原有live555循環中,此函數作用為建立本地接收端口,建立createNewSource與createNewSink,將數據傳輸循環中的各個部件都准備妥當,一旦收到Play命令就開始循環工作,那么同樣重寫此virtual函數,在重寫中實現向前端發送SETUP請求,等待響應成功,再執行本地的SETUP,向前端發送SETUP實現可以同樣由剛才傳入的"RTSPClient繼承"與MediaSubsession來實現發送命令,等待返回,再繼續執行OnDemandServerMediaSubsession::getStreamParameters()實現本地的SETUP,如此一來,本地與遠程的SETUP都已完成。

 

PLAY轉發:同樣,按照流程,重寫OnDemandServerMediaSubsession::startStream()函數,發送Play請求到遠程,等待返回,再執行本地的startStream(),本地與遠程的Play都已完成。

 

上面已經將RTSP的轉發實現,而且基本是在live555原有基礎上進行,沒有破壞原有框架結構,下面進行rtp的轉發。

 

rtp的轉發實現的重點是在建立source到sink的循環,重寫OnDemandServerMediaSubsession::createNewStreamSource,與OnDemandServerMediaSubsession::createNewRTPSink,理想中的轉發是能夠實現收到rtp包不進行任何重組,直接發送即可,但我所實現的只能是由MediaSubsession中的readSource獲取完整的一幀后,再交給rtpSink進行重新切片組裝,具體到實現上,我實現了一個集成自H264VideoStreamFramer的類,並將MediaSubsession->readSource作為inputSource傳入,重寫doGetNextFrame(),從inputSource中獲取完整一幀,copy到fTo,再交由createNewRTPSink()返回的H264VideoRTPSink進行重新組裝並發送,后來考慮到此種做法,有利有弊,與不重新組裝,直接發送,各有考慮。

 

如此,便實現了RTSP與RTP的轉發功能,多有不妥,后續會持續改進,還望能夠在留言中多多指正!

 

2012.3.23

 

有朋友問到rtcp的轉發問題,這里闡述下我的理解:

 

轉發RTCP實際的意義並不是很大,一個方面是rtcp控制的可能是兩條不通的數據鏈路,對擁堵的控制總是在較小的鏈路基礎上,犧牲太大;第二是作為服務器考慮,服務器通過雙重身份將數據取來再發出去,控制協調應當完全自主掌控,如果后期在服務器中加入緩存機制實現抖動控制和擁堵控制,可以通過對進線與出線的rtcp控制達到控制作用,而且效果較好!

轉自:http://www.easydarwin.org/article/Streaming/1.html


免責聲明!

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



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