安卓 webrtc 开启 h264 软编解码
@[toc]
安卓 webrtc 开启 h264 软编解码
本文首发地址 https://blog.csdn.net/CSqingchen/article/details/120199702
最新更新地址 https://gitee.com/chenjim/chenjimblog
本文基于libmediasoupclient 3.2.0 和 webrtc branch-heads/4147(m84)
本文得熟悉相关基础,参考 文1 和 文2
除了需要加编译参数rtc_use_h264=true
, 还需要以下修改以支持h264软编解码
网络搜索到的有很多复制、粘贴,缺少部分内容的,或者版本环境不匹配,很让人头疼。。。。
- 修改 ffmpeg_generated.gni 开启 openh264 编解码
安卓平台默认未支持 h264 解码,会显示黑屏
从third_party/ffmpeg/ffmpeg_generated.gni
中我们可以开到,默认未支持安卓平台
修改ffmpeg_generated.gni
中use_linux_config
,添加|| is_android
以支持,结果如下use_linux_config = is_linux || is_fuchsia || is_android
参考自 https://www.codeleading.com/article/3215969775
而对于软编解码,android webrtc采用openh264 +ffmpeg,这两块的代码都在webrtc源码src/third_party当中 - 增加 codec_list parser_list h264 支持
third_party/ffmpeg/chromium/config/Chrome/android/arm64/libavcodec/parser_list.c
中添加&ff_h264_parser,
third_party/ffmpeg/chromium/config/Chrome/android/arm64/libavcodec/codec_list.c
中添加&ff_h264_decoder,
third_party/ffmpeg/chromium/config/
下有Chrome ChromeOS Chromium
,这里用的是Chrome
,(其它可能有问题。。。)
需要在编译参数添加ffmpeg_branding="Chrome"
这里路径android/arm64
是需要配合参数--arch "arm64-v8a"
,
如果是armeabi-v7a
需要同步修改目录android/arm-neon/libavcodec
下内容,
最终编译参数参考:./tools_webrtc/android/build_aar.py --extra-gn-args 'rtc_use_h264=true ffmpeg_branding="Chrome" rtc_enable_protobuf=false use_rtti=true use_custom_libcxx=false' --arch "arm64-v8a"
增加文件 LibH264Decoder.java
复制sdk/android/api/org/webrtc/LibvpxVp8Decoder.java
为同目录LibH264Decoder.java
,修改后如下:package org.webrtc; public class LibH264Decoder extends WrappedNativeVideoDecoder { @Override public long createNativeVideoDecoder() { return nativeCreateDecoder(); } static native long nativeCreateDecoder(); }
增加文件 LibH264Encoder.java
复制sdk/android/api/org/webrtc/LibvpxVp8Encoder.java
为同目录LibH264Encoder.java
,修改后如下:package org.webrtc; public class LibH264Encoder extends WrappedNativeVideoEncoder { @Override public long createNativeVideoEncoder() { return nativeCreateEncoder(); } static native long nativeCreateEncoder(); @Override public boolean isHardwareEncoder() {return false;} }
增加 h264_codec.cc
复制sdk/android/src/jni/vp8_codec.cc
为同目录h264_codec.cc
,修改后如下:#include <jni.h> #include "modules/video_coding/codecs/h264/include/h264.h" #include "sdk/android/generated_libH264_jni/LibH264Decoder_jni.h" #include "sdk/android/generated_libH264_jni/LibH264Encoder_jni.h" #include "sdk/android/src/jni/jni_helpers.h" namespace webrtc { namespace jni { static jlong JNI_LibH264Encoder_CreateEncoder(JNIEnv* jni) { return jlongFromPointer(H264Encoder::Create().release()); } static jlong JNI_LibH264Decoder_CreateDecoder(JNIEnv* jni) { return jlongFromPointer(H264Decoder::Create().release()); } } // namespace jni } // namespace webrtc
修改H264 Create()
添加上面要用到的H264Encoder::Create()
,修改 diff 如下:--- a/modules/video_coding/codecs/h264/h264.cc +++ b/modules/video_coding/codecs/h264/h264.cc @@ -84,6 +84,16 @@ std::vector<SdpVideoFormat> SupportedH264Codecs() { "0")}; } +std::unique_ptr<H264Encoder> H264Encoder::Create() {
- RTC_LOG(LS_INFO) << "Creating H264EncoderImpl.";
- return std::make_unique
(cricket::VideoCodec("H264"));
+#else - RTC_NOTREACHED();
- return nullptr;
+#endif }
+
std::unique_ptrH264Encoder::Create(
const cricket::VideoCodec& codec) {
RTC_DCHECK(H264Encoder::IsSupported());--- a/modules/video_coding/codecs/h264/include/h264.h
+++ b/modules/video_coding/codecs/h264/include/h264.h
@@ -43,6 +43,7 @@ std::vectorSupportedH264Codecs(); class RTC_EXPORT H264Encoder : public VideoEncoder {
public:static std::unique_ptr
Create();
static std::unique_ptrCreate(const cricket::VideoCodec& codec);
// If H.264 is supported (any implementation).
static bool IsSupported();修改
sdk/android/BUILD.gn
将其中 vp8 相关地方复制添加 h264 相关,我的一份修改 diff 如下,若编译有问题或者无效,需仔细核对此处。。。@@ -45,6 +45,7 @@ if (is_android) { ":java_audio_device_module_java", ":libjingle_peerconnection_java",
":libH264_java",
":libvpx_vp8_java", ":libvpx_vp9_java", ":logging_java",
@@ -489,6 +490,20 @@ if (is_android) {
]
}- rtc_android_library("libH264_java") {
- visibility = [ "*" ]
- sources = [
- "api/org/webrtc/LibH264Decoder.java",
- "api/org/webrtc/LibH264Encoder.java",
- ]
- deps = [
- ":base_java",
- ":video_api_java",
- ":video_java",
- "//rtc_base:base_java",
- ]
}
+
rtc_android_library("libvpx_vp9_java") {
visibility = [ "*" ]
sources = [
@@ -512,6 +527,7 @@ if (is_android) {deps = [
":base_java",
":libH264_java",
":libvpx_vp8_java", ":libvpx_vp9_java", ":video_api_java",
@@ -783,6 +799,18 @@ if (current_os == "linux" || is_android) {
]
}- rtc_library("libH264_jni") {
- visibility = [ "*" ]
- allow_poison = [ "software_video_codecs" ]
- sources = [ "src/jni/h264_codec.cc" ]
- deps = [
- ":base_jni",
- ":generated_libH264_jni",
- ":video_jni",
- "../../modules/video_coding:webrtc_h264",
- ]
- }
+
rtc_library("libvpx_vp9_jni") {
visibility = [ "*" ]
allow_poison = [ "software_video_codecs" ]
@@ -799,6 +827,7 @@ if (current_os == "linux" || is_android) {
visibility = [ "*" ]
allow_poison = [ "software_video_codecs" ]
deps = [ ":libH264_jni",
":libvpx_vp8_jni", ":libvpx_vp9_jni",
]
@@ -1203,6 +1232,16 @@ if (current_os == "linux" || is_android) {
jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h"
}- generate_jni("generated_libH264_jni") {
- sources = [
- "api/org/webrtc/LibH264Decoder.java",
- "api/org/webrtc/LibH264Encoder.java",
- ]
+ - namespace = "webrtc::jni"
- jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h"
}
+
generate_jni("generated_libvpx_vp9_jni") {
sources = ["api/org/webrtc/LibvpxVp9Decoder.java",
修改 SoftwareVideoDecoderFacoty.java 和 SoftwareVideoEncoderFacoty.java
需要 分别注册 H.264 并添加创建 codec 的代码, 我的修改 DIFF 如下--- a/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java +++ b/sdk/android/api/org/webrtc/SoftwareVideoDecoderFactory.java @@ -26,6 +26,10 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory { @Nullable @Override
- if (codecType.getName().equalsIgnoreCase("H264")) {
- return new LibH264Decoder();
}
+
if (codecType.getName().equalsIgnoreCase("VP8")) {return new LibvpxVp8Decoder();
}
@@ -45,6 +49,9 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
Listcodecs = new ArrayList (); codecs.add(new VideoCodecInfo("VP8", new HashMap<>()));
+codecs.add(new VideoCodecInfo("H264", new HashMap<>()));
+
if (LibvpxVp9Decoder.nativeIsSupported()) {codecs.add(new VideoCodecInfo("VP9", new HashMap<>()));
}
--- a/sdk/android/api/org/webrtc/SoftwareVideoEncoderFactory.java
+++ b/sdk/android/api/org/webrtc/SoftwareVideoEncoderFactory.java
@@ -19,6 +19,9 @@ public class SoftwareVideoEncoderFactory implements VideoEncoderFactory {
@Nullable
@Override
public VideoEncoder createEncoder(VideoCodecInfo info) {- if (info.name.equalsIgnoreCase("H264")) {
- return new LibH264Encoder();
}
if (info.name.equalsIgnoreCase("VP8")) {return new LibvpxVp8Encoder();
}
@@ -38,6 +41,9 @@ public class SoftwareVideoEncoderFactory implements VideoEncoderFactory {
Listcodecs = new ArrayList (); codecs.add(new VideoCodecInfo("VP8", new HashMap<>()));
+codecs.add(new VideoCodecInfo("H264", new HashMap<>()));
+
if (LibvpxVp9Encoder.nativeIsSupported()) {codecs.add(new VideoCodecInfo("VP9", new HashMap<>()));
}
- 编译使用吧,祝好运。。。
本文参考自 webrtc M75支持android安卓H264软编解遇到的一些坑
在其基础补充、完善部分说明和详细修改结果,如有问题欢迎反馈
其它相关文档
- WebRTC on Android: how to enable hardware encoding on multiple devices
https://medium.com/bumble-tech/webrtc-on-android-how-to-enable-hardware-encoding-on-multiple-devices-5bd819c0ce5 - 安卓webrtc在ubuntu 2004下编译使用
https://blog.csdn.net/CSqingchen/article/details/120016697 - Android 断点调试 webrtc、 medieasoup
https://blog.csdn.net/CSqingchen/article/details/120156900 - 安卓增加 mediasoup webrtc 日志输出
https://blog.csdn.net/CSqingchen/article/details/120156669 - 安卓 Mediasoup V3 基于webrtc 分支m84 的编译
https://blog.csdn.net/CSqingchen/article/details/120163087 - 安卓 webrtc 开启h264 软编解码
https://blog.csdn.net/CSqingchen/article/details/120199702 - 安卓mediasoup输出H264流(支持H264编码)
https://blog.csdn.net/CSqingchen/article/details/120218832 - 安卓mediasoup webrtc h264 软编解码相关源码分析
https://blog.csdn.net/CSqingchen/article/details/120218923