【流媒體服務器Mediasoup】 源碼中重要類基本概念 、上層代碼作用詳解、底層C++類關係詳解(四)

目錄

 

前言     

MediaSoup的特性 

特性一

特性二

特性三

 

MediaSoup SFU簡單的架構說明

MediaSoup庫中Lib目錄下的JS作用

MediaSoup-JS類的關係圖

MediaSoup js部分起到的作用

MediaSoup C++ 庫類關係圖

核心類圖

C++類圖

小結


前言
     

      上篇文章對MediaSoup源碼的調試方法  以及運行時分析、調試、查看核心信息   【流媒體服務器Mediasoup】調試源碼以及運行時分析、調試、查看核心信息(三),本章節主要對MediaSoup的源碼中重要類基本概念 、上層代碼作用詳解、底層C++類關係詳解

      在下一篇文章中將繼續對MediaSoup的源碼進行分析和架構的講解。

MediaSoup的特性 

特性一

  •       支持IPV6
  •       ICE/DTLS/RTP/RTCP    既可以在TCP協議上運行也可以在UDP協議上運行
  •       支持Simulcast(多流發送) 和 SVC(分層接收) 

特性二

  •        支持擁塞控制
  •        帶寬評估  (Remb前幾個章節有提到)
  •        支持STCP協議(非音視頻數據 如文件,文本數據)

特性三

  •         多留使用同一個 ICE + DTLS 傳輸通道 (減少端口的佔用)
  •         擁有強大的性能(底層是C++ 使用進程+LIBUV  異步I/O實踐處理機制)

 

MediaSoup SFU簡單的架構說明

              å¨è¿éæå¥å¾çæè¿°

Worker

  •       一個Worker代表着一個運行在單核CPU上並處理Router實例的mediasoup C++子進程;

Router

  •        Router用於注入、選擇和轉發通過Transport實例創建的媒體流;

Transport

  •        Transport將終端與MediaSoup Router連接起來,並通過在其上創建的Producer和Consumer實例實現雙向媒體傳輸,實         現了下面3種Transport:WebRtcTransport,PlainRtpTransport,PipeTransport.
  1.       每個Client創建兩個Peerconnection分別用於發送和接受媒體流,發送端用於發送承載本地videoTrack和audioTrack的      localStream,接收端接受來自其他Client的remoteStream;
  2.       同時Room會爲每個Client創建一個Peer,Peer管理兩個Transport用於接受Client的媒體流和向Client發送媒體流;
  3.      Peer爲對應的Client發送的videoTrack和audioTrack分別創建一個Producer(共2個);
  4.      Peer爲其他兩個Client發送的videoTrack和audioTrack分別創建2個Consumer(共2個);
  5.      Producer將媒體數據發送給每一個訂閱者Consumer
  6.     Consumer代表着一個被MediaSoup Router轉發到終端的音頻或視頻源。它是在定義媒體數據包傳送方式的Transport之上創建的。

 

MediaSoup庫中Lib目錄下的JS作用

               

        lib庫需要先npm install   編譯過後纔會出現詳細請參閱

                  【流媒體服務器Mediasoup】環境部署與demo搭建(二)

        npm install後 lib 庫的路徑爲

                    server\node_modules\mediasoup\lib

                                                                  

AudioLevelObserver.js  

          用於檢測聲音的大小, 通過C++檢測音頻聲音返回應用層,通過Observer接收並展示音頻大小

Channel.js

          主要用於與C++部分信令通訊

Consume.js

      消費媒體數據,音頻或視頻

EnhancedEventEmitter.js

      EventEmitter的封裝,C++底層向上層發送事件

Logger.js

      用於寫日誌

PipeTransport.js

      Router之間的轉發

PlainRtpTransport.js

      普通的rtp傳輸通道,如FFmpeg等不經過瀏覽器rtp協議的數據傳輸

Producer.js

     生產媒體數據,音頻或視頻

Routers.js

     代表一個房間或者一個路由器

RtpObserver.js

     Rtp數據的觀察者 回調用的

Transport.js

     所有傳輸的的基類(父類)

WebRtcRtpTransport.js

  瀏覽器使用的傳輸

Worker.js

    一個節點或者一個進程,實際應該是進程,代碼中根據CPU核數啓動相對   應的Worker數量;一個房間只能在一個Worker裏。

Errors.js

     錯誤信息的定義

Index.js

     Mediasoup的庫,上層引入Mediasoup最先導入的庫,也爲庫的索引。

Ortc.js

     其與SDP相對應,以對象的形式標識SDP,如編解碼參數,編解碼器,幀   率等,以對象方式去存儲。

ScalabilityModes.js

  一般不關心,略過

SupportedRtpCapabilities.js

  對通訊能力的支持,實際上是媒體協商相關的東西,如你支持的幀率, 碼率,編解碼器是什麼等

Utils.js

       一些常見的工具函數

 

MediaSoup-JS類的關係圖

 

                            

  • 每個Worker裏有多個Router
  • 每個Worker裏都有一個Channel(管道) 通過其與C++進行通訊
  • 每個用戶的Transport可能會有多個Produces或者 Consume
  • ransoprt爲WebRtcTransport(瀏覽器加密數據使用的傳輸)、PlainRtpTransport(自定義Rtp數據,如FFmpeg推流使用的傳輸)、PipeTransport(不同Router之間的通信傳輸)的基類

