天天看點

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編解碼的方式已經完成,本人水準一般,能力有限,歡迎大家指正留言交流!

繼續閱讀