为 WebRTC Android (M70) 添加 H.264 编解码
文章目录
作为 Google 的 p2p 音视频方案,WebRTC 在很长时间里都会优先选择同样是 Google 自家的 VP8/VP9 作为编解码方案。但是不可否认,H.264 才是现在业界里更加主流的方案。所以在最近的几个版本中,WebRTC 也开始逐渐将 H.264 添加到默认的编解码方案中来了。
Android 上 WebRTC 只针对少量的设备提供了硬编解的支持,而软解则是完全不支持。幸运的是,WebRTC 使用 openH264 来实现软编码,FFmpeg 实现软解码,而这两部分代码都包含在了 src/third_party
中,我们只需要修改部分代码及编译的脚本就可以把这部分能力集成进来了。
针对 Android 平台,我们要完整的支持 H.264 的编解码,需要完成这些目标:
- 完善硬编解列表
- FFmpeg 开启 H.264 软解
- WebRTC 开启 H.264 软编解
本文基于 M70 版本
完善硬编解列表
不同于早期的版本,M70 移除了默认的编解码,必须在创建 PeerConnectionFactory
的时候显式的传入 VideoDecoderFactory
和 VideoEncoderFactory
,通常来说,可以按照官方的 PSA 配置默认的工厂类。
配置硬编(解)码的代码在 sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java
和 sdk/android/api/org/webrtc/HardwareVideoDecoderFactory.java
中。两个类对于编(解)码实例创建的逻辑是相似的,都需要先根据 MediaCodecInfo
和 VideoCodecType
判断当前设备是否支持。仅以 HardwareVideoEncoderFactory
为例:
op1=>operation: HardwareVideoEncoderFactory::createEncoder
op2=>operation: HardwareVideoEncoderFactory::findCodecForType
op3=>operation: HardwareVideoEncoderFactory::isSupportedCodec
op4=>operation: HardwareVideoEncoderFactory::isHardwareSupportedInCurrentSdk
op5=>operation: HardwareVideoEncoderFactory::isHardwareSupportedInCurrentSdkH264
op1->op2->op3->op4->op5
默认只支持 OMX.qcom.
和 OMX.Exynos.
,可以根据业务需求把 OMX.hisi.
、OMX.MTK.
添加进来,当然也可以根据黑名单排除一些设备。
FFmpeg 开启 H.264 软解
为 FFmpeg 开启 H.264 的编译选项,需要修改 third_party/ffmpeg
下的脚本。
third_party/ffmpeg/ffmpeg_generated.gni
将 h264 相关的源码添加到 ffmpeg_c_sources 中- 修改
third_party/ffmpeg/chromium/config/Chromium/{ABI}/config.h
中#define CONFIG_H264_DECODER
的宏定义 - 由于 FFmpeg 废弃了
av_register_all
,所以需要静态的注册 H.264。third_party/ffmpeg/chromium/config/Chromium/android/{ABI}/libavcodec/parser_list.c
和third_party/ffmpeg/chromium/config/Chromium/android/{ABI}/libavcodec/codec_list.c
分别添加 h264 的 parser 和 decoder
WebRTC 开启 H.264 软编解
尽管我们已经将 H.264 的软解添加到 FFmpeg 中了,但是 WebRTC 还是没有调用到这些代码。这里我们可以参考源码中对于 VP9 的处理,依样画葫芦。
- 参照
sdk/android/src/java/org/webrtc/VP9Decoder.java
和sdk/android/src/java/org/webrtc/VP9Encoder.java
实现 H.264 的 Java 层 Wrapper - 参照
sdk/android/jni/vp9codec.cc
实现 H.264 的 native 代码 sdk/android/BUILD.gn
中分别添加generate_jni
和rtc_static_library
任务,并添加对应的 java 和 cpp 文件- 在
sdk/android/api/org/webrtc/SoftwareVideoDecoderFacoty.java
和sdk/android/api/org/webrtc/SoftwareVideoEncoderFacoty.java
中分别注册 H.264 并添加创建 codec 的代码
注:WebRTC Android JNI 接口的 C 层函数定义,都是通过 Python 脚本 base/android/jni_generator/jni_generator.py
生成的,生成的代码在 out/{destination}/gen/sdk/android/generated_xxx_jni/jni
目录下。我们需要通过第3步生成 H.264 的 JNI 函数,并在第四步中引用生成的头文件。
另注:我们在将 H.264 的软编(解)码添加到工厂类里时,需要传入一个 Map
作为参数。sdk/android/src/java/org/webrtc/H264Utils.java
提供了这些生成参数的方法。这里的参数会影响协商时生成的 SDP,要根据业务实现。
收个尾
编译时,我们需要将 rtc_use_h264
设置为 true。可以在 webrtc.gni
中修改,也可以通过 gn gen
在生成 gn 项目的时候通过 --args
设置。
文章作者 Dio.Ye
上次更新 2019-02-18