基于WebRTC m94 android版本编译 mediasoup-client-android

2,131 阅读7分钟

基于WebRTC m94 android版本编译 mediasoup-client-android

编译webrtc

准备工作

  • 编译环境 Ubuntu 18.04
  • webrtc 需要科学上网,代理一定要稳定!!! 代理一定要稳定!!! 代理一定要稳定!!!
  • 安装 depot_tools(需要用到depot_tools工具来下载webrtc源码)
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
  • 把depot_tools添加到path中去 将depot_tools的路径追加到用户目录的.bashrc文件中 xxx换成你的用户名
export WEBRTC_DEPOT_TOOLS=/home/xxx/webRTC_Source/depot_tools
export PATH=$PATH:$WEBRTC_DEPOT_TOOLS
  • 使变量生效, 命令行执行 source ~/.bashrc

下载源码

mkdir webrtc_android
cd webrtc_android
fetch --nohooks webrtc_android
gclient sync

如果fetch --nohooks webrtc_android 执行失败 直接执行gclient sync即可

  • 切换到稳定分支 我切换到m94分支
cd src
git checkout -b m94 branch-heads/4606
/*同步代码*/
cd ..
gclient sync --nohooks
gclient runhooks

如果有执行失败,gclient sync --nohooks、gclient runhooks 哪个失败,重新执行哪个

  • 安装编译 WebRTC 所需的依赖
cd src
./build/install-build-deps.sh
./build/install-build-deps-android.sh

编译

编译aar
./tools_webrtc/android/build_aar.py  

./tools_webrtc/android/build_aar.py -h : 查看有哪些编译参数

编译libwebrtc.a 和 libwebrtc.jar
  • 默认不会编译 webrtc 模块,我们需要在tools_webrtc/android/build_aar.py 文件中加入 ':webrtc'
   TARGETS = [
    ':webrtc',
    'sdk/android:libwebrtc',
    'sdk/android:libjingle_peerconnection_so',
]
  • 如果需要开启h264,需要添加licenses
  1. 修改 tools_webrtc/libs/generate_licenses.py 如下,添加 LICENSE
    'openh264':['third_party/openh264/src/LICENSE'],
    'ffmpeg':['third_party/ffmpeg/LICENSE.md'],

位置如下

'g722': ['modules/third_party/g722/LICENSE'],
'fft4g': ['common_audio/third_party/fft4g/LICENSE'],
'spl_sqrt_floor': ['common_audio/third_party/spl_sqrt_floor/LICENSE'],
+    'openh264':['third_party/openh264/src/LICENSE'],
+    'ffmpeg':['third_party/ffmpeg/LICENSE.md'],
# TODO(bugs.webrtc.org/1110): Remove this hack. This is not a lib.
  1. 修改 编译ffmpeg 配置项
third_party/ffmpeg/ffmpeg_generated.gni
-use_linux_config = is_linux || is_fuchsia
+use_linux_config = is_linux || is_fuchsia || is_android
 third_party/ffmpeg/chromium/config/Chrome/android/{ABI}/config.h
-#define CONFIG_H264_DECODER 0
+#define CONFIG_H264_DECODER 1
third_party/ffmpeg/chromium/config/Chrome/android/{ABI}/libavcodec/codec_list.c
// 增加 ff_h264_decoder
+    &ff_h264_decoder,
    NULL};
third_party/ffmpeg/chromium/config/Chrome/android/{ABI}/libavcodec/parser_list.c
// 增加 ff_h264_parser
+    &ff_h264_parser,
     NULL};
  1. 修改 编译OpenH264 配置项
modules/video_coding/codecs/h264/include/h264.h
 class RTC_EXPORT H264Encoder : public VideoEncoder {
  public:
+
+  static std::unique_ptr<H264Encoder> Create();
modules/video_coding/codecs/h264/h264.cc

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
+}
增加文件 sdk/android/api/org/webrtc/LibH264Decoder.java
+
+package org.webrtc;
+
+public class LibH264Decoder extends WrappedNativeVideoDecoder {
+  @Override
+  public long createNativeVideoDecoder() {
+    return nativeCreateDecoder();
+  }
+
+  static native long nativeCreateDecoder();
+}
sdk/android/api/org/webrtc/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;
+  }
+}
增加  sdk/android/src/jni/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

