WebRTC SDK API封装(4)-WebRTC添加HW/SW H264编解码

背景

WebRTC由于license及其他的一些原因,默认的视频编解码只有使用vp8跟vp9,没有支持h264的编解码,但是我经过一些对比测试(vp9 vs h264)的测试数据发现,vp9的优势在于1080p以上才开始渐渐追上h264的效率,并且目前大多数的视频设备,还是使用h264的比较多,因此要实现对h264的编解码,就必须重新编译WebRTC添加对h264的支持。

实现

通过研究WebRTC的源码发现,对于视频编解码的部分,移动端的使用有两方面需要考虑:

  • 硬件方式编解码
  • 软件方式编解码

1.硬件编解码

WebRTC从r5X版本开始,Android/iOS 平台开始支持HW en/decoder, 查看r67版本WebRTC,其中:

  • Android平台的支持情况分别为:
    • 支持硬编硬解vp8 codec的平台:qcom/Nvidia/Exynos/Intel/MTK
    • 支持硬编硬解vp9 codec的平台:qcom/Exynos
    • 支持硬编硬解h264 codec的平台:qcom/Exynos/Intel/MTK

    Android判断是否支持硬件编解码,是在org.webrtc.HardwareVideoEn/Decoder.java中supportedVP8/VP9/H264HwCodecPrefixes这个字符串数组中定义,可根据需要对手机做机型适配,比如华为的某些手机处理器,CPU本身支持硬件编解码,但是检测不到.

  • iOS处理器只支持h264的硬编硬解。

软件使用的基本逻辑为先去判断自身平台是否支持硬件编解码,如果支持则使用,如果不支持则回退到软件编解码,具体使用上层代码HardwareVideoEn/Decoder.java和RTCVideoEn/DecoderH264.mm分别去实现Android和iOS平台的h264硬件编解码.
在native c/c++代码中的调用方式代码片段如下:

#if defined(WEBRTC_ANDROID)
			webrtc::jni::MediaCodecVideoEncoderFactory* encoder_factory = new webrtc::jni::MediaCodecVideoEncoderFactory();
			video_send_config.rtp.payload_name = "H264";
			video_send_config.rtp.payload_type = kWtkPayloadTypeH264;
			cricket::VideoCodec codec("H264");
			
			webrtc::VideoEncoder* is_encoder_support = encoder_factory->CreateVideoEncoder(codec);
			if(is_encoder_support != nullptr)
			{
				video_send_config.encoder_settings.encoder = is_encoder_support;
				RTC_LOG(LS_INFO) << __FUNCTION__ << " , HW H264 Supported, Use it!";
			}
			else
			{
				video_send_config.encoder_settings.encoder = webrtc::H264Encoder::Create(codec).release();
				RTC_LOG(LS_INFO) << __FUNCTION__ << " , HW H264 Not Supported, roll back to SW H264!";
			}
#elif defined(WEBRTC_IOS)
			video_send_config.rtp.payload_name = "H264";
			video_send_config.rtp.payload_type = kWtkPayloadTypeH264;
			video_send_config.encoder_settings.encoder = webrtc::CreateObjCEncoderFactory()->CreateVideoEncoder(webrtc::SdpVideoFormat("H264")).release();
#endif

具体代码参考我的github下wtkrtc_mediaengine中的代码实现.

2.软件编解码

可参考我在webrtc-discuss中的maillist,具体方法如下:
在WebRTC的源码src/third_party/下,有openh264及ffmpeg的源码,编译默认只支持的配置为
is_linux和is_fuchsia参数,修改方法如下:

  • 首先,修改third_party/ffmpeg/ffmpeg_generated.gni这个文件,改为添加android平台;
#use_linux_config = is_linux || is_fuchsia改为以下
use_linux_config = is_linux || is_fuchsia || is_android
  • 其次,gn创建的工程参数,添加’rtc_use_h264 = true ffmpeg_branding = “Chrome” ',这一步也可通过直接修改out/你的项目名/args.gn文件来完成;
  • 最后,以下两个文件打上补丁支持h264解码:
//以下两个文件
third_party/ffmpeg/chromium/config/Chrome/android/arm-neon/libavcodec/parser_list.c
third_party/ffmpeg/chromium/config/Chrome/android/arm-neon/libavcodec/codec_list.c 
--- a/chromium/config/Chrome/android/arm-neon/libavcodec/parser_list.c
+++ b/chromium/config/Chrome/android/arm-neon/libavcodec/parser_list.c
@@ -4,4 +4,5 @@ static const AVCodecParser * const parser_list[] = {
     &ff_mpegaudio_parser,
     &ff_opus_parser,
     &ff_vorbis_parser,
+    &ff_h264_parser,
     NULL };

--- a/chromium/config/Chrome/android/arm-neon/libavcodec/codec_list.c
+++ b/chromium/config/Chrome/android/arm-neon/libavcodec/codec_list.c
@@ -13,4 +13,5 @@ static const AVCodec * const codec_list[] = {
     &ff_pcm_s32le_decoder,
     &ff_pcm_u8_decoder,
     &ff_libopus_decoder,
+    &ff_h264_decoder,
     NULL };
  • 重新编译
$ninja -c out/你的项目名

CrossWalk

最近在使用Hybird APP的开发模式,采用H5 + 原生的混合模式开发,这样的好处就是不用频繁升级手机端APP,只需服务器前端调整即可实现更新。

最后选用CrossWalk去实现混合开发WebRTC,也是发现默认不支持h264的编解码,有了上面的经验,修改Chromium之后重新编译CrossWalk,感兴趣的请移步这里。

至此,在WebRTC中添加h264编解码的方式已经完成,本人水平一般,能力有限,欢迎大家指正留言交流!

你可能感兴趣的:(VoIP,Media,Engine,webrtc,h264,crosswalk)