MediaSoup js部分起到的作用

  • 起到管理作用,通過上圖可以看出各個模塊之間的關係
  • 生成JSON字符串,傳給C++; 作爲承上啓下的作用,即是應用層調用的接口層,又是C++層的適配層或者橋樑層,上層應用與C++的一個橋樑。

例如

 createRouter({ mediaCodecs, appData = {} } = {}) {
           ....            
            yield this._channel.request('worker.createRouter', internal);
            const data = { rtpCapabilities };
            const router = new Router_1.Router({
                internal,
                data,
                channel: this._channel,
                appData
            });
          .....
    }

 ..channel.request()最後會構造json字符串通過channel 傳給C++層,C++層則做它自己相對應的邏輯操作.

 

MediaSoup C++ 庫類關係圖

   對於C++庫來說是整個MediaSoup庫中最核心的部分,包括了基本的一些管理,這些管理或者關係相對於JS來說要少一些,但最主要的是流的傳輸,首先對於WebRtc 要先進行數據加密再傳到服務端之後要對這些數據進行解密操作。另外包括整個數據的安全,它的驗證機制是由C++部分進行驗證的,包括流的流轉,數據的流轉,帶寬的評估,發生丟包之後的通知客戶端進行重傳等操作都是有C++部分完成這些工作。

核心類圖

                 

SimpleConsumer

        普通RTP數據的消費者,比如有音頻流和視頻流每個都是SimpleConsumer,沒有按類型區分,音視頻流都是一樣的,最簡單的consumer

PipeConsumer

        不同Worker之間Router之間的數據流轉,則其爲接收或者消費從另外一個Worker中的Router傳過來的數據

SvcConsumer

        傳輸時一般分爲3層(核心層、拓展層、邊緣層)進行傳輸,則其處理消費多層數據

SimulcastConsumer

        當共享者使用的是多路流時,則使用其來接收

Consumer

        爲上述模塊的基類(父類)

WebRtcTransport

        主要用於瀏覽器之間的或者瀏覽器與其他終端進行通訊的,這種傳輸數據一般是進行加密的,爲了保證數據安全,它有很多安全機制,安全機制較爲複雜。

PlainRtpTransport

用於普通或者自定義的rtp數據傳輸

PipeTransport

不同Worker之間Router之間的數據傳輸

TransportTuple

包括了本地的Socket,遠端的Soucket ,使用的是TCP還是UDP , 傳輸協議等信息存儲地方

Transport

        各種傳輸的基類(父類)

 

C++類圖

                 

RtpPack的起作用爲對rtp數據包的一個分析,如Rtp包中有包頭,拓展頭,數據,對於數據協議或者解析都是它的工作

SeqManager對傳輸的數據重新進行排序和處理,相當於WebRtc客戶端與服務端之間進行傳輸數據的時候 服務端要新產生一個流推送給客戶端,整個順序都是重新排的,某個SSRC所對應的起始位置是多少,後面的包都是以這個起始包基礎上進行傳輸和排序遞增

所有Consumer都包含了RtpStreamSend對象, 從服務端角度來說,消費數據等於把數據發送給其他客戶端

Producer對於服務端來說,他要生產流數據則就是接受客戶端傳輸來的數據,因此每個Producer會對應多個RtpStreamRecv,爲什麼會有多個接收流?有可能是丟包了,丟包重傳的數據也是單獨的一路流。RtpStreamRecv使用了NackGenerator(丟包的一個產生器),對於接受者來說,發送者發了100個包,那麼接受者是知道丟了哪些包(通過SeqManager知道丟的哪些包), 如果短時間內可以通過NackGenerator對客戶端通知 進行補包。

WebRtcTransport

可以使用UDP或者TCP來傳輸數據,這兩種傳輸都用PortManager進行端口管理,Mediasoup的默認端口爲4000~4999(不同woker[進程]可複用),管理如關口是否被佔用等一些策略。具體的傳輸工作還是 handle目錄下的::UdpSocket和 ::TcpServer來完成。UdpSocket和TcpServer只是做了一層封裝。

使用了上述的數據連接之後,對於上層傳輸來說,DtlsTransport 使用了dtls協議對rtp數據包進行加密的傳輸,在DtlsTransport 會用到SrtpSession的 收與發。RembClient和RembServer主要用於帶寬的評估,對於共享者來說MediaSoup它的WebRtcTransport就是一個Clinet端,對於消費者來說,它就是Server端。Remb只是其中一種帶寬評估方法,還有其他,這裏不做重點講解。

TransportTuple很多可選項存儲在IceServer裏,一對多的關係,TransportTuple如果是Tcp連接那麼裏面還包含了::TcpConnection,  其與 ::TcpServer又有關係,它包含了多個::TcpConnection

 

小結

有很多人對 Nodejs 比較詬病,認爲 Nodejs 提拱不了高性能的流媒體服務器。實際上,如果按照傳輸的 Nodejs 應用開發出的流媒體服務器肯定是不能勝任這項工作的。但對於 Mediasoup 來講,它只不過使用 Nodejs 做 信令處理 及 業務的管理 工作,所以它的負擔並不重。對性能要求高的是媒體數據流的轉發工作,而這部分工作是由 Mediasoup(C++)部分實現的。Nodejs 與 Mediasoup之間通過管道進行通信。

嚴格意義上來說,Mediasoup是單進程的。但這不影響了它的性能。實際上,它是使用單進程的方式將服務器上CPU某個 充分利用好,然後在業務層控制進程的個數。比如說你的服務器是個 8 核的CPU,那麼在業務層你就該啓動 8 個Mediasoup進程。通過這種方式來達到對 CPU 的充分利用。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章