LIVE555研究之三:LIVE555基礎

ithzhang發表於2014-08-16

                                                  LIVE555基礎

 

     LIVE555是為流媒體提供解決方案的跨平臺C++開源專案。從今天起我們將正式開始深入LIVE555程式碼。

 

一、各庫簡要介紹

    LIVE555下包含LiveMediaUsageEnvironmentBasicUsageEnvironmentGroupSock庫,MediaServer簡單伺服器程式以及其他多個測試demo

    LiveMedia庫:包含一系列處理不同編碼格式和封裝格式的類,基類是Medium

    UsageEnvironment庫:環境類,用於錯誤資訊的輸出。LIVE555中多數類中均包含此類物件指標。其內部包含TaskSchedule抽象類的指標,該類用於任務排程,因此所有包含UsageEnvironment指標的類均可將自己加入到排程中。

    BasicUsageEnvironment庫:包含具體環境類和具體TaskScheduler類。UsageEnvironment用於對錯誤資訊的處理,BasicUsageEnvironment類用於以控制檯方式輸出錯誤資訊。因此想要以其他方式輸出錯誤資訊的類,可以從UsageEnvironment派生。BasicTaskSchedule類繼承自TaskScheduler抽象類,用以定義具體的排程策略。任何基於LIVE555的應用程式均需要定義自己的BasicEnvironmentTaskScheduler庫。如果建立視窗應用程式,在重定義TaskScheduler時,需要與圖形環境自己的事件處理框架整合。BasicTaskSheduler使用select模型實現事件的獲取和處理。如果想使用更高效的IOCP模型,可以定義自己的BasicTaskScheduler類。BasicTaskScheduler內部有一個迴圈,迴圈讀取佇列中的訊息並處理。整個基於BasicTaskScheduler的程式只有一個執行緒驅動。

    GroupSock庫:對各種socket操作的封裝,用於收發資料。主要面向組播,但也可以進行單播的收發資料,僅支援UDP,不支援TCP

    MediaServer 伺服器程式:該程式使用BasicUsageEnvironment庫實現,因此是一個控制檯程式。任務排程類是BasicTaskScheduler類,因此使用Select模型且僅有一個執行緒在迴圈處理各種事件。後期如果有時間會實現基於IOCPMediaServer伺服器程式。

    其他測試Demo:基於LIVE555實現的客戶端程式,會在需要的時候介紹。

 

二、涉及到的基本概念

 

1.  SouceSink

    Souce :翻譯為源、源頭。表示資料的提供者,比如通過RTP讀取資料,通過檔案讀取資料或者從記憶體讀取資料,這些均可以作為Souce

    Sink:翻譯為水槽。表示資料的流向、消費者。比如寫檔案、顯示到螢幕等。

    Filter:翻譯為過濾器。在資料流從Souce流到Sink的過程中可以設定Filter,用於過濾或做進一步加工。

    在整個LiveMedia中,資料都是從Souce,經過一個或多個Filter,最終流向Sink。在伺服器中資料流是從檔案或裝置流向網路,而在客戶端資料流是從網路流向檔案或螢幕。

 

    MediaSouce是所有Souce的基類,MediaSink是所有Sink的基類。

 

    從類數量和程式碼規模可以看到,LiveMedia類是整個LIVE555的核心,其內部包含數十個操作具體編碼和封裝格式的類。LiveMedia定義的各種Souce均是從檔案讀取,如果想實現從裝置獲得實時流的傳輸,可以定義自己的Souce

 

2.  ClientSession

    對於每一個連線到伺服器的客戶端,伺服器會為其建立一個ClientSession物件,儲存該客戶端的socketip地址等。同時在該客戶端中定義了各種響應函式用以處理和回應客戶端的各種請求。新版(2014.7.4)的LIVE555增加了ClientConnection類。用於處理一些與正常播放無關的命令。如命令未找到、命令不支援或媒體檔案未找到等。在ClientConnection處理DESCRIBE命令時會建立ClientSession物件,其他命令在ClientSession中處理。

 

3.  MediaSessionMediaSubsessionTrack

    LIVE555使用MediaSession管理一個包含音視訊的媒體檔案,每個MediaSession使用檔名唯一標識。

    使用SubSession管理MediaSession中的一個音訊流或視訊流。為行文方便我們稱音訊或視訊均為一個媒體檔案中的媒體流。因此一個MediaSession可以有多個MediaSubsession,一個管理音訊流一個管理視訊流。

    在上一篇介紹RTSP協議時,客戶端在給伺服器傳送DESCRIBE查詢某個檔案的SDP資訊時,伺服器會給客戶端返回該媒體檔案所包含的多個媒體流資訊。併為每個媒體流分配一個TrackID。如視訊流分配為Track1,音訊流分配為Track2。此後客戶端必須在URL指定要為那個Track傳送SETUP命令。

    因此我們可以認為MediaSubsession代表Server端媒體檔案的一個Track,也即對應一個媒體流。MediaSession代表Server端一個媒體檔案。對於既包含音訊又包含視訊的媒體檔案,MediaSession內包含兩個MediaSubsession

    但MediaSessionMediaSubsession僅代表靜態資訊,若多個客戶端請求同一個檔案,伺服器僅會建立一個MediaSession。各個客戶端公用。為了區分各個MediaSession的狀態又定義了StreamState類,用來管理每個媒體流的狀態。在MediaSubsession中完成了SouceSink連線。Souce對指標象會被設定進sink。在Sink需要資料時,可以通過呼叫SouceGetNextFrame來獲得。

 

    LIVE555中大量使用簡單工廠模式,每個子類均有一個CreateNew靜態成員。該子類的建構函式被設定為Protected,因此在外部不能直接通過new來構造。同時,每個類的建構函式的引數中均有一個指向UsageEnvironment的指標,從而可以輸出錯誤資訊和將自己加入排程。

 

4. HashTable

    LIVE555內部實現了一個簡單雜湊表類BasicHashTable。在LIVE555中,有很多地方需要用到該雜湊表類。如:媒體檔名與MediaSession的對映,SessionIDClientSession的對映,UserNamePassword的對映等。

 

5. SDP

    SDPSession Description Protocol的縮寫。是一個用來描述多媒體會話的應用層協議,它是基於文字的,用於會話建立過程中的媒體型別和編碼方案的協商等。客戶端會通過DESCRIBE命令請求查詢指定檔案的媒體資訊。有不明白的可以看下上一篇介紹RTSPRTPRTCP的文章。

 

6.  LIVE555中的關鍵類繼承層次(均以對H264碼流的處理為例)

   大家可以先混個臉熟,以後會詳細介紹。

                  Souce

                                                       

                            

    H264VideoStreamFramer是真正的Souce,它用於從h264檔案中讀取資料,並組裝成幀。在Sink呼叫GetNextFrame時將幀資料返回給Sink

 

                      Sink

                                 

    H264VideoRTPSink是真正的Sink,用於完成幀資料的傳送。

 

                SubSession

                                

    SubSession用於完成SouceSink的連線,同時用於管理每個媒體流。

                                                                                                                              

對於H264碼流,資料流的流動方向為:

    伺服器端:H264VideoStreamFramer ->H264Or5Fragmenter (Filter)r->H264VideoRTPSink

    客戶端:H264RTPSouce ->Sink(不同客戶端實現不同)

 

     LIVE555類之間關係很是複雜,類之間犬牙交錯的關係增大了學習LIVE555的難度,深入學習之前應先熟悉基本流程,對各類的大概功能有所瞭解,至於細節問題可暫時略過。 

     對於LIVE555的程式碼風格,本人不是很喜歡:一是成員變數命名方式。二是花括號({)緊跟在上一行的末尾,沒有上下對齊層次清晰。三是多句程式碼位於同一行,多見於if語句。當然這僅僅是是個人喜好。歡迎大家表達自己的見解。

     文章的最後,讓我們來探討下LIVE555應該如何發音的問題。聽過不少人都讀成: [liv](力V555)。個人感覺不對。因為live作為動詞講時,確實是讀成:力V,但此時是居住、生存、經歷的意思。作為形容詞講時是活的、直播、生動的。此時應讀成:賴V。作為一個為流媒體提供解決方案的開源C++專案,應該離直播更近一些吧!個人認為應該讀成賴V555。更洋氣的讀法:賴V Triple Five!這都是個人想當然的讀法,沒有聽過老外如何讀,歡迎拍磚!

 

    下節我們將從伺服器程式入手,開始介紹LIVE555原始碼。

        

                                                             2014.8.16於浙江杭州

相關文章