EasyDarwin開源流媒體伺服器Golang版本:拉轉推功能之拉流實現方法
阿新 • • 發佈:2018-12-01
EasyDarwin開源流媒體伺服器(www.easydarwin.org),拉轉推是一個很有意義的功能,它可將一個獨立的RTSP資料來源“拉”到伺服器,再通過轉發協議轉發給多個客戶端,或者通過EasyDarwin的本地儲存功能進行儲存。國內大多攝像機都支援RTSP協議,通過拉轉推可將第三方攝像機接入到EasyDarwin伺服器。
拉轉推需要伺服器不僅實現服務端,還要實現客戶端。這裡我們介紹下拉流功能的實現。
RTSP的客戶端拉流流程為:
- 傳送RTSP命令
- 接收RTP媒體流
傳送RTSP命令,又有如下幾步:
- OPTIONS 獲取Server端支援的REQUEST請求集合
- DESCRIBE 獲取碼流的SDP
- SETUP 根據SDP資訊,配置單個媒體流的傳輸方式
- PLAY 啟動播放
我們結合程式碼分析下拉流是如何實現的。RTSP的拉流實現在rtsp-client.go
檔案裡,我們定義了一個結構體RTSPClient
,實現了兩個方法Start
和Stop
在Start函式裡面,主要有兩部分,RTSP命令互動部分,即requestStream
和媒體流收發部分,即stream
。
先看requestStream
- 解析URL的host和port,建立TCP連結,準備進行命令互動
- 傳送OPTION和DESCRIBE請求,這裡的Request介面,是封裝的一個進行RTSP命令互動的介面,該介面傳送報文,並接受響應,解析響應資訊。返回值分別是RTSP的響應和錯誤。在程式碼裡,每一個請求都判斷了錯誤,如果錯誤了則直接返回。
- 解析DESCRIBE返回的SDP資訊,並針對每一個Stream,傳送SETUP命令。這裡使用了開源的SDP解析類
go-sdp
來解析SDP,其地址為https://github.com/pixelbender/go-sdp 在程式碼可以看出SDP解析出來後,遍歷每一個stream,如果是video或者audio那就分別傳送SETUP
資訊
- 傳送PLAY命令,向伺服器端申請流
傳送了PLAY
命令後,requestStream
結束,然後整個流程進入stream
部分.
stream
部分主要是持續接收媒體流或者Server端發來的RTSP命令報文(包括請求和響應),必要的情況下再發送心跳包給伺服器。
- 初始化,這裡根據OptionIntervalMillis引數是否大於0來判斷是否需要傳送心跳包給伺服器端。如果需要,那以該值為週期,定期傳送OPTIONS請求。注意這裡的OPTIONS不能阻塞接收響應,這是因為此刻伺服器端也在不斷地傳送著RTP資料,這種情況下阻塞接受響應的話,可能會受到RTP資料。響應報文由後續的持續接收資料部分進行處理。
- 接收RTP資料。根據RTP資料格式,我們先讀一個位元組的頭,如果這個頭的值為0x24,則其為RTP資料。否則就是RTSP命令資料。對於RTP資料,接下來我們的工作,就是將其完全接收,然後放到佇列裡面。
- 這裡是RTP包的解析過程,可以看到,首先收取一個包的長度,然後根據這個長度,接收完成所有的一整包。再去解析包的內容,最後將包回調出去。RTP包有四種類型,VIDEO、AUDIO、VIDEOCONTROL、AUDIOCONTROL,這些型別通過channel來區分開來。channel是在SETUP的時候指定的。
- 非RTP資料包的接收,就比較簡單了。由於RTSP是文字協議,逐行讀取文字,直到讀出一個長度為0的行。同時判斷是否包括
Content-Length
?如果有的話,再讀取Content-Length
長度的資料包。否則接收完成。完全接收到一個整包後,這裡單純打印出來,不做後續操作。但是我們還是要把它完全接收,不然會導致資料包的解析完全亂套。
接收到的RTP資料包,我們在這裡僅僅將其回撥給上層處理。上層要維護一個佇列,並將RTP資料包入隊了。當有Client連線時,從佇列裡面去除RTP包,分發給Client,便實現了拉流轉發功能。
資源連結
EasyDarwin官網:www.easydarwin.org
EasyDarwin Github:https://github.com/easydarwin