webrtc發(fā)送端-Android編碼器創(chuàng)建

github:https://github.com/bigonelby/webrtcUml/tree/master/latest

webrtc-發(fā)送端-Android編碼器創(chuàng)建.drawio.png
  1. 這張圖介紹了Android編碼器的創(chuàng)建過程

  2. 前面已經(jīng)介紹過iOS編碼器的創(chuàng)建過程,Android編碼器的創(chuàng)建過程比iOS編碼器創(chuàng)建過程類似,也是從native層,轉(zhuǎn)到j(luò)ava層,再從java層回到native層。但是Android上有兩點(diǎn)比iOS要復(fù)雜些:其一就是Android上支持軟編碼fallback;其二就是Android編碼器支持純java層和java native wrapper兩種

  3. 首先還是從應(yīng)用設(shè)置給底層的factory說起。通過PeerConnectionFactory傳入這些factory,當(dāng)然,傳入的都是java層的。即Java層的VideoEncoderFactory。具體的實(shí)現(xiàn)類是DefaultVideoEncoderFactory。這個(gè)稍后再說。不過對(duì)于底層而言,最終還需要一個(gè)native層的VideoEncoderFactory,這樣,當(dāng)然就需要一個(gè)轉(zhuǎn)換類了,這個(gè)轉(zhuǎn)換類本身是native層的,并且繼承了VideoEncoderFactory,但真正的創(chuàng)建工作,是通過jni調(diào)用java層的VideoEncoderFactory完成的。完成這個(gè)工作的轉(zhuǎn)換類就是VideoEncoderFactoryWrapper

  4. 目前,我們知道了,上層傳入的是java層的VideoEncoderFactory,webrtc進(jìn)行了內(nèi)部處理,即創(chuàng)建了native層的VideoEncoderFactoryWrapper,當(dāng)需要?jiǎng)?chuàng)建編碼器時(shí),通過java層的VideoEncoderFactory創(chuàng)建

  5. 下面看看java層的編碼器。本身VideoEncoderFactory工廠類創(chuàng)建編碼器VideoEncoder是很正常的。不過Android的編碼器是支持fallback的,這就涉及到了三個(gè)編碼器,其一是支持fallback的編碼器;其二是硬編碼器;其三是軟編碼器。對(duì)應(yīng)的java層的類分別為:VideoEncoderFallback,HardwareVideoEncoder和H264Encoder。他們的關(guān)系是VideoEncoderFallback持有兩個(gè)編碼器,primary和fallback。優(yōu)先采用primary編碼器進(jìn)行編碼,即HardwareVideoEncoder。當(dāng)編碼出錯(cuò)超過一定閾值時(shí),啟動(dòng)fallback編碼器并通過fallback編碼器進(jìn)行編碼,這里的fallback編碼器就是H264Encoder。java層既然有三個(gè)編碼器,當(dāng)然也就對(duì)應(yīng)了三個(gè)編碼器的工廠類,分別為:DefaultVideoEncoderFactory,將會(huì)創(chuàng)建VideoEncoderFallback;HardwareVideoEncoderFactory,將會(huì)創(chuàng)建HardwareVideoEncoder;以及SoftwareVideoEncoderFactory,將會(huì)創(chuàng)建H264Encoder。不難猜測(cè),DefaultVideoEncoderFactory持有了HardwareVideoEncoderFactory和SoftwareVideoEncoderFactory這兩個(gè)工廠。當(dāng)通過DefaultVideoEncoderFactory創(chuàng)建編碼器時(shí),首先通過HardwareVideoEncoderFactory創(chuàng)建出HardwareVideoEncoder;接著通過SoftwareVideoEncoderFactory創(chuàng)建H264Encoder;最后創(chuàng)建出VideoEncoderFallback并將創(chuàng)建好的軟硬編碼器作為參數(shù)傳入構(gòu)造函數(shù)。

  6. 接著說說編碼器,Android中的編碼器分為硬編碼器,比如HardwareVideoEncoder,和WrappedNativeVideoEncoder兩種。怎么理解呢?這里有個(gè)非常重要的技巧就是createNativeVideoEncoder這個(gè)方法是如何實(shí)現(xiàn)的。對(duì)于HardwareVideoEncoder而言,這個(gè)是硬編碼器,根正苗紅,直接和MediaCodec打交道,并不需要native層的配合,這點(diǎn)事他自己干就完全可以了。另一種,WrappedNativeVideoEncoder則是一個(gè)名副其實(shí)的傀儡了,他自己本身完不成任何編碼的能力。這個(gè)類實(shí)現(xiàn)了VideoEncoder接口的若干方法,但是實(shí)現(xiàn)的方式都是拋出異常,也就是說,別人可別調(diào)用我的這些方法,這些方法我都搞不定。那么真正干活的是誰呢?是native層的encoder,每個(gè)WrappedNativeVideoEncoder都可以創(chuàng)建出自己的nativeEncoder,通過接口createNativeVideoEncoder來完成。創(chuàng)建出的encoder,繼承了底層的VideoEncoder,并且可以獨(dú)立完成所有的編碼工作,換言之,不需要通過jni接口反調(diào)用java層的接口,不需要java層的任何輔助。對(duì)于HardwareVideoEncoder這種不屬于WrappedNativeVideoEncoder而言,雖然可以獨(dú)立完成編碼工作,但畢竟所有pipeline都是底層驅(qū)動(dòng)的,因此還需要一個(gè)native層的轉(zhuǎn)換類VideoEncoderWrapper來完成這個(gè)適配的過程,VideoEncoderWrapper本身繼承自VideoEncoder,并且所有的接口實(shí)現(xiàn),都是通過jni反調(diào)上層java層的HardwareVideoEncoder完成。小結(jié)一下,Android的編碼器分為純java編碼器(硬編碼器)和native wrapped編碼器,對(duì)于硬編碼器而言,native層有轉(zhuǎn)換類VideoEncoderWrapper繼承自VideoEncoder并通過jni回調(diào)到j(luò)ava層,核心工作在java層完成;對(duì)于native wrapped編碼器,則java層不做任何工作,創(chuàng)建出的native encoder繼承了VideoEncoder,并進(jìn)行相應(yīng)的工作

  7. 明白了編碼器的這兩種分類,java層的編碼器可以轉(zhuǎn)換為native層的編碼器了,這是我們想要的。對(duì)于硬編碼器,其對(duì)應(yīng)的native層的編碼器就是VideoEncoderWrapper;對(duì)于軟編碼器這種native wrapped編碼器,通過createNativeVideoEncoder方法創(chuàng)建native層所對(duì)應(yīng)的編碼器,這個(gè)編碼器就是我們需要的native的編碼器。如何判斷一個(gè)java層的編碼器是純java層的,還是native wrapped的呢?就是通過接口createNativeVideoEncoder方法的返回值!如果返回值為0,則代表不需要native encoder,則為純java層encoder;如果返回值非0,則為native wrapper encoder

  8. 饒了一大圈,我們梳理一下整個(gè)pipeline,上層傳下來的VideoEncoderFactory,將被底層包裝為native層的VideoEncoderFactoryWrapper。底層創(chuàng)建編碼器時(shí),將用這個(gè)factory的CreateVideoEncoder方法創(chuàng)建native層的encoder。首先通過保存的java層的factory,即DefaultVideoEncoderFactory,創(chuàng)建出java層的encoder,即VideoEncoderFallback,再將java層的encoder轉(zhuǎn)換為native層的encoder,具體的方法是,由于VideoEncoderFallback為WrappedNativeVideoEncoder,因此直接通過其createNativeVideoEncoder方法,直接創(chuàng)建出native的encoder即可

  9. 最后再簡(jiǎn)單的說一下fallback。java層的VideoEncoderFallback所創(chuàng)建出的native層的編碼器為VideoEncoderSoftwareFallbackWrapper,這個(gè)編碼器的特殊之處在于他同時(shí)擁有硬編碼器和軟編碼器兩個(gè)編碼器,這兩個(gè)編碼器都是通過java層的編碼器轉(zhuǎn)換而來,具體的轉(zhuǎn)換方法參見上述的7。首先通過硬編碼器進(jìn)行編碼,如果在編碼過程中出錯(cuò)超過一定閾值,則會(huì)初始化軟編碼器,交由軟編碼器編碼,這就實(shí)現(xiàn)了fallback的過程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容