WebRTC:如何從WebRTC中提取出音頻QoS代碼(Windows下並編譯成dll庫文件)

轉載請註明出處:https://blog.csdn.net/qq_29621351/article/details/80991615

WebRTC版本:M66 

      WebRTC的語音QoS機制幾乎可以說是行業的標杆,其實現的方式主要融入了三種技術,包括丟包重傳(NACK),前向糾錯(FEC)以及原GIPS公司的網絡均衡器(NetEqualizer,簡稱NetEQ)。前兩種都是在犧牲一定成本的前提下,盡最大努力降低丟包率,而NetEQ是在前兩者的基礎上降低延遲、彌補丟包。

      WebRTC語音質量效果好絕不是因爲使用了其中某一項技術,而是三種技術相結合並且有策略的使用,例如對於實時音視頻來講,丟包重傳技術由於需要等待重傳包,往往會增加延時,而它在與前向糾錯同時使用的過程中,只有在前向糾錯無法恢復丟失的數據包時,纔會使用丟包重傳,並且即使開啓了丟包重傳,對於它重傳過來的數據包,是否使用還要權衡網絡的RTT狀態值。WebRTC源碼中對於語音QoS的封裝層次很深,NetEQ封裝在最底層,其中包含着抖動消除、解碼和丟包隱藏(也就是丟包補償)。在NetEQ的外層,封裝着NACK和FEC。某些編解碼器也支持帶內的FEC(例如opus)。

      其實我是做Android版的WebRTC的,但是Android版本WebRTC調試實在是太不方便了,所以我一般做什麼都預先在Windows上做完,這樣可以用VS單步調試,然後在Linux上模仿着做。這次主要是在WebRTC中將音頻QoS接收端處理提取出來,用C語言格式封裝成庫,以後可以隨拿隨用。首先需要有VS開發環境,WebRTC源碼,至少在VS上面編譯了一遍WebRTC(以往的文章中有方法),這樣有基礎環境會好很多。

    從WebRTC中提取音頻QoS的代碼分爲很多種層面,最底層從neteq_impl層面,再高一層可以從,我選擇了從audio_coding_module層面來實現,因爲從這一層不僅可以使用NetEQ的抖動緩衝和丟包隱藏功能,還能享受到某些編碼器(例如opus)集成的FEC和DTX功能,如果更高的話就是channel層,而這已經脫離了簡單的QoS處理的層面,接口調用的層面體現在WebRTC源碼的文件中。

audio_coding_module.cc
acm_receiver.cc
neteq_impl.cc

 如果想編譯成.so文件使用方便,最好用C語言封裝。

提取代碼

      首先在自己的電腦上完整的編譯一遍Windows版本WebRTC,這在我以前的文章中有方法,然後自己新建一個工程,取個名字。我的叫acm,工程最終將編譯生成dll文件。

然後需要定義你想要封裝的接口,寫一個文件acm.def內容如下,接口的名字和數量隨便改,這就是我定義的5種接口,分別是創建、初始化、釋放、插入RTP包和去除PCM數據。可以根據自己的需要定義形式。

LIBRARY acm
EXPORTS
WebRtcQos_Create @ 1
WebRtcQos_Init @ 2
WebRtcQos_Free @ 3
WebRtcQos_InsertPacket @ 4
WebRtcQos_getAudioData @ 5

將這個文件放在與acm.cpp源文件相同目錄下,然後在工程中將其添加進去,右鍵acm項目—>添加—>現有項,不用在意我這個文件夾下有多少文件,這都是我在完成工程之後添加的文件。

接下來配置acm調用WebRTC源碼頭文件的導入目錄以及預處理宏定義

右鍵點擊acm解決方案,然後選擇屬性 —> C/C++ —> 常規

屬性 —> C/C++ —> 預處理器(NOMINMAX預處理變量爲可能出現的一種BUG的解決方式)

接下來就可以基於WebRTC裏面的audio_coding_module.h裏面定義的接口進行自己的QoS處理封裝了,我的處理比較簡單直接,只定義了5個接口。封裝完之後生成解決方案。

生成解決方案成功之後理論上寫上那麼一小段程序調用這個dll庫是可以運行的,但是如我們所知,事實上編譯的過程只是編譯了一個調用語句,沒有要求具體的實現,而鏈接的過程才需要實際的代碼,所以我們要將自己編譯的WebRTC中的peerconnection_client工程所編譯好的xxx.obj、xxx.lib、xxx.dll文件鏈接到現有的acm工程中,這樣可以節省很多繁瑣的尋找依賴頭文件的過程。至於該鏈接哪些xxx.obj、xxx.lib、xxx.dll,其實我也不是很清楚,但你可以一點點的去嘗試,我的做法是,我找到了webrtc_checkout\src\out\Debug\obj\examples\peerconnection_client.ninja文件,這個文件主要包含peerconnection_client編譯過程中的預處理變量、導入頭文件的路徑、編譯器標誌和鏈接文件等等,如下。

在link之後的基本上就是需要鏈接的文件,於是我把他原封不動的鏈接到acm工程中,連接方式如下,但是這樣做可能導致最後鏈接生成的acm.dll文件過於龐大,所以大家也可以一點點試着選擇性的去除鏈接文件,如果對功能有影響就保留,沒影響就刪除鏈接。

以上路徑均可以寫成絕對路徑,然後由於我們要生成的是dll動態鏈接庫文件,所以要設置模塊定義文件。

此外,還需要將acm中的代碼調試設置成多線程調試,如下。

這是因爲acm中的兩個函數是分別需要在兩個線程中調用。然後編譯就會在acm工程源碼目錄的debug下生成acm.dll文件,當某個程序調用它時,就將它拷貝到這個程序.exe文件的源碼目錄下。

最終,你可以再創建一個工程test_acm。

並將acm.dll拷貝到工程源碼目錄下,然後需要設置一些與acm工程類似的相關變量。

然後就編譯運行test_acm,測試逆接口的封裝,注意每更改一次acm源碼,就需要重新編譯acm源碼,生成新的acm.dll文件,然後重新拷貝到test_acm工程中去。

至於如何封裝接口,以後接口成熟了,我可能會上傳到github中去。這裏就不介紹了。

如果有在實施過程中出現問題的,可以下方評論,我會盡力解決。

 

 

 

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