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