一個RtspServer的設計與實現和RTSP2.0簡介
前段時間著手實現了一個RTSP Server,能夠正常實現多路RTSP流的直播播放,因專案需要,只做了對H.264和AAC編碼的支援,但是相信其他編碼的實現基本邏輯也是想通的。這裡我把主要設計和思考過程,以及實現框架分享一下。因為關注的是直播,這裡只討論RTSP直播協議。
RTSP協議概述與RTSP2.0
眾所周知,RTSP協議是一個流媒體協議,可以實現直播和點播形式的音訊與視訊流的播放。RTSP協議定義了多種伺服器-客戶端之間互動的介面,主要有OPTIONS,DESCRIBE,SETUP,PLAY,TEARDOWN,RECORD,ANNOUNCE。網路上已經有很多針對RTSP協議的文章,我這裡不準備進行過多介紹,詳細的協議定義,可以參見RFC2326。RTSP並不包括具體資料的傳輸,該功能一般由RTP與RTCP協議來實現,並可以通過TCP或UDP兩種底層傳輸方式進行。
下圖是典型的RTSP直播過程中服務端-客戶端主要互動過程:
當然,直播過程中也可能在伺服器與客戶端之間呼叫GET_PARAMETER等其他介面,上圖偷懶省略了。上圖綠色部分表示的是資料傳輸。之前說過,流媒體資料傳輸不是RTSP協議的內容,由RTP包來做。但是具體在實現上,RTP包可以通過UDP或TCP的方式來進行,而且這兩種傳輸方式,區別其實還不小,下面具體說下。
RTSP 資料傳輸流程
1. RTSP over UDP
對於udp模式,客戶端在傳送PLAY以後,就開始建立udp埠,以接收伺服器發來的RTP包,同樣,伺服器也會建立udp埠,並向客戶端傳送RTP包。這是網上大部分程式所採用的方式,優點是邏輯清晰,實現方便,不過缺點也很明顯,就是udp所固有的,容易丟包,尤其是在高解析度高位元速率下。
2. RTSP over TCP
對tcp模式,通過SETUP介面來指定傳輸方式,伺服器返回同樣資料以確定雙方通過tcp方式來傳輸資料。不過跟udp最大的不同是,rtsp over tcp的形式,不再建立單獨的tcp通道,而是直接使用之前rtsp通訊所使用的tcp通道,流程如下所示:
由於跟rtsp訊息使用同一個tcp埠,為了區分,rtp以及rtcp包,增加了4個位元組額外的欄位,並通過特殊的標識'$',與正常的rtsp訊息進行了區分。
RTSP Live Server 設計與實現
1. 程式框架
我這次所實現的RTSP Server,主要功能是採集攝像頭和麥克風資料,進行h.264編碼以及aac編碼,並對外提供RTSP直播流服務。我在實際寫程式碼中,也是首先實現了rtsp over udp的模式,然而,通過實際測試,我發現在高解析度高位元速率情況下,由於h.264 NAL單元過大,會拆分成很多的rtp包,而udp不可靠的傳輸方式,總是難免丟包,在低位元速率的時候還不明顯,高位元速率情況下,丟包導致的花屏會頻繁出現,這樣體驗特別差。於是我重新實現了一份rtsp over tcp模式的程式碼,順利解決了這個問題。
2. 關於h264在sdp中的描述
h264在sdp中的媒體資訊,大多都是可以直接填寫的,但是有兩項資料需要根據編碼後的資料來提取,就是profile-level-id和sprop-parameter-sets。這兩項字串資料的計算公式
- profile-level-id = "Base16(sps[1])" + "Base16(sps[2])" + "Base16(sps[3])"
- sprop-parameter-sets = "Base64(sps)" + "," + "Base64(pps)"
3. 主要程式碼
3.1 Rtsp服務介面
3.2 RtspSession在TCP通道里處理RTSP訊息與RTP報文
4. 執行效果
同時用vlc和ffplay進行多路播放,以tcp請求的方式,效果如下,延遲極低。
關於RTSP 2.0
2016年IETF釋出了新的RTSP標準,這就是就是RTSP2.0協議(RFC7826),新標準還是有不少修改的,除了完善一些原協議的中的定義,還有一些我覺得比較重要的是,對介面method進行了修改,比如刪除了RECORD和ANNOUNCE方法,新增了PLAY_NOTIFY方法。
- 刪除了RECORD,這表示你不能再通過這個介面來控制伺服器進行資料的錄製了,可以選擇在PLAY方法中,新增一些引數,來實現伺服器對直播資料進行錄製,還可以分隔錄製。
- 刪除了ANNOUNCE,這意味著,不能像RTMP一樣,客戶端通過向伺服器推送資料,來實現本機資料對外直播了,這可能需要其他的推送途徑來進行替代了。
- 至於PLAY_NOTIFY,它替代來原來Server向Client端傳送ANNOUNCE方法,所實現的功能,也就是告訴客戶端,需要根據新引數來調整直播播放狀態。
- 刪除通過UDP傳輸RTSP訊息的形式
- 刪除通過發PLAY訊息來keep alive的方式(用SET_PARAMETER來做)
- RTSP Server也可向Client發TEARDOWN訊息
- 支援IPV6
- RTSP請求,支援pipelining的形式,也就是聚合Request。比如可以不等伺服器返回,把SETUP和PLAY一起傳送,這樣可以提高至少一個RTT的啟動時間。當然需要在訊息里加上相關欄位。
- 重寫了狀態機,完善了伺服器對客戶端來說在各個狀態之間的轉換和行為
- RTSP訊息內支援URI了
- 擴充套件了REDIRECT方法,等,等等。
相關文章
- 一個簡單的時間視窗設計與實現
- 一個簡易郵件群發軟體設計與實現
- java設計模式一一設計模式的簡介和介紹Java設計模式
- 《Bootstrap 4 Web設計與開發實戰》簡介bootWeb
- Java實現一個簡單的計算器Java
- shell程式設計—簡介(一)程式設計
- Redis(設計與實現):---釋出與訂閱介紹Redis
- Tekton 設計簡介 及 實踐
- Proteus實現簡單51程式的設計與模擬
- 用java實現一個簡單的計算器Java
- 快捷簡易統計圖表模型設計與實現模型
- flex設計思想和語法簡介Flex
- LFU 的設計與實現
- Titan 的設計與實現
- 實現一個簡單的TomcatTomcat
- 實現一個簡易的vueVue
- 前端 JavaScript 實現一個簡易計算器前端JavaScript
- WCM功能簡介與企業級設計
- Python實現火柴人的設計與實現Python
- 限流 SDK 的設計與實現
- Picker元件的設計與實現元件
- Steps 元件的設計與實現元件
- 動手實現一個localcache - 設計篇
- 使用Netty和動態代理實現一個簡單的RPCNettyRPC
- 簡單的實現一個原型鏈原型
- 實現一個簡單的MVVM(Compile)MVVMCompile
- php實現一個簡單的socketPHP
- 實現一個簡單的 RESTful APIRESTAPI
- Matlab簡介與程式設計例項(一)(西北工業大MOOC)Matlab程式設計
- 《redis設計與實現》Redis
- Redis設計與實現Redis
- Cobar SQL審計的設計與實現SQL
- Vuex和Redux都使用的Flux設計模式精簡版實現VueRedux設計模式
- 遊戲設計與現實的距離,你憑什麼說這個設計一定有效?遊戲設計
- 實現一個簡單的 jQuery 的 APIjQueryAPI
- 簡易實現一個expressExpress
- ModbusTCP協議簡介與程式設計流程圖TCP協議程式設計流程圖
- 論如何用Vue實現一個彈窗-一個簡單的元件實現Vue元件
- 關於一個最簡單的數獨解題實現與疑惑一