WebRTC SDK API封装(4)-WebRTC添加HWSW H264编解码

    xiaoxiao2023-10-19  170

    背景

    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编解码的方式已经完成,本人水平一般,能力有限,欢迎大家指正留言交流!

    最新回复(0)