安卓 webrtc 开启h264 软编解码

本文档详细介绍了如何在Android上配置WebRTC以支持H264软编解码,包括修改ffmpeg_generated.gni文件、增加codec_listparser支持、添加Java和C++文件、修改H264Create函数、更新BUILD.gn文件以及相应Java类。此外,还提供了编译参数和相关源码分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文首发地址 https://h89.cn/archives/6.html
最新更新地址 https://gitee.com/chenjim/chenjimblog
本文基于libmediasoupclient 3.2.0 和 webrtc branch-heads/4147(m84)
本文得熟悉相关基础,参考 文1文2
除了需要加编译参数 rtc_use_h264=true, 还需要以下修改以支持h264软编解码
网络搜索到的有很多复制、粘贴,缺少部分内容的,或者版本环境不匹配,很让人头疼。。。。

1. 修改 ffmpeg_generated.gni 开启 openh264 编解码

安卓平台默认未支持 h264 解码,会显示黑屏
third_party/ffmpeg/ffmpeg_generated.gni 中我们可以开到,默认未支持安卓平台
修改 ffmpeg_generated.gniuse_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当中

2. 增加 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"

3. 增加文件 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();
}

4. 增加文件 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;}
}

5. 增加 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

6. 修改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() {
+#if defined(WEBRTC_USE_H264)
+  RTC_LOG(LS_INFO) << "Creating H264EncoderImpl.";
+  return std::make_unique<H264EncoderImpl>(cricket::VideoCodec("H264"));
+#else
+      RTC_NOTREACHED();
+      return nullptr;
+#endif
+    }
+
std::unique_ptr<H264Encoder> H264Encoder::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::vector<SdpVideoFormat> SupportedH264Codecs();

class RTC_EXPORT H264Encoder : public VideoEncoder {
  public:
+  static std::unique_ptr<H264Encoder> Create();
  static std::unique_ptr<H264Encoder> Create(const cricket::VideoCodec& codec);
  // If H.264 is supported (any implementation).
  static bool IsSupported();

7. 修改 sdk/android/BUILD.gn

将其中 vp8 相关地方复制添加 h264 相关,我的一份修改 diff 如下,若编译有问题或者无效,需仔细核对此处。。。

@@ -45,6 +45,7 @@ if (is_android) {
      ":java_audio_device_module_java",
      ":libjingle_peerconnection_java",
      ":libjingle_peerconnection_metrics_default_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",

8. 修改 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
  public VideoDecoder createDecoder(VideoCodecInfo codecType) {
+    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 {
    List<VideoCodecInfo> codecs = new ArrayList<VideoCodecInfo>();

    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 {
    List<VideoCodecInfo> codecs = new ArrayList<VideoCodecInfo>();

    codecs.add(new VideoCodecInfo("VP8", new HashMap<>()));
+
+    codecs.add(new VideoCodecInfo("H264", new HashMap<>()));
+
    if (LibvpxVp9Encoder.nativeIsSupported()) {
      codecs.add(new VideoCodecInfo("VP9", new HashMap<>()));
    }

9. 编译使用吧,祝好运。。。

本文参考自 webrtc M75支持android安卓H264软编解遇到的一些坑
在其基础补充、完善部分说明和详细修改结果,如有问题欢迎反馈


其它相关文档

<think>嗯,用户想了解如何将WebRTC移植到特定平台或环境中使用,具体需要教程和开发指南。首先,我需要回忆WebRTC的基本结构,它主要用C++写,所以跨平台移植通常涉及译和适配不同系统的API。接下来,用户可能需要步骤化的指导,比如环境准备、代码获取、构建配置、平台适配、功能测试等。 根据提供的引用内容,用户提到的WebRTC_VAD项目使用了CMake,这可能意味着CMake是构建管理的关键工具。引用1提到安装和配置指南,可能需要指导用户如何配置构建系统。引用2和3涉及将WebRTC移植到Windows和Android的经验,这可能作为案例参考。 我需要分步骤说明,首先介绍通用移植流程,然后举例具体平台如Android和Windows,参考引用中的案例。要注意用户可能需要处理平台相关的依赖,比如Android的JNI接口或Windows的API调用。此外,译工具链的选择也很重要,比如使用GN和Ninja,或者CMake。 另外,用户可能需要优化和调试的建议,比如日志模块和性能优化,这部分需要结合常见问题和解决方案。最后,生成相关问题,帮助用户深入探索,比如如何优化性能或处理特定依赖。 需要确保回答结构清晰,分步骤,结合引用中的示例,并自然插入引用标记。同时,避免使用Markdown,保持口语化但专业。</think>以下是将WebRTC移植到特定平台/环境的开发指南,包含关键步骤和技术要点: ### 一、WebRTC移植基础流程 1. **环境准备** - 安装必要工具链:GN(生成构建文件)、Ninja(译工具)、Python(脚本支持) - 配置平台SDK(如Android NDK、Windows SDK等) - 下载WebRTC源码(建议使用官方仓库同步): ```bash fetch --nohooks webrtc gclient sync ``` 2. **构建系统配置** - 通过GN生成平台专属构建文件: ```bash gn gen out/Android --args='target_os="android" target_cpu="arm64"' ``` - 支持跨平台参数包括: - `target_os`(android/win/linux等) - `rtc_use_h264`(编解码器开关) - `rtc_enable_protobuf`(协议支持) 3. **平台适配层开发** - 实现`rtc_base/platform_thread.h`中的线程接口 - 重写`rtc_base/physical_socket_server.cc`网络层 - 适配硬件加速接口(如Android的MediaCodec) ### 二、Android平台移植示例(引用[3]) 1. **JNI接口封装** ```java public class WebRTCBridge { static { System.loadLibrary("webrtc_jni"); } public native void createPeerConnection(); } ``` 2. **Gradle配置要点 ```gradle android { externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" } } } ``` ### 三、Windows平台移植要点(引用[2]) 1. COM组件适配 - 实现`webrtc::WinVideoCapture`模块 - DirectShow滤镜链集成 2. 音频子系统重写 ```cpp class WindowsAudioDevice : public webrtc::AudioDeviceModule { int32_t InitSpeaker() override { // 调用Windows Core Audio API } }; ``` ### 四、关键调试技术 1. 日志系统配置 ```cpp rtc::LogMessage::LogToDebug(rtc::LS_VERBOSE); ``` 2. 单元测试接入 ```bash ninja -C out/Release rtc_unittests ``` ### 五、优化建议 - 使用`RTC_DCHECK`进行运行时验证 - 开启LTO(链接时优化)减小二进制体积 - 定制化译参数排除不需要的模块
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清霜辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值