getStats是WebRTC一個很是重要的API,用來向開發者和用戶導出WebRTC運行時狀態信息,包括網絡數據接收和發送狀態、P2P客戶端媒體數據採集和渲染狀態等[1]。這些信息對於監控WebRTC運行狀態、排除程序錯誤等很是重要。瀏覽器
本文首先描述W3C定義的getStats標準,而後展現如何在JS層調用getStats,最後深刻分析WebRTC源代碼中getStats的實現。全文從標準到實現,全方位透徹展現getStats的細節。網絡
一 getStats標準getStats的標準由W3C定義,其接口很簡單,可是卻返回豐富的WebRTC運行時信息。其返回信息的主要內容以下[2]:異步
1.發送端採集統計:對應於媒體數據的產生,包括幀率,幀大小,媒體數據源的時鐘頻率,編解碼器名稱,等等。ide
2.發送端RTP統計:對應於媒體數據的發送,包括髮送數據包數,發送字節數,往返時間RTT,等等。函數
3.接收端RTP統計:對應於媒體數據的接收,包括接收數據包數,接收字節數,丟棄數據包數,丟失數據包數,網絡抖動jitter,等等。編碼
4.接收端渲染統計:對應於媒體數據的渲染,包括丟棄幀數,丟失幀數,渲染幀數,渲染延遲,等等。spa
另外還有一些雜項統計,如DataChannel度量,網絡接口度量,證書統計等等。在衆多信息中,有一些反映WebRTC運行狀態的核心度量,包括往返時間RTT,丟包率和接收端延遲等,分別表述以下:線程
·往返時間RTT:表示數據在網絡上傳輸所用的時間,通常經過RTCP 的SR/RR數據包中的相關域進行計算。該度量直接反映網絡情況的好壞。code
·丟包率影響接收端音視頻質量,在嚴重的狀況下可能致使聲音跳變或者視頻馬賽克,從側面反映網絡情況的好壞。視頻
·音視頻數據到達接收端以後,要經歷收包、解碼、渲染等過程,該過程會帶來延遲。接收端延遲是數據從採集到渲染單向延遲的重要組成部分。
經過以上分析可知,getStats的返回信息包含WebRTC數據管線的各個階段的統計信息,從數據採集、編碼到發送,再到數據接收、解碼和渲染。這爲監控WebRTC應用的運行狀態提供第一手數據。
二 使用JS調用getStatsgetStats的JS API很簡單, W3C規定getStats的JS API函數PTCPeerConnection.getStats須要三個參數:一個可爲空的MediaStreamTrack對象,一個調用成功時的回調函數和一個調用失敗時的回調函數。成功回調函數的參數爲getStats獲得的RTCStatsReport,主要工做就發生在解析RTCStatsReport上,拿到咱們感興趣的參數,進而分析應用的運行狀態。
下面咱們選取W3C標準上給出的例子做簡單講解[1]。假設當前會話的通話質量不好,咱們想知道是否是因爲丟包率過大引發的。所以,咱們能夠經過getStats返回結果的outbound-rtp中的丟包數和收包數計算丟包率,而後進行判斷。具體代碼實現以下:
經過上述例子,咱們能夠體會到從JS層調用getStats分析應用運行狀態的基本流程。值得注意的是,Chrome和Firefox兩款瀏覽器在調用方面有稍微差異,具體請參考文檔[3]。
三 getStats在WebRTC內部的實現JS層的getStats調用如何傳遞到到WebRTC內部的實現函數,涉及到瀏覽器的內部工做原理,具體到Chrome瀏覽器來說,是由WebKit,V8,Content,libjingle等模塊一塊兒協同工做實現。本節咱們不討論這裏面的細節,咱們只關注getStats在WebRTC內部的實現。
WebRTC模塊對外提供兩個重要對象:PeerConnectionFactory和PeerConnection,前者負責一系列重要對象的建立,如MediaStream,MediaSource,MediaTrack等等,後者則負責P2P鏈接的創建和維護,包括CreateOffer/Answer,AddStream等操做。監控P2P鏈接運行狀態GetStats函數,天然在PeerConnection對象中實現,而該對象把任務委託給成員變量StatsCollector對象的UpdateStats函數來實現:
由該函數咱們能夠看到,信息的收集是分模塊進行的,其中最重要的是四個模塊的信息:Transport,VoiceChannel,VideoChannel,DataChannel。顧名思義,Transport是和網絡相關的統計信息,而其他三個是和各自MediaChannel相關的統計信息。
Extract系列函數從相應模塊收集到信息後,執行後處理操做,把不一樣類型的信息從新組織爲類型相同的StatsReport對象,存儲到StatsCollector的列表中。StatsReport對象結構基本定義以下:
下面以ExtractVideoInfo爲例分析信息收集過程:
從videochannel收集到的數據來自三個模塊:VideoSendStream,VideoReceiveStream 和Call,這三個模塊分別從本身的信息統計對象中得到統計數據,最後彙總爲VideoMediaInfo對象,由ExtractStatsFromXX系列函數歸一化爲StatsReport對象。
以上分析的即爲getStats函數的內部實現細節。須要注意的是,getStats只負責拉取統計數據,而統計數據自己則由WebRTC內部各個模塊週期性更新,這個過程是異步的。例如,傳輸層的RTT是由網絡線程收到數據包後實時更新,而帶寬估計信息則是在受到RTCP報文後解析計算獲得。下面以VideoReceiveStream統計信息的更新過程爲例,深刻分析這部分是如何協同工做的:
VideoReceiveStream的數據更新和拉取
在Video接收端,network/decoder/render三個線程在各自工做完成後,都會更新相應的統計數據到timing對象中。而module process線程則週期性更新Stats proxy對象,該對象從timing對象中拉取數據,保存在本身的stats成員變量中。最後,getstats線程調用流程到達stats proxy對象,獲取stats數據而返。工做線程、更新線程和拉取線程共同協同工做完成統計數據的產生、更新和拉取
四 總結本文從標準、使用和實現三個方面全方位分析了WebRTC的getStats API,這對WebRTC應用的運行時監控和狀態分析排錯具備重要意義,咱們從另外一角度對WebRTC有了更深刻的理解。