webrtc源碼閱讀理解一
webrtc是一個比較成熟的實時音視頻處理開源項目,一上來老大就扔給我一本webrtc native實踐,雖然狠下心「翻」完了一遍,但是還是雲里霧裡的,在經過幾個月的摸索之後,我大概知道原因了,歸根到底,是基礎不在一個層次,理解不了的,所以我決定,嘗試寫一個接近我這種零基礎入門實時音視頻的記錄系列,希望能幫到一些同學
基礎概念的理解
實時音視頻是一個很長的流程,從採集-編碼-傳輸-接收-解碼-渲染,每一個步驟都是很大的模塊,所以我們一個一個來,我們先從採集相關的設計開始,我們先看一些概念,否則直接看代碼會有點懵
stream(流):包含音頻軌和視頻軌的編碼流
track(軌道):音頻軌或者視頻軌
音視頻同異點-我的理解
先說幾個點
- 音頻和視頻還是很多地方不一樣的
- 音頻採集了,自己不不要同時聽到自己,一般只需要傳輸給對方;一般只有一個採集的地方;即使有多個採集的地方,對方希望聽到是合流之後的一個聲音;
- 視頻採集了,一般需要同時在己方和對方都渲染顯示出來;可能要多個採集源;一般希望每個視頻源獨立展示(甚至是不同的設備展示)
- 音頻和視頻有很多地方是一致的
- 是同級的概念;整體的處理流程幾乎一致
- 音頻和視頻輸入和輸出的過程不一樣
整體感覺是視頻的邏輯要比音頻複雜一些,所以下面我主要也是圍繞視頻展開,音頻也會順便說下
視頻代碼設計
其實這個地方很難真正從零開始,我這裡也是從中間某個點開始說(對着代碼說自己的理解);結合上面的同異點,我們來看下webrtc裏面的代碼設計
source和sink
這是我覺得第一個坑的設計,但你理解了之後,覺得這樣設計也沒有問題


聯繫實際場景,攝像頭採集到圖像之後,保存視頻,成為視頻源,編碼和本地渲染需要消費圖像做處理,類似於生產和消費的概念
對於消費者,也就是sink來說,如果我想要增加一個消費者,我繼承sink接口,塞到保存視頻源的實例裏面去,讓實例不斷給我塞數據給我消費即可(onFrame),所以sink的接口定義比較好理解;
source的接口定義裏面只有對sink的操作,這是我覺得一開始不好理解的地方,source並沒有存儲視頻圖像(為什麼叫source呢?);我現在的理解是,相對於sink,這樣的接口就可以理解為source(攝像頭採集圖像之後,調用source的某個接口,這這個接口裏面,對圖像數據進行分發給sink,對於sink來說,這個實例就可以理解為source);
videoBroadcaster
broadcaster做的就是我們上面那段話想做的事情
source的接口太簡單了,下面是videoSourceBase的函數定義,還增加了一個sinks的成員來保存所有的sink成員;
而broadcaster同時繼承了sink和source,這就是我們想做的事情:初始化一個broadcaster實例,增加一個消費者sink的時候,把sink通過broadcaster的source接口存入sinks即可;當採集到圖像的時候,把圖像按照既定的邏輯調用所有sink的接口即可;
webrtc裏面同時是sink又是source的實例還有很多,例如

這是第一個實際概念到代碼設計的實踐,可以看到,簡單的物理概念想真正用代碼設計構架起來,還是需要很多抽象設計和構架思考的
source、track、stream
上面說完了整體一個大概念的圖像採集之後,採集分發的小流程,這些圖像數據source要變成track最後要形成 stream,我們看下這裡的設計,在這些之前,有些更細節的概念也要考慮到,例如音視頻發生了變化需要通知觀察者
所以首先定義了觀察者接口和通知者接口,都是很純粹的接口定義
而通知者的繼承關係則很長,通知接口有三個繼承者MediaSourceInterface,MediaStreamTrackInterface,MediaStreamInterface,基本source、track、stream都是通知者
MediaSourceInterface
定義了媒體源的基本狀態,媒體大類有兩個,音頻和視頻,所以有兩個繼承者VideoTrackSourceInterface,AudioSourceInterface,上面也說到過,音視頻細節上有些差異,從這裡的接口設計可以看到一些
AudioSourceInterface
AudioSourceInterface的接口,例如音量這些,都是音頻獨有的
VideoTrackSourceInterface
因為之前已經定義了VideoSourceInterface,所以這裡直接到了videoTrackSource的定義
從audio和video兩個繼承來看,這裡的分化挺明顯的
MediaStreamTrackInterface
track的定義和繼承如下,定義了trackState和必要接口;同時可以看到有音視頻track兩個子接口
videoTrack
audioTrack和VideoTrack有一個不一樣的地方是,audioTrack只是組合了audioSource,videoTrack還繼承了videoSource,我理解這是因為視頻的來源和分發比音頻複雜,因為所有的音頻可能最後會匯聚成一個,是多個視頻源可能需要分發和處理到不同的地方;
MediaStreamInterface
最後繼承Notifier的是MediaStreamInterface,可以看到,stream是videoTrack和audioTrack的組合
好了,今天就先寫到這裡,後面應該會持續更新
p