SoftwareVideoDecoderFactory.java 添加 LibH264Decoder

public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
   @Nullable
   @Override
   public VideoDecoder createDecoder(VideoCodecInfo codecType) {
+    Logging.d("VideoDecoder", "createDecoder: "+codecType.getName()+" params =  "+codecType.getParams());
+    if(codecType.getName().equalsIgnoreCase("H264")){
+      return new LibH264Decoder();
+    }
     if (codecType.getName().equalsIgnoreCase("VP8")) {
       return new LibvpxVp8Decoder();
     }
@@ -43,7 +47,7 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {

   static VideoCodecInfo[] supportedCodecs() {
     List<VideoCodecInfo> codecs = new ArrayList<VideoCodecInfo>();
-
+    codecs.add(new VideoCodecInfo("H264", H264Utils.getDefaultH264Params(false)));
     codecs.add(new VideoCodecInfo("VP8", new HashMap<>()));
     if (LibvpxVp9Decoder.nativeIsSupported()) {
       codecs.add(new VideoCodecInfo("VP9", new HashMap<>()));

SoftwareVideoEncoderFactory.java 添加 LibH264Encoder

public class SoftwareVideoEncoderFactory implements VideoEncoderFactory {
   @Nullable
   @Override
   public VideoEncoder createEncoder(VideoCodecInfo info) {
+    Logging.d("VideoEncoder", "createEncoder: "+info.getName()+" params =  "+info.getParams());
+    if (info.name.equalsIgnoreCase("H264")) {
+      return new LibH264Encoder();
+    }
     if (info.name.equalsIgnoreCase("VP8")) {
       return new LibvpxVp8Encoder();
     }
@@ -36,7 +40,7 @@ public class SoftwareVideoEncoderFactory implements VideoEncoderFactory {

   static VideoCodecInfo[] supportedCodecs() {
     List<VideoCodecInfo> codecs = new ArrayList<VideoCodecInfo>();
-
+    codecs.add(new VideoCodecInfo("H264",  H264Utils.getDefaultH264Params(false)));
     codecs.add(new VideoCodecInfo("VP8", new HashMap<>()));
     if (LibvpxVp9Encoder.nativeIsSupported()) {
       codecs.add(new VideoCodecInfo("VP9", new HashMap<>()));
sdk/android/BUILD.gn
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -46,6 +46,7 @@ if (is_android) {
       ":libjingle_peerconnection_java",
       ":libjingle_peerconnection_metrics_default_java",
       ":libvpx_vp8_java",
+      ":libH264_java",
       ":libvpx_vp9_java",
       ":logging_java",
       ":peerconnection_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",
+       ":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"
+   }
+
  1. 如果需要支持h264 simulcast 分辨率不支持 需要修改文件 modules/video_coding/utility/simulcast_utility.cc
bool SimulcastUtility::ValidSimulcastParameters(const VideoCodec& codec,
   } else {
     // TODO(mirtad): H264 encoder implementation still assumes the default
     // resolution downscaling is used.
-    for (int i = 1; i < num_streams; ++i) {
-      if (codec.simulcastStream[i].width !=
-          codec.simulcastStream[i - 1].width * 2) {
-        return false;
-      }
-    }
+//    for (int i = 1; i < num_streams; ++i) {
+//      if (codec.simulcastStream[i].width !=
+//          codec.simulcastStream[i - 1].width * 2) {
+//        return false;
+//      }
+//    }
   }
  • 编译命令
./tools_webrtc/android/build_aar.py --extra-gn-args 'is_debug=false is_component_build=false is_clang=true rtc_include_tests=false rtc_use_h264 = true ffmpeg_branding = "Chrome" rtc_enable_protobuf=false use_rtti=true use_custom_libcxx=false' --build-dir ./out/release-build/m94/
  • 可能会遇到的问题
ModuleNotFoundError: No module named 'dataclasses'

缺少python依赖

//python2
  sudo apt install python-pip
  pip install dataclasses

//python3
  sudo apt install python3-pip
  pip3 install dataclasses
  • 输出路径
 out/release-build/m94/armeabi-v7a/obj/libwebrtc.a
 out/release-build/m94/armeabi-v7a/lib.java/sdk/android/libwebrtc.jar

至此WebRTC编译完成,拷贝出libwebrtc.a libwebrtc.jar 备用


编译mediasoup

下载

mediasoup-client-android m94 编译 下载地址

git clone https://github.com/haiyangwu/mediasoup-client-android.git
git checkout -b 340 3.4.0-beta

编译

将编译好的 各个abi的libwebrtc.a 和libwebrtc.jar 导入mediasoup-client-android的 mediasoup-client/deps/webrtc/lib 目录中替换 用Android Studio 打开, 开始编译吧。。。


mediasoup 320版本编译

WebRTC m84编译

libmediasoupclient 对应的WebRTC版本是 branch-heads/4147

cd src
git checkout -b m84 branch-heads/4147 
/*同步代码*/
cd ..
gclient sync --nohooks
gclient runhooks

编译和m94版本类似

libmediasoupclient编译

  • 下载libmediasoupclient
  • 切换分支 320
git clone https://github.com/versatica/libmediasoupclient
git checkout -b 320 3.2.0

mediasoup-client-android m84 编译 下载地址

 git clone https://github.com/haiyangwu/mediasoup-client-android.git
 git checkout -b 320 59315929fb2be499c474dd21a4e95b6b69116d80
  1. 将下载好的libmediasoupclient 320分支拷贝到mediasoup-client-android/mediasoup-client/deps目录下
  2. 删除SendTransport::ProduceData 相关的方法
  3. 将webrtc 84分支的头文件导入到mediasoup-client-android/mediasoup-client/deps/webrtc/src目录下 可以从webrtc源码中导出
cd ~/webrtc/android/src
mkdir -p ~/m84/include/third_party/
cp -r       api/                    ~/m84/include/
cp -r       audio/                    ~/m84/include/
cp -r       base/                    ~/m84/include/
cp -r       build_overrides/                    ~/m84/include/
cp -r       call/                    ~/m84/include/
cp -r       common_audio/                    ~/m84/include/
cp -r       common_video/                    ~/m84/include/
cp -r       logging/                    ~/m84/include/
cp -r       media/                    ~/m84/include/
cp -r       modules/                    ~/m84/include/
cp -r       p2p/                    ~/m84/include/
cp -r       pc/                    ~/m84/include/
cp -r       rtc_base/                    ~/m84/include/
cp -r       rtc_tools/                    ~/m84/include/
cp -r       sdk/                    ~/m84/include/
cp -r       stats/                    ~/m84/include/
cp -r       style-guide/                    ~/m84/include/
cp -r       system_wrappers/                    ~/m84/include/
cp -r       test/                    ~/m84/include/
cp -r       third_party/abseil-cpp/     ~/m84/include/third_party/
cp -r       tools_webrtc/                    ~/m84/include/
cp -r       video/                    ~/m84/include/
cp .clang-format  ~/m84/include/
cp .git-blame-ignore-revs  ~/m84/include/
cp .gitignore  ~/m84/include/
cp .vpython  ~/m84/include/
cp abseil-in-webrtc.md  ~/m84/include/
cp AUTHORS  ~/m84/include/
cp BUILD.gn  ~/m84/include/
cp codereview.settings  ~/m84/include/
cp CODE_OF_CONDUCT.md  ~/m84/include/
cp common_types.h  ~/m84/include/
cp DEPS  ~/m84/include/
cp ENG_REVIEW_OWNERS  ~/m84/include/
cp LICENSE  ~/m84/include/
cp license_template.txt  ~/m84/include/
cp native-api.md  ~/m84/include/
cp OWNERS  ~/m84/include/
cp PATENTS  ~/m84/include/
cp PRESUBMIT.py  ~/m84/include/
cp presubmit_test.py  ~/m84/include/
cp presubmit_test_mocks.py  ~/m84/include/
cp pylintrc  ~/m84/include/
cp README.chromium  ~/m84/include/
cp README.md  ~/m84/include/
cp style-guide.md  ~/m84/include/
cp WATCHLISTS  ~/m84/include/
cp webrtc.gni  ~/m84/include/
cp whitespace.txt  ~/m84/include/

用Android Studio 打开, 开始编译吧。。。

参考文档