1. 程式人生 > >linux下live555編譯和除錯

linux下live555編譯和除錯

./genMakefile linux-gdb
make
2、執行
cd mediaServer
./live555MediaServer
可以看到支援的檔案格式是不包括 .264 的。(關於其它格式請參考我的另一篇博文)
3、live555 模組分析

分為四個基本庫 :UsageEnvironment&TaskScheduler, groupsock, liveMedia和BasicUsageEnvironment

UsageEnvironment和TaskScheduler類用於事件的排程,實現非同步讀取事件的控制代碼的設定以及錯誤資訊的輸出。另外,還有 一個HashTable類定義了一個通用的hash表,其它程式碼要用到這個表。這些都是抽象類,在應用程式中基於這些類來實現自己的子類。

groupsock類是對網路介面的封裝,用於收發資料包。正如名字本身,groupsock主要是面向多播資料的收發的,它也同時支援單播資料 的收發。 

liveMedia庫中有一系列類,基類是Medium,這些類針對不同的流媒體型別和編碼。 
備註:在支援 h.264 的過程中,主要是修改這個目錄下,需要新增一些檔案

各種測試程式碼在testProg目錄下,這個目錄下的測試很多要求組播,組播環境比較難搭建(當然排除你是搞網路的),所以,建議測試 testOnDemandRTSPServer 
測試步驟:
1、./testOnDemandRTSPServer 
這時,你會看到它的提示,不要著急去測試,先把你測試所需的媒體檔案丟到 testProg 目錄下
2、建議客戶端使用 vlc 測試, vlc 在 linux 下 apt-get 即可,在 windows 下也有相應版本
3、測試過程中,為了提高效率,建議使用抓包工具 ,推薦使用  wireshark ,在 linux 下 source code 編譯安裝,在 windows 下有相應版本

4、live555 概述

Media Server是一個純粹的RTSP伺服器。支援多種格式的媒體檔案(在我的另一篇博文中有提到為什麼強調“支援”)

5、用live555開發必備概念

基於liveMedia的程式,需要通過繼承UsageEnvironment抽象類和TaskScheduler抽象類,定義相應的類來處理事 件排程,資料讀寫以及錯誤處理。live專案的原始碼裡有這些類的一個基本實現,這就是“BasicUsageEnvironment”庫。 BasicUsageEnvironment主要是針對簡單的控制檯應用程式,利用select實現事件獲取和處理。這個庫利用Unix或者 Windows的控制檯作為輸入輸出,處於應用程式原形或者除錯的目的,可以用這個庫使用者可以開發傳統的執行與控制檯的應用。 
通過使用自定義的“UsageEnvironment”和“TaskScheduler”抽象類的子類,這些應用程式就可以在特定的環境中執行, 不需要做過多的修改。需要指出的是在圖形環境(GUI toolkit)下,抽象類 TaskScheduler 的子類在實現 doEventLoop()的時候應該與圖形環境自己的事件處理框架整合。

一些重要的東東:
Sink -- 就是消費資料的物件,比如把接收到的資料儲存到檔案, 這個檔案就是一個Sink。
Source -- 就是生產資料的物件,比如通過RTP讀取資料。
Framer
Parser
Session -- 這主要是因為 rtsp 是有狀態的

備註:
從其它Source接收資料的source也叫做"filters"。
Module是一個sink或者一個filter。
資料接收的終點是 Sink類,MediaSink是所有Sink類的基類。
Sink類實現對資料的處理是通過實現純虛擬函式continuePlaying(),通常情況下 continuePlaying呼叫fSource->getNextFrame來為Source設定資料緩衝區,處理資料的回撥函式 等,fSource是MediaSink的型別為FramedSource*的類成員。
但如果你有硬編碼硬體生成的媒體檔案,並且不需要實時播放,那麼 Source 就是可以沒有的。

6、liveMedia的應用程式的控制流程

1)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,開始對這個客戶端的會話進行處理。

2)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 端所能提供的媒體會話。

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

7、新增檔案,修改 live555 支援 h.264
H264VideoStreamFramer: A filter that breaks up an H264 video stream into headers and frames 

StreamParser: Abstract class for parsing a byte stream 

H264VideoStreamParser: Class for parsing H264Video stream 

ByteStreamFileSource: A file source that is a plain byte stream (rather than frames) 

StreamState:A class that represents the state of an ongoing stream

H264VideoRTPSink 

H264VideoFileServerMediaSubsession