More detailed! Android WebRTC Enable H264 soft codec
The codec of Android WebRTC software is based on openH264 and FFMpeg, but it is not enabled by default during compilation. If you want to enable it, you need to add and modify the code. I will list all the modification steps one by one below.
This article is based on
WebRTC version:
Equipment: Mac
Virtual machine: Parallels Desktop + Ubuntu 18.4
start
Change the return value of rTC_USe_h264
Path: webrtc/ SRC /webrtc.gni. Open the file and change rtc_use_h264 to rtc_USe_h264 = true
# rtc_use_h264 = # proprietary_codecs && ! is_android && ! is_ios && ! (is_win && ! is_clang) rtc_use_h264 = trueCopy the code
Two: modify ffMPEG related compilation parameters
Path: webrtc/SRC/third_party/ffmpeg/ffmpeg_generated gni
Here you need to turn on a number of H264 related compiler switches, make sure to watch, otherwise the compiler will report this error ❌
Armv7 + arm64 + armv7 + arm64 + armv7 + arm64 + armv7 + arm64
Line # :
198 #
if((is_mac) | | (is_win) | | (use_linux_config))if ((is_mac) || (is_win) || (use_linux_config) || (is_android))
Copy the code
252 #
if ((is_mac && ffmpeg_branding == "Chrome") || (is_win && ffmpeg_branding == "Chrome") || (use_linux_config && Ffmpeg_branding = = "Chrome") | | (use_linux_config && ffmpeg_branding = = "jump")) to modify the if ((is_mac && ffmpeg_branding == "Chrome") || (is_win && ffmpeg_branding == "Chrome") || (use_linux_config && ffmpeg_branding == "Chrome") || (use_linux_config && ffmpeg_branding == "ChromeOS") || (is_android))Copy the code
295 #
if ((is_mac && current_cpu == "x64") || (is_win && current_cpu == "x64") || (is_win && current_cpu == "x86") || (use_linux_config && current_cpu = = "x64") | | (use_linux_config && current_cpu = = "x86")) to modify the if ((is_mac && current_cpu == "x64") || (is_win && current_cpu == "x64") || (is_win && current_cpu == "x86") || (use_linux_config && current_cpu == "x64") || (use_linux_config && current_cpu == "x86") || (is_android && current_cpu=="x86") || (is_android && current_cpu=="x64"))Copy the code
376 #
if ((is_mac && current_cpu == "x64" && ffmpeg_branding == "Chrome") || (is_win && current_cpu == "x64" && ffmpeg_branding == "Chrome") || (is_win && current_cpu == "x86" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "x64" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "x64" && ffmpeg_branding == "ChromeOS") || (use_linux_config && current_cpu == "x86" && ffmpeg_branding == "Chrome") || (use_linux_config && Current_cpu == "x86" && ffmpeG_branding == "ChromeOS")) modify if ((is_mac && current_CPU == "x64" && ffmpeg_branding == "Chrome") || (is_win && current_cpu == "x64" && ffmpeg_branding == "Chrome") || (is_win && current_cpu == "x86" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "x64" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "x64" && ffmpeg_branding == "ChromeOS") || (use_linux_config && current_cpu == "x86" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "x86" && ffmpeg_branding == "ChromeOS") || (is_android && current_cpu == "x64"))Copy the code
397 #
if ((is_mac && current_cpu == "arm64") || (is_win && current_cpu == "arm64") || (use_linux_config && current_cpu == "Arm64")) to modify the if ((is_mac && current_cpu = = "arm64") | | (is_win && current_cpu = = "arm64") | | (use_linux_config && current_cpu == "arm64") || (is_android && current_cpu == "arm64"))Copy the code
423 #
if ((is_mac && current_cpu == "arm64" && ffmpeg_branding == "Chrome") || (is_win && current_cpu == "arm64" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "arm64" && ffmpeg_branding == "Chrome") || (use_linux_config &¤t_CPU == "arm64" &&ffmpeg_branding == "ChromeOS") Modify if ((is_mac &¤t_CPU == "arm64") && ffmpeg_branding == "Chrome") || (is_win && current_cpu == "arm64" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "arm64" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "arm64" && ffmpeg_branding == "ChromeOS") || (is_android && current_cpu == "arm64"))Copy the code
487 #
If ((use_linux_config && current_cpu = = "arm" && arm_use_neon) | | (use_linux_config && current_cpu = = "arm")) to modify the if ((use_linux_config && current_cpu == "arm" && arm_use_neon) || (use_linux_config && current_cpu == "arm") || (is_android && current_cpu == "arm"))Copy the code
527 #
if ((use_linux_config && current_cpu == "arm" && arm_use_neon && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "arm" && arm_use_neon && ffmpeg_branding == "ChromeOS") || (use_linux_config && current_cpu == "arm" && Ffmpeg_branding = = "Chrome") | | (use_linux_config && current_cpu = = "arm" && ffmpeg_branding = = "jump")) to modify the if ((use_linux_config && current_cpu == "arm" && arm_use_neon && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "arm" && arm_use_neon && ffmpeg_branding == "ChromeOS") || (use_linux_config && current_cpu == "arm" && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "arm" && ffmpeg_branding == "ChromeOS")|| (is_android && current_cpu == "arm" && arm_use_neon))Copy the code
545 #
If (use_linux_config && current_CPU == "arm" && arm_use_neon) Changes if (use_linux_config && current_CPU == "arm" && arm_use_neon || (is_android && current_cpu == "arm" && arm_use_neon))Copy the code
564 #
if ((use_linux_config && current_cpu == "arm" && arm_use_neon && ffmpeg_branding == "Chrome") || (use_linux_config && Current_cpu == "arm" &&arm_use_neon &&ffmpeg_branding == "ChromeOS") modify if ((use_linux_config && current_CPU == "arm") && arm_use_neon && ffmpeg_branding == "Chrome") || (use_linux_config && current_cpu == "arm" && arm_use_neon && ffmpeg_branding == "ChromeOS")||(is_android && current_cpu =="arm" && arm_use_neon))Copy the code
Three: add static compilation
Route 1: webrtc_source webrtc/SRC/third_party/ffmpeg/chromium/config/chromium/android / / libavcodec codec_list. C
Add & ff_h264_decoder
static const AVCodec * const codec_list[] = {
&ff_flac_decoder,
&ff_mp3_decoder,
&ff_vorbis_decoder,
&ff_pcm_alaw_decoder,
&ff_pcm_f32le_decoder,
&ff_pcm_mulaw_decoder,
&ff_pcm_s16be_decoder,
&ff_pcm_s16le_decoder,
&ff_pcm_s24be_decoder,
&ff_pcm_s24le_decoder,
&ff_pcm_s32le_decoder,
&ff_pcm_u8_decoder,
&ff_libopus_decoder,
&ff_h264_decoder,
NULL };
Copy the code
Path 2: webrtc_source webrtc/SRC/third_party/ffmpeg/chromium/config/chromium/android / / libavcodec parser_list. C
Add & ff_h264_parser
static const AVCodecParser * const parser_list[] = {
&ff_flac_parser,
&ff_mpegaudio_parser,
&ff_opus_parser,
&ff_vorbis_parser,
&ff_vp9_parser,
&ff_h264_parser,
NULL };
Copy the code
Four: modify macro definition
Path: webrtc/SRC/third_party/ffmpeg/chromium/config/chromium/android / / config. H
Search CONFIG_H264_DECODER to change its value from 0 to 1
#define CONFIG_H264_DECODER 1
Copy the code
5: Add Licenses
Path: webrtc/SRC/tools_webrtc/libs/generate_licenses py
Find LIB_TO_LICENSES_DICT to add to the node
LIB_TO_LICENSES_DICT = { 'abseil-cpp': ['third_party/abseil-cpp/LICENSE'], ... 'spl_sqrt_floor': ['common_audio/third_party/spl_sqrt_floor/LICENSE'], 'openh264: [' third_party/openh264 / SRC/LICENSE'], add 'ffmpeg' # : [' third_party/ffmpeg/LICENSE. Md] # add}Copy the code
Create h264_codec.cc
Path: webrtc/SRC/SDK/android/SRC/jni
Create a new file h264_codec.cc in the above path
#include <jni.h> #include "modules/video_coding/codecs/h264/include/h264.h" #include "sdk/android/generated_h264_jni/H264Decoder_jni.h" #include "sdk/android/generated_h264_jni/H264Encoder_jni.h" #include "sdk/android/src/jni/jni_helpers.h" namespace webrtc { namespace jni { static jlong JNI_H264Encoder_CreateEncoder(JNIEnv* jni) { return jlongFromPointer(H264Encoder::Create(cricket::VideoCodec(cricket::kH264CodecName)).release()); } static jboolean JNI_H264Encoder_IsSupported(JNIEnv* jni) { return ! SupportedH264Codecs().empty(); } static jlong JNI_H264Decoder_CreateDecoder(JNIEnv* jni) { return jlongFromPointer(H264Decoder::Create().release()); } static jboolean JNI_H264Decoder_IsSupported(JNIEnv* jni) { return ! SupportedH264Codecs().empty(); } } // namespace jni } // namespace webrtcCopy the code
Create h264encode. Java and h264decoder. Java
Path: webrtc/SRC/SDK/android/SRC/Java/org/webrtc /
If you are compiling to AAR, add two Java files to the above directory. If you want to modify your own WEbrTC code for NDK development, the above files can be put in your own SDK, make sure the directory is org/webrtc/.
H264Decoder.java
package org.webrtc;
public class H264Decoder extends WrappedNativeVideoDecoder {
@Override
public long createNativeVideoDecoder() {
return nativeCreateDecoder();
}
static native boolean nativeIsSupported();
static native long nativeCreateDecoder();
}
Copy the code
H264Encoder.java
package org.webrtc;
public class H264Encoder extends WrappedNativeVideoEncoder {
@Override
public long createNativeVideoEncoder() {
return nativeCreateEncoder();
}
static native long nativeCreateEncoder();
@Override
public boolean isHardwareEncoder() {
return false;
}
static native boolean nativeIsSupported();
}
Copy the code
Eight: modify the Java layer software codec class
Find SoftwareVideoEncoderFactory. Java
public VideoEncoder createEncoder(VideoCodecInfo codecInfo) { String codecName = codecInfo.getName(); If (codecName. EqualsIgnoreCase (" H264 ")) {/ / new return new H264Encoder (); // add}// addCopy the code
Find SoftwareVideoDecoderFactory. Java
public VideoDecoder createDecoder(VideoCodecInfo codecInfo) { String codecName = codecInfo.getName(); If (codecName. EqualsIgnoreCase (VideoCodecMimeType. H264. ToSdpCodecName ())) {/ / new return new H264Decoder (); // add}// addCopy the code
Nine: add H264 compilation script
Write by imitating other codecs
Path: webrtc/SRC/SDK/android/BUILD designed.the gn
51 #
Add: “: h264_java”,
505 #
increase
rtc_android_library("h264_java") { visibility = [ "*" ] sources = [ "api/org/webrtc/H264Decoder.java", "api/org/webrtc/H264Encoder.java", ] deps = [ ":base_java", ":video_api_java", ":video_java", "//rtc_base:base_java", ]}Copy the code
545 #
Add: “: h264_java”,
860 #
Add:
rtc_library("h264_jni") {
visibility = [ "*" ]
allow_poison = [ "software_video_codecs" ]
sources = [ "src/jni/h264_codec.cc" ]
deps = [
":base_jni",
":generated_h264_jni",
":video_jni",
"../../modules/video_coding:webrtc_h264",
]
}
Copy the code
895 #
Add: “: h264_jni”,
1329 #
Add:
generate_jni("generated_h264_jni") {
sources = [
"api/org/webrtc/H264Decoder.java",
"api/org/webrtc/H264Encoder.java",
]
namespace = "webrtc::jni"
jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h"
}
Copy the code
Ten: compile
gn gen out/m93 --args='is_debug=false target_os="android" target_cpu="arm64" rtc_use_h264=true use_custom_libcxx=false'
Copy the code
ninja -C out/release/arm64-v8a
Copy the code
Ffmpeg conflict
The resulting static library contains FFMPEG, but is a crippled version of FFMPEG with very little functionality. It’s hard to share WEBRTC if you need FFMPEG in your own projects. Integrating your own will result in duplicate definition conflicts.
Is_component_ffmpeg is set to false to use a dynamic library, so that you can integrate FFMpeg yourself, and webRTC use your integrated one, so there is no conflict