webrtc发送端-Android编码器创建

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

webrtc-发送端-Android编码器创建.drawio.png
  1. 这张图介绍了Android编码器的创建过程

  2. 前面已经介绍过iOS编码器的创建过程,Android编码器的创建过程比iOS编码器创建过程类似,也是从native层,转到java层,再从java层回到native层。但是Android上有两点比iOS要复杂些:其一就是Android上支持软编码fallback;其二就是Android编码器支持纯java层和java native wrapper两种

  3. 首先还是从应用设置给底层的factory说起。通过PeerConnectionFactory传入这些factory,当然,传入的都是java层的。即Java层的VideoEncoderFactory。具体的实现类是DefaultVideoEncoderFactory。这个稍后再说。不过对于底层而言,最终还需要一个native层的VideoEncoderFactory,这样,当然就需要一个转换类了,这个转换类本身是native层的,并且继承了VideoEncoderFactory,但真正的创建工作,是通过jni调用java层的VideoEncoderFactory完成的。完成这个工作的转换类就是VideoEncoderFactoryWrapper

  4. 目前,我们知道了,上层传入的是java层的VideoEncoderFactory,webrtc进行了内部处理,即创建了native层的VideoEncoderFactoryWrapper,当需要创建编码器时,通过java层的VideoEncoderFactory创建

  5. 下面看看java层的编码器。本身VideoEncoderFactory工厂类创建编码器VideoEncoder是很正常的。不过Android的编码器是支持fallback的,这就涉及到了三个编码器,其一是支持fallback的编码器;其二是硬编码器;其三是软编码器。对应的java层的类分别为:VideoEncoderFallback,HardwareVideoEncoder和H264Encoder。他们的关系是VideoEncoderFallback持有两个编码器,primary和fallback。优先采用primary编码器进行编码,即HardwareVideoEncoder。当编码出错超过一定阈值时,启动fallback编码器并通过fallback编码器进行编码,这里的fallback编码器就是H264Encoder。java层既然有三个编码器,当然也就对应了三个编码器的工厂类,分别为:DefaultVideoEncoderFactory,将会创建VideoEncoderFallback;HardwareVideoEncoderFactory,将会创建HardwareVideoEncoder;以及SoftwareVideoEncoderFactory,将会创建H264Encoder。不难猜测,DefaultVideoEncoderFactory持有了HardwareVideoEncoderFactory和SoftwareVideoEncoderFactory这两个工厂。当通过DefaultVideoEncoderFactory创建编码器时,首先通过HardwareVideoEncoderFactory创建出HardwareVideoEncoder;接着通过SoftwareVideoEncoderFactory创建H264Encoder;最后创建出VideoEncoderFallback并将创建好的软硬编码器作为参数传入构造函数。

  6. 接着说说编码器,Android中的编码器分为硬编码器,比如HardwareVideoEncoder,和WrappedNativeVideoEncoder两种。怎么理解呢?这里有个非常重要的技巧就是createNativeVideoEncoder这个方法是如何实现的。对于HardwareVideoEncoder而言,这个是硬编码器,根正苗红,直接和MediaCodec打交道,并不需要native层的配合,这点事他自己干就完全可以了。另一种,WrappedNativeVideoEncoder则是一个名副其实的傀儡了,他自己本身完不成任何编码的能力。这个类实现了VideoEncoder接口的若干方法,但是实现的方式都是抛出异常,也就是说,别人可别调用我的这些方法,这些方法我都搞不定。那么真正干活的是谁呢?是native层的encoder,每个WrappedNativeVideoEncoder都可以创建出自己的nativeEncoder,通过接口createNativeVideoEncoder来完成。创建出的encoder,继承了底层的VideoEncoder,并且可以独立完成所有的编码工作,换言之,不需要通过jni接口反调用java层的接口,不需要java层的任何辅助。对于HardwareVideoEncoder这种不属于WrappedNativeVideoEncoder而言,虽然可以独立完成编码工作,但毕竟所有pipeline都是底层驱动的,因此还需要一个native层的转换类VideoEncoderWrapper来完成这个适配的过程,VideoEncoderWrapper本身继承自VideoEncoder,并且所有的接口实现,都是通过jni反调上层java层的HardwareVideoEncoder完成。小结一下,Android的编码器分为纯java编码器(硬编码器)和native wrapped编码器,对于硬编码器而言,native层有转换类VideoEncoderWrapper继承自VideoEncoder并通过jni回调到java层,核心工作在java层完成;对于native wrapped编码器,则java层不做任何工作,创建出的native encoder继承了VideoEncoder,并进行相应的工作

  7. 明白了编码器的这两种分类,java层的编码器可以转换为native层的编码器了,这是我们想要的。对于硬编码器,其对应的native层的编码器就是VideoEncoderWrapper;对于软编码器这种native wrapped编码器,通过createNativeVideoEncoder方法创建native层所对应的编码器,这个编码器就是我们需要的native的编码器。如何判断一个java层的编码器是纯java层的,还是native wrapped的呢?就是通过接口createNativeVideoEncoder方法的返回值!如果返回值为0,则代表不需要native encoder,则为纯java层encoder;如果返回值非0,则为native wrapper encoder

  8. 饶了一大圈,我们梳理一下整个pipeline,上层传下来的VideoEncoderFactory,将被底层包装为native层的VideoEncoderFactoryWrapper。底层创建编码器时,将用这个factory的CreateVideoEncoder方法创建native层的encoder。首先通过保存的java层的factory,即DefaultVideoEncoderFactory,创建出java层的encoder,即VideoEncoderFallback,再将java层的encoder转换为native层的encoder,具体的方法是,由于VideoEncoderFallback为WrappedNativeVideoEncoder,因此直接通过其createNativeVideoEncoder方法,直接创建出native的encoder即可

  9. 最后再简单的说一下fallback。java层的VideoEncoderFallback所创建出的native层的编码器为VideoEncoderSoftwareFallbackWrapper,这个编码器的特殊之处在于他同时拥有硬编码器和软编码器两个编码器,这两个编码器都是通过java层的编码器转换而来,具体的转换方法参见上述的7。首先通过硬编码器进行编码,如果在编码过程中出错超过一定阈值,则会初始化软编码器,交由软编码器编码,这就实现了fallback的过程

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容