一個RtspServer的設計與實現和RTSP2.0簡介


一個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進行了修改,比如刪除了RECORDANNOUNCE方法,新增了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方法,等,等等。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

haibindev.cnblogs.com,合作請聯系QQ。(轉載請注明作者和出處~)

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


免責聲明!

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



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