今天聊一下WebRTC。很多開發者,可能會覺得有些陌生,或者直接感覺繁雜。因為WebRTC在iOS上的應用,隻是編譯都讓人很是頭痛。這些話,到此為止,以防讓了解者失去信心。我們隻傳播正能量,再多的困難都是可以解決的。本部落格會不斷更新增加内容,不要怕長。首先看一下定義。WebRTC,名稱源自網頁實時通信(WebReal-TimeCommunication)的縮寫,是一個支援網頁浏覽器進行實時語音對話或視訊對話的技術,是谷歌2010年以6820萬美元收購GlobalIPSolutions公司而獲得的一項技術。2011年5月開放了工程的源代碼,在行業内得到了廣泛的支援和應用,成為下一代視訊通話的标準。
WebRTC實作了基于網頁的視訊會議,标準是WHATWG
協定,目的是通過浏覽器提供簡單的javascript就可以達到實時通訊(Real-Time Communications
(RTC))能力。
WebRTC(Web Real-TimeCommunication)項目的最終目的主要是讓Web開發者能夠基于浏覽器(Chrome\FireFox\...)輕易快捷開發出豐富的實時多媒體應用,而無需下載下傳安裝任何插件,Web開發者也無需關注多媒體的數字信号處理過程,隻需編寫簡單的Javascript程式即可實作,W3C等組織正在制定Javascript 标準API,目前是WebRTC1.0版本,Draft狀态;另外WebRTC還希望能夠建立一個多網際網路浏覽器間健壯的實時通信的平台,形成開發者與浏覽器廠商良好的生态環境。同時,Google也希望和緻力于讓WebRTC的技術成為HTML5标準之一,可見Google布局之深遠。
WebRTC提供了視訊會議的核心技術,包括音視訊的采集、編解碼、網絡傳輸、顯示等功能,并且還支援跨平台:windows,linux,mac,android。
架構元件介紹
(1) Your Web App
Web開發者開發的程式,Web開發者可以基于內建WebRTC的浏覽器提供的webAPI開發基于視訊、音頻的實時通信應用。
(2)Web API
面向第三方開發者的WebRTC标準API(Javascript),使開發者能夠容易地開發出類似于網絡視訊聊天的web應用,最新的标準化程序可以檢視這裡。
這些API可分成Network Stream API、 RTCPeerConnection、Peer-to-peer
Data API三類,詳細的API說明可以看這裡。
Network Stream API
MediaStream:MediaStream用來表示一個媒體資料流。
MediaStreamTrack在浏覽器中表示一個媒體源。
RTCPeerConnection
RTCPeerConnection:
一個RTCPeerConnection對象允許使用者在兩個浏覽器之間直接通訊。
RTCIceCandidate :表示一個ICE協定的候選者。
RTCIceServer:表示一個ICE Server。
Peer-to-peer Data API
DataChannel:資料通道( DataChannel)接口表示一個在兩個節點之間的雙向的資料通道 。
(3)WebRTC Native C++ API
本地C++ API層,使浏覽器廠商容易實作WebRTC标準的Web API,抽象地對數字信号過程進行處理。
(4)Transport / Session
傳輸/會話層
會話層元件采用了libjingle庫的部分元件實作,無須使用xmpp/jingle協定
a. RTP Stack協定棧
Real Time Protocol
b. STUN/ICE
可以通過STUN和ICE元件來建立不同類型網絡間的呼叫連接配接。
c. Session Management
一個抽象的會話層,提供會話建立和管理功能。該層協定留給應用開發者自定義實作。
(5)VoiceEngine
音頻引擎是包含一系列音頻多媒體處理的架構,包括從視訊采集卡到網絡傳輸端等整個解決方案。
PS:VoiceEngine是WebRTC極具價值的技術之一,是Google收購GIPS公司後開源的。在VoIP上,技術業界領先,後面的文章會詳細了解
a. iSAC
Internet Speech Audio Codec
針對VoIP和音頻流的寬帶和超寬帶音頻編解碼器,是WebRTC音頻引擎的預設的編解碼器
采樣頻率:16khz,24khz,32khz;(預設為16khz)
自适應速率為10kbit/s ~ 52kbit/;
自适應包大小:30~60ms;
算法延時:frame + 3ms
b.iLBC
Internet Low Bitrate Codec
VoIP音頻流的窄帶語音編解碼器
采樣頻率:8khz;
20ms幀比特率為15.2kbps
30ms幀比特率為13.33kbps
标準由IETF RFC3951和RFC3952定義
c.NetEQ for Voice
針對音頻軟體實作的語音信号處理元件
NetEQ算法:自适應抖動控制算法以及語音包丢失隐藏算法。使其能夠快速且高解析度地适應不斷變化的網絡環境,確定音質優美且緩沖延遲最小。
是GIPS公司獨步天下的技術,能夠有效的處理由于網絡抖動和語音包丢失時候對語音品質産生的影響。
PS:NetEQ
也是WebRTC中一個極具價值的技術,對于提高VoIP品質有明顯效果,加以AEC\NR\AGC等子產品內建使用,效果更好。
d.Acoustic Echo Canceler (AEC)
回聲消除器是一個基于軟體的信号處理元件,能實時的去除mic采集到的回聲。
e.Noise Reduction (NR)
噪聲抑制也是一個基于軟體的信号處理元件,用于消除與相關VoIP的某些類型的背景噪聲(嘶嘶聲,風扇噪音等等… …)
(6)VideoEngine
WebRTC視訊處理引擎
VideoEngine是包含一系列視訊處理的整體架構,從攝像頭采集視訊到視訊資訊網絡傳輸再到視訊顯示整個完整過程的解決方案。
a. VP8
視訊圖像編解碼器,是WebRTC視訊引擎的預設的編解碼器
VP8适合實時通信應用場景,因為它主要是針對低延時而設計的編解碼器。
PS:VPx編解碼器是Google收購ON2公司後開源的,VPx現在是WebM項目的一部分,而WebM項目是Google緻力于推動的HTML5标準之一
b. Video Jitter Buffer
視訊抖動緩沖器,可以降低由于視訊抖動和視訊資訊包丢失帶來的不良影響。
c. Image enhancements
圖像品質增強子產品
對網絡攝像頭采集到的圖像進行處理,包括明暗度檢測、顔色增強、降噪處理等功能,用來提升視訊品質。
視訊
WebRTC的視訊部分,包含采集、編解碼(I420/VP8)、加密、媒體檔案、圖像處理、顯示、網絡傳輸與流控(RTP/RTCP)等功能。
視訊采集---video_capture
源代碼在webrtc\modules\video_capture\main目錄下,包含接口和各個平台的源代碼。
在windows平台上,WebRTC采用的是dshow技術,來實作枚舉視訊的裝置資訊和視訊資料的采集,這意味着可以支援大多數的視訊采集裝置;對那些需要單獨驅動程式的視訊采集卡(比如海康高清卡)就無能為力了。
視訊采集支援多種媒體類型,比如I420、YUY2、RGB、UYUY等,并可以進行幀大小和幀率控制。
視訊編解碼---video_coding
源代碼在webrtc\modules\video_coding目錄下。
WebRTC采用I420/VP8編解碼技術。VP8是google收購ON2後的開源實作,并且也用在WebM項目中。VP8能以更少的資料提供更高品質的視訊,特别适合視訊會議這樣的需求。
視訊加密--video_engine_encryption
視訊加密是WebRTC的video_engine一部分,相當于視訊應用層面的功能,給點對點的視訊雙方提供了資料上的安全保證,可以防止在Web上視訊資料的洩漏。
視訊加密在發送端和接收端進行加解密視訊資料,密鑰由視訊雙方協商,代價是會影響視訊資料處理的性能;也可以不使用視訊加密功能,這樣在性能上會好些。
視訊加密的資料源可能是原始的資料流,也可能是編碼後的資料流。估計是編碼後的資料流,這樣加密代價會小一些,需要進一步研究。
視訊媒體檔案--media_file
源代碼在webrtc\modules\media_file目錄下。
該功能是可以用本地檔案作為視訊源,有點類似虛拟攝像頭的功能;支援的格式有Avi。
另外,WebRTC還可以錄制音視訊到本地檔案,比較實用的功能。
視訊圖像處理--video_processing
源代碼在webrtc\modules\video_processing目錄下。
視訊圖像處理針對每一幀的圖像進行處理,包括明暗度檢測、顔色增強、降噪處理等功能,用來提升視訊品質。
視訊顯示--video_render
源代碼在webrtc\modules\video_render目錄下。
在windows平台,WebRTC采用direct3d9和directdraw的方式來顯示視訊,隻能這樣,必須這樣。
網絡傳輸與流控
對于網絡視訊來講,資料的傳輸與控制是核心價值。WebRTC采用的是成熟的RTP/RTCP技術。
音頻
WebRTC的音頻部分,包含裝置、編解碼(iLIBC/iSAC/G722/PCM16/RED/AVT、NetEQ)、加密、聲音檔案、聲音處理、聲音輸出、音量控制、音視訊同步、網絡傳輸與流控(RTP/RTCP)等功能。
音頻裝置---audio_device
源代碼在webrtc\modules\audio_device\main目錄下,包含接口和各個平台的源代碼。
在windows平台上,WebRTC采用的是Windows Core Audio和Windows
Wave技術來管理音頻裝置,還提供了一個混音管理器。
利用音頻裝置,可以實作聲音輸出,音量控制等功能。
音頻編解碼---audio_coding
源代碼在webrtc\modules\audio_coding目錄下。
WebRTC采用iLIBC/iSAC/G722/PCM16/RED/AVT編解碼技術。
WebRTC還提供NetEQ功能---抖動緩沖器及丢包補償子產品,能夠提高音質,并把延遲減至最小。
另外一個核心功能是基于語音會議的混音處理。
聲音加密--voice_engine_encryption
和視訊一樣,WebRTC也提供聲音加密功能。
聲音檔案
該功能是可以用本地檔案作為音頻源,支援的格式有Pcm和Wav。
同樣,WebRTC也可以錄制音頻到本地檔案。
聲音處理--audio_processing
源代碼在webrtc\modules\audio_processing目錄下。
聲音處理針對音頻資料進行處理,包括回聲消除(AEC)、AECM(AEC
Mobile)、自動增益(AGC)、降噪(NS)、靜音檢測(VAD)處理等功能,用來提升聲音品質。
網絡傳輸與流控
和視訊一樣,WebRTC采用的是成熟的RTP/RTCP技術。
好了,這麼多的概念内容之後我要切入正題,iOS才是我們真正關心的。下面就進入我們關心的内容。
Webrtc的ios架構編譯
1.WebRTC的iOS架構的選擇
目前兩個比較活躍的開源WebRTC實作.
Google WebRTC:
項目位址是: https://code.google.com/p/webrtc/
Ericsson Research OpenWebRTC:
項目位址是: https://github.com/EricssonResearch/openwebrtc
我們戴維營教育為了給學生實戰項目中運用WebRTC視訊通話技術,選擇Google的WebRTC項目來建構iOS
App的開發架構,因為目前Chrome浏覽器和FireFox浏覽器的WebRTC支援都是采用該項目.那麼問題就來了,既然浏覽器裡都支援了
WebRTC,那我們再去移植編譯它到iOS平台幹嘛呢,直接用webview 不行? 對,還不行!
Apple在這方面已經嚴重拖後腿了.不過他有他牛逼的Facetime技術,可以随時随地的視訊通話,但是他不開源,是以我們隻能垂涎了.
故還是老老實實的移植WebRTC吧.非常幸運的是,Google
的Chromium項目開發者已經實作了其WebRTC的Objective-C的一套API了.
不過,醜話還是說在前頭好,要從零開始內建WebRTC到我們的App中中,
簡直就是噩夢;因為WebRTC項目和Chromium項目有一定的關聯依賴關系,而且這些項目都是跨平台的大項目,采用了Google自己的一套編譯系
統,相對我們日常的IDE來說要複雜的多.如果我們需要得到一個WebRTC的庫或者架構,我們就需要忘記Xcode
IDE和Interface Builder這些高科技,我們要切換到終端環境下用指令行下的黑科技來征服這一切.
2.開始WebRTC源碼下載下傳
前提條件:
我現在用的Macbook,8G記憶體,運作OS X 10.9.5.
安裝最新的git和subversions并確定其可正常工作.
Xcode 6.1.1 和 Command Line Tools.
中國大陸使用者額外要求,快速的VPN,或者快速的shadowsocks服務.(FQ和給git和svn以及curl設定代理等).
2.1 建立一個編譯目錄
我們建立一個目錄專門來存放項目編譯工具和項目代碼倉庫等.確定該目錄所在磁盤可用空間至少有8~10G.打開系統的終端工具進入到Shell:
wuqiong:~ apple$mkdir -p$HOME/opensource/webrtc_build/
2.2 下載下傳Chromium的depot工具
在執行下面指令之前,請確定你已經連上快速VPN已經FQ了,或者你已經給git單獨配置了有效的socksFQ代理,如果你這些都不是問題,就當我沒說.
wuqiong:~ apple$cd$HOME/opensource/webrtc_build/wuqiong:webrtc_build apple$git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
這是一套Google用來編譯Chromium或者WebRTC的建構工具,在我們後續的編譯過程中也将使用它.為了指令行使用友善,我們把這些工具的路徑加入到系統環境變量PATH中去:
wuqiong:webrtc_build apple$echo"export PATH=$PWD/depot_tools:$PATH" >$HOME/.bash_profile
然後需要關閉目前終端重新開啟一個來上面設定的環境變量生效.或者在現在終端執行入門指令在目前終端裡加載生效:
wuqiong:webrtc_build apple$source$HOME/.bash_profile
2.3 下載下傳WebRTC的源碼
在我們的編譯工作目錄webrtc_build下建立一個webtrtc子目錄來存放代碼,請執行下面指令:
wuqiong:webrtc_build apple$ mkdirwebrtc wuqiong:webrtc_build apple$cd
webrtc
在上面的檢查工作沒錯之後,我們就需要開始把WebRTC項目的代碼倉庫下載下傳一份到本地來.由于其倉庫之大,大約一共需要下載下傳6G+的東西.是以這一步非常需要有耐心.而且需要有穩定無障礙的網際網路.
執行如下指令然後吧:
wuqiong:webrtc apple$ gclient config--name src http://webrtc.googlecode.com/svn/trunk wuqiong:webrtcapple$echo"target_os = ['ios']" >>.gclient wuqiong:webrtc apple$ gclient sync
--force
FQ快的去喝咖啡,慢的去約妹子吧.辦完事情之後回來如果上面的指令都一切順利,我們就可以往下走去開始編譯了.
(為了友善大家,我已經把webrtc_build目錄打包備份,這樣大家可以省去大量的代碼下載下傳時間.打封包件有5G,正在尋找網盤存放,随後公布.)
2.4 編譯WebRTC.framework
到了這一步,源碼應該已經下載下傳好了.這些源碼可以編譯為好幾個平台,OS X, Linux, Windows, Android,
iOS等.這裡我們隻需要編譯iOS平台的WebRTC,并制作成一個iOS的開發架構.這裡我們不能用Xcode工具,因為這些項目壓根就不支援
XCode.我們需要在終端指令行環境下去搞定這一切!
首先,為了我們裝逼玩黑武器,我們需要在webrtc的項目代碼目錄下建立一個腳本,
這個腳本就是我為了簡化指令的複雜度和提高使用的友善性專門編寫的一個一鍵架構編譯腳本,這個腳本就是今天的核心黑科技了.先建立一個空檔案,然後賦予執行權限:
wuqiong:webrtc apple$ touchbuild_webrtc.sh wuqiong:webrtc apple$ chmod +x
build_webrtc.sh
然後用編輯器打開編輯剛剛建立的腳本檔案,把如下腳本粘貼進去之後儲存并關閉:
1 #!/bin/bash
2 # Script to build WebRTC.framework for iOS
3 # Copyright (C) 2015 戴維營教育 - All Rights Reserved
4 # Last revised 28/1/2015
5 #
6
7 function build_iossim_ia32() {
8 echo "*** building WebRTC for the ia32 iOS simulator";
9 export GYP_GENERATORS="ninja";
10 export GYP_DEFINES="build_with_libjingle=1 build_with_chromium=0 libjingle_objc=1 OS=ios target_arch=ia32";
11 export GYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGS output_dir=out_ios_ia32";
12 export GYP_CROSSCOMPILE=1;
13 pushd src;
14 gclient runhooks;
15 ninja -C out_ios_ia32/Release-iphonesimulator iossim AppRTCDemo;
16
17 echo "*** creating iOS ia32 libraries";
18 pushd out_ios_ia32/Release-iphonesimulator/;
19 rm -f libapprtc_signaling.a;
20 popd;
21 mkdir -p out_ios_ia32/libs;
22 libtool -static -o out_ios_ia32/libs/libWebRTC-ia32.a out_ios_ia32/Release-iphonesimulator/lib*.a;
23 strip -S -x -o out_ios_ia32/libs/libWebRTC.a -r out_ios_ia32/libs/libWebRTC-ia32.a;
24 rm -f out_ios_ia32/libs/libWebRTC-ia32.a;
25 echo "*** result: $PWD/out_ios_ia32/libs/libWebRTC.a";
26
27 popd;
28 }
29
30 function build_iossim_x86_64() {
31 echo "*** building WebRTC for the x86_64 iOS simulator";
32 export GYP_GENERATORS="ninja";
33 export GYP_DEFINES="build_with_libjingle=1 build_with_chromium=0 libjingle_objc=1 OS=ios target_arch=x64 target_subarch=arm64";
34 export GYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGS output_dir=out_ios_x86_64";
35 export GYP_CROSSCOMPILE=1;
36 pushd src;
37 gclient runhooks;
38 ninja -C out_ios_x86_64/Release-iphonesimulator iossim AppRTCDemo;
39
40 echo "*** creating iOS x86_64 libraries";
41 pushd out_ios_x86_64/Release-iphonesimulator/;
42 rm -f libapprtc_signaling.a;
43 popd;
44 mkdir -p out_ios_x86_64/libs;
45 libtool -static -o out_ios_x86_64/libs/libWebRTC-x86_64.a out_ios_x86_64/Release-iphonesimulator/lib*.a;
46 strip -S -x -o out_ios_x86_64/libs/libWebRTC.a -r out_ios_x86_64/libs/libWebRTC-x86_64.a;
47 echo "*** result: $PWD/out_ios_x86_64/libs/libWebRTC.a";
48
49 popd;
50 }
51
52 function build_iosdevice_armv7() {
53 echo "*** building WebRTC for armv7 iOS devices";
54 export GYP_GENERATORS="ninja";
55 export GYP_DEFINES="build_with_libjingle=1 build_with_chromium=0 libjingle_objc=1 OS=ios target_arch=armv7";
56 export GYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGS output_dir=out_ios_armv7";
57 export GYP_CROSSCOMPILE=1;
58 pushd src;
59 gclient runhooks;
60 ninja -C out_ios_armv7/Release-iphoneos AppRTCDemo;
61
62 echo "*** creating iOS armv7 libraries";
63 pushd out_ios_armv7/Release-iphoneos/;
64 rm -f libapprtc_signaling.a;
65 popd;
66 mkdir -p out_ios_armv7/libs;
67 libtool -static -o out_ios_armv7/libs/libWebRTC-armv7.a out_ios_armv7/Release-iphoneos/lib*.a;
68 strip -S -x -o out_ios_armv7/libs/libWebRTC.a -r out_ios_armv7/libs/libWebRTC-armv7.a;
69 echo "*** result: $PWD/out_ios_armv7/libs/libWebRTC.a";
70
71 popd;
72 }
73
74 function build_iosdevice_arm64() {
75 echo "*** building WebRTC for arm64 iOS devices";
76 export GYP_GENERATORS="ninja";
77 export GYP_DEFINES="build_with_libjingle=1 build_with_chromium=0 libjingle_objc=1 OS=ios target_arch=arm64 target_subarch=arm64";
78 export GYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGS output_dir=out_ios_arm64";
79 export GYP_CROSSCOMPILE=1;
80 pushd src;
81 gclient runhooks;
82 ninja -C out_ios_arm64/Release-iphoneos AppRTCDemo;
83
84 echo "*** creating iOS arm64 libraries";
85 pushd out_ios_arm64/Release-iphoneos/;
86 rm -f libapprtc_signaling.a;
87 popd;
88 mkdir -p out_ios_arm64/libs;
89 libtool -static -o out_ios_arm64/libs/libWebRTC-arm64.a out_ios_arm64/Release-iphoneos/lib*.a;
90 strip -S -x -o out_ios_arm64/libs/libWebRTC.a -r out_ios_arm64/libs/libWebRTC-arm64.a;
91 echo "*** result: $PWD/out_ios_arm64/libs/libWebRTC.a";
92
93 popd;
94 }
95
96 function combine_libs()
97 {
98 echo "*** combining libraries";
99 lipo -create src/out_ios_ia32/libs/libWebRTC.a \
100 src/out_ios_x86_64/libs/libWebRTC.a \
101 src/out_ios_armv7/libs/libWebRTC.a \
102 src/out_ios_arm64/libs/libWebRTC.a \
103 -output libWebRTC.a;
104 echo "The public headers are located in $PWD/src/talk/app/webrtc/objc/public/*.h";
105 }
106
107 function create_framework() {
108 echo "*** creating WebRTC.framework";
109 rm -rf WebRTC.framework;
110 mkdir -p WebRTC.framework/Versions/A/Headers;
111 cp ./src/talk/app/webrtc/objc/public/*.h WebRTC.framework/Versions/A/Headers;
112 cp libWebRTC.a WebRTC.framework/Versions/A/WebRTC;
113
114 pushd WebRTC.framework/Versions;
115 ln -sfh A Current;
116 popd;
117 pushd WebRTC.framework;
118 ln -sfh Versions/Current/Headers Headers;
119 ln -sfh Versions/Current/WebRTC WebRTC;
120 popd;
121 }
122
123 function clean()
124 {
125 echo "*** cleaning";
126 pushd src;
127 rm -rf out_ios_arm64 out_ios_armv7 out_ios_ia32 out_ios_x86_64;
128 popd;
129 echo "*** all cleaned";
130 }
131
132 function update()
133 {
134 gclient sync --force
135 pushd src
136 svn info | grep Revision > ../svn_rev.txt
137 popd
138 }
139
140 function build_all() {
141 build_iossim_ia32 && build_iossim_x86_64 && \
142 build_iosdevice_armv7 && build_iosdevice_arm64 && \
143 combine_libs && create_framework;
144 }
145
146 function run_simulator_ia32() {
147 echo "*** running webrtc appdemo on ia32 iOS simulator";
148 src/out_ios_ia32/Release-iphonesimulator/iossim src/out_ios_ia32/Release-iphonesimulator/AppRTCDemo.app;
149 }
150
151 function run_simulator_x86_64() {
152 echo "*** running webrtc appdemo on x86_64 iOS simulator";
153 src/out_ios_x86_64/Release-iphonesimulator/iossim -d 'iPhone 6' -s '8.1' src/out_ios_x86_64/Release-iphonesimulator/AppRTCDemo.app;
154 }
155
156 function run_on_device_armv7() {
157 echo "*** launching on armv7 iOS device";
158 ideviceinstaller -i src/out_ios_armv7/Release-iphoneos/AppRTCDemo.app;
159 echo "*** launch complete";
160 }
161
162 function run_on_device_arm64() {
163 echo "*** launching on arm64 iOS device";
164 ideviceinstaller -i src/out_ios_arm64/Release-iphoneos/AppRTCDemo.app;
165 echo "*** launch complete";
166 }
167
168 #運作指令行參數中第一個參數所指定的Shell函數
169 [email protected]
這個編譯腳本除了可以編譯WebRTC項目自帶的AppRTCDemo應用外,還可以編譯出WebRTC.framework.
執行如下指令來編譯我們所需要的全部:
wuqiong:webrtc apple$ ./build_webrtc.sh build_all
等上面指令完成之後,我們所需要的WebRTC架構就在目前目錄下了.可以用ls指令檢視之:
wuqiong:webrtc apple$ ls WebRTC.framework build_webrtc.sh libWebRTC.a srcwuqiong:webrtc apple$
第一個WebRTC.framework就是我們需要的架構了! 到此,我們的編譯任務就完成了!不是吧..就這麼簡單?不是說起來超級麻煩嗎?呵呵,裝逼結束.繁瑣的部分已經封裝到了shell腳本裡頭去了.如果有興趣可以去研究一下這個腳本.
2.5 WebRTC.framework的依賴.
如果項目使用了該架構,那麼編譯的時候需要在項目的Build Phases中添加如下庫和架構:
libstdc++.6.dylib
libsqlite3.dylib
libc++.dylib
libicucore.dylib
Security.framework
CFNetwork.framework
GLKit.framework
AudioToolbox.framework
AVFoundation.framework
CoreAudio.framework
CoreMedia.framework
CoreVideo.framework
CoreGraphics.framework
OpenGLES.framework
QuartzCore.framework
重要提示
目前Google官方代碼中在ARMv7平台有VP8視訊編碼的stackoverflow問題。
以iOS為例,建議直接使用CocoaPods上面的東西,名字是libjingle_peerconnection。
使用這個庫裡面的東西并不是很麻煩,但要搞清楚裡面的邏輯卻挺頭大的,因為Google提供了一個例子,AppRTCDemo,裡面由于使用了
很多Google自己的一個架構,把整個Demo搞得劇複雜無比,不過搞清楚原理後,隻需要使用幾個簡單的API就可以實作WebRTC的通信。
WebRTC要工作起來,需要一下幾個方面
1. 雙方建立PeerConnection
2. 一端建立和發出Offer,另一端接收Offer後響應Answer
3. PeerConnection的兩端交換SDP資訊
建立PeerConnection需要ICE資訊,裡面提供的網絡打洞穿牆等路徑資料,
RTCIceServer*iceServer = [[RTCICEServeralloc]initWithURI:[NSURLURLWithString:YOUR_SERVER]username:USERNAME_OR_EMPTY_STRINGpassword:PASSWORD_OR_EMPTY_STRING]];RTCPeerConnectionFactory*pcFactory = [[RTCPeerConnectionFactoryalloc] init];RTCPeerConnection*peerConnection = [pcFactorypeerConnectionWithICEServers:iceServersconstraints:nildelegate:self];
一端建立Offer
RTCMediaConstraints *constraints = [RTCMediaConstraints alloc]initWithMandatoryConstraints: @[ [[RTCPair alloc]initWithKey:@"OfferToReceiveAudio"value:@"true"], [[RTCPair alloc]initWithKey:@"OfferToReceiveVideo"value:@"true"] ] optionalConstraints:nil]; [peerConnection createOfferWithConstraints:constraints];
這之後的動作都是通過peerConnection的delegate來完成的createOffer之後,會觸發didCreateSessionDescription方法,可以在這個方法中來設定localDescription
- (void)peerConnection:(RTCPeerConnection*)peerConnectiondidCreateSessionDescription:(RTCSessionDescription*)sdp error:(NSError*)error {[peerConnection setLocalDescription:sdp] }
localDescription設定成功後,會觸發didSetSessionDescriptionWithError的方法
- (void)peerConnection:(RTCPeerConnection*)peerConnection didSetSessionDescriptionWithError:(NSError *)error{if(peerConnection.signalingState ==RTCSignalingHaveLocalOffer) {// 通過Signaling
Channel發送Offer之類的資訊} }
當另一端收到Offer時,要設定remoteDescription
RTCSessionDescription*remoteDesc=[[RTCSessionDescription alloc]initWithType:@"answer" sdp:sdp]; [peerConnection
setRemoteDescription:remoteDesc];
剩下的一些delegate都是跟ICE的candidate相關的,處理在建立PeerConnection時的P2P連接配接資訊
- (void)peerConnection:(RTCPeerConnection*)peerConnection gotICECandidate:(RTCICECandidate *)candidate {// 獲得Candidate資訊,通過signaling channel發送給另一端}
當通過signaling
channel收到candidate資訊後,添加到peerConnection,讓P2P來處理打洞資訊
RTCICECandidate*candidate= [[RTCICECandidate alloc]initWithMid:SDP_MIDindex:SDP_M_LINE_INDEXsdp:SDP_CANDIDATE]; [self.rtcPeerConnectionaddICECandidate:candidate];
最後一個是媒體資料處理,當peerConnection收到媒體資料時,會觸發另一個方法
- (void)peerConnection:(RTCPeerConnection *)peerConnectionaddedStream:(RTCMediaStream *)stream { //Createa new renderviewwithasizeofyour choice RTCEAGLVideoView*renderView = [[RTCEAGLVideoView alloc]initWithFrame:CGRectMake(100,100)];[stream.videoTracks.lastObjectaddRenderer:self.renderView]; // RTCEAGLVideoView is a subclass ofUIView, so renderView // can be inserted into your view hierarchywhere it suits your application. }
總共這些方法就能夠簡單的讓WebRTC工作起來,但還需要很多别的處理,比如iOS的預設speaker播放聲音,音視訊編解碼,chrome用的v8,iOS用的是H264,還有很多問題要等待一一處理。今天先到這裡後續再更新謝謝大家。
轉載于:https://www.cnblogs.com/hedengyao/p/6700136.html