咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

Ubuntu 编译 FFmpeg 扩展 exoplayer3 音频软解码

项目使用了【exoplayer3】 ,播放MP4 AAC音频硬解码不支持,切换到软解AAC效果不理想,考虑使用FFmpeg扩展来实现音频软解码 。

一、软件环境

  1. Ubuntu 24.04 Server
  2. Android SDK
  3. NDK r25b (“ndk;25.1.8937393”) 和 cmake
  4. exoplayer3 release-1.5.0-alpha01

编译所需软件

1
2
$ su
$ apt update & apt install openjdk-17-jdk unzip -y

二、编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
cd /opt
wget -q https://googledownloads.cn/android/repository/commandlinetools-linux-11076708_latest.zip
<!-- wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip-->
unzip -qq commandlinetools-linux-7583922_latest.zip
mkdir -p android-sdk/cmdline-tools && mv cmdline-tools $_/latest
export ANDROID_HOME=$PWD/android-sdk
export ANDROID_SDK_ROOT=$ANDROID_HOME
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin


echo y | sdkmanager --update
echo y | sdkmanager --install "ndk;25.1.8937393"
export NDK_PATH=$ANDROID_HOME/ndk/25.1.8937393

# 同意授权
echo y | sdkmanager --licenses

# 如果sdkmanager网络不通,可以手动下载NDK
# sdkmanager download ndk fail. change to wget download
# wget -q https://googledownloads.cn/android/repository/android-ndk-r27-linux.zip
# <!-- wget -q https://dl.google.com/android/repository/android-ndk-r27-linux.zip-->
# unzip -qq android-ndk-r27-linux.zip
# cd android-ndk-r27-linux
# export NDK_PATH=$PWD

rm -rf /usr/local/bin/cmake
ln -s $NDK_PATH/prebuilt/linux-x86_64/bin/make /usr/bin/make


# release 1.4.1 分支有BUG,https://github.com/androidx/media/issues/992
# git checkout b930b40a16c06318e43c81771fa2b1024bdb3f29 此commit修复 992 BUG
git clone -b release-1.5.0-alpha01 https://github.com/androidx/media

export MEDIA_PATH="$PWD/media"
export FFMPEG_MODULE_PATH="$MEDIA_PATH/libraries/decoder_ffmpeg/src/main"
export HOST_PLATFORM="linux-x86_64"
export ANDROID_ABI=21
# export ENABLED_DECODERS=(vorbis opus flac alac pcm_mulaw pcm_alaw mp3 amrnb amrwb aac ac3 eac3 dca mlp truehd)
# 此处仅支持alac、aac
export ENABLED_DECODERS=(alac aac)
cd $FFMPEG_MODULE_PATH/jni
git clone -b "release/6.0" git://source.ffmpeg.org/ffmpeg
export FFMPEG_PATH=$PWD/ffmpeg
ln -s "$FFMPEG_PATH" ffmpeg

# 编译 ffmpeg
./build_ffmpeg.sh $FFMPEG_MODULE_PATH $NDK_PATH $HOST_PLATFORM $ANDROID_ABI ${ENABLED_DECODERS[@]}
# 编译成功,库文件在 $FFMPEG_MODULE_PATH/jni/ffmpeg/android-libs
tree $FFMPEG_MODULE_PATH/jni/ffmpeg/android-libs
# .
# ├── arm64-v8a
# │ ├── libavcodec.a
# │ ├── libavutil.a
# │ └── libswresample.a
# ├── armeabi-v7a
# │ ├── libavcodec.a
# │ ├── libavutil.a
# │ └── libswresample.a
# ├── x86
# │ ├── libavcodec.a
# │ ├── libavutil.a
# │ └── libswresample.a
# └── x86_64
# ├── libavcodec.a
# ├── libavutil.a
# └── libswresample.a

# 编译 lib-decoder-ffmpeg
cd $MEDIA_PATH
# 国内加速:distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-x-bin.zip
./gradlew lib-decoder-ffmpeg:assembleRelease
# 编译产物
cd /media/libraries/decoder_ffmpeg/buildout/outputs/aar/

三、错误解决

./gradlew lib-decoder-ffmpeg:assembleRelease 编译发生了很多关于的C++错误,主要的原因还是版本的兼容问题。
比如: ndk 版本,ANDROID_ABI 版本等等。比如手动下载并指定了 NDK 27 版本,但是编译进行中C++工具链会指向 ndk 25 版本,导致编译失败。

比如以下错误信息:

环境变量 export ANDROID_ABI=23 在日志中看到 aarch64-linux-android/21/liblog.so 链接到了 ABI-21,然后发生错误.
** 改为 ABI21 问题解决**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
root@cnserver:/opt/media# ./gradlew lib-decoder-ffmpeg:assembleRelease

> Configure project :demo
WARNING: The option setting 'android.jetifier.ignorelist=bcprov' is experimental.
WARNING: We recommend using a newer Android Gradle plugin to use compileSdk = 34

This Android Gradle plugin (8.0.1) was tested up to compileSdk = 33.

You are strongly encouraged to update your project to use a newer
Android Gradle plugin that has been tested with compileSdk = 34.

If you are already using the latest version of the Android Gradle plugin,
you may need to wait until a newer version with support for compileSdk = 34 is available.

To suppress this warning, add/update
android.suppressUnsupportedCompileSdk=34
to this project's gradle.properties.

> Task :lib-decoder-ffmpeg:buildCMakeRelWithDebInfo[arm64-v8a] FAILED
C/C++: ninja: Entering directory `/opt/media/libraries/decoder_ffmpeg/.cxx/RelWithDebInfo/3f254l4a/arm64-v8a'
C/C++: : && /opt/android-sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --sysroot=/opt/android-sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -g -DNDEBUG -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--gc-sections -Wl,--no-undefined -Qunused-arguments -Wl,-Bsymbolic -shared -Wl,-soname,libffmpegJNI.so -o /opt/media/libraries/decoder_ffmpeg/buildout/intermediates/cxx/RelWithDebInfo/3f254l4a/obj/arm64-v8a/libffmpegJNI.so CMakeFiles/ffmpegJNI.dir/ffmpeg_jni.cc.o -landroid /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libswresample.a /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavcodec.a /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a /opt/android-sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/21/liblog.so -latomic -lm && :
C/C++: ld: error: undefined symbol: stderr
C/C++: >>> referenced by log.c:380 (libavutil/log.c:380)
C/C++: >>> log.o:(av_log_default_callback) in archive /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a
C/C++: >>> referenced by log.c:380 (libavutil/log.c:380)
C/C++: >>> log.o:(av_log_default_callback) in archive /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a
C/C++: >>> referenced by log.c:384 (libavutil/log.c:384)
C/C++: >>> log.o:(av_log_default_callback) in archive /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a
C/C++: >>> referenced 7 more times
C/C++: clang++: error: linker command failed with exit code 1 (use -v to see invocation)
C/C++: ninja: build stopped: subcommand failed.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':lib-decoder-ffmpeg:buildCMakeRelWithDebInfo[arm64-v8a]'.
> com.android.ide.common.process.ProcessException: ninja: Entering directory `/opt/media/libraries/decoder_ffmpeg/.cxx/RelWithDebInfo/3f254l4a/arm64-v8a'
[1/2] Building CXX object CMakeFiles/ffmpegJNI.dir/ffmpeg_jni.cc.o
[2/2] Linking CXX shared library /opt/media/libraries/decoder_ffmpeg/buildout/intermediates/cxx/RelWithDebInfo/3f254l4a/obj/arm64-v8a/libffmpegJNI.so
FAILED: /opt/media/libraries/decoder_ffmpeg/buildout/intermediates/cxx/RelWithDebInfo/3f254l4a/obj/arm64-v8a/libffmpegJNI.so
: && /opt/android-sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --sysroot=/opt/android-sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -g -DNDEBUG -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--gc-sections -Wl,--no-undefined -Qunused-arguments -Wl,-Bsymbolic -shared -Wl,-soname,libffmpegJNI.so -o /opt/media/libraries/decoder_ffmpeg/buildout/intermediates/cxx/RelWithDebInfo/3f254l4a/obj/arm64-v8a/libffmpegJNI.so CMakeFiles/ffmpegJNI.dir/ffmpeg_jni.cc.o -landroid /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libswresample.a /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavcodec.a /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a /opt/android-sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/21/liblog.so -latomic -lm && :
ld: error: undefined symbol: stderr
>>> referenced by log.c:380 (libavutil/log.c:380)
>>> log.o:(av_log_default_callback) in archive /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a
>>> referenced by log.c:380 (libavutil/log.c:380)
>>> log.o:(av_log_default_callback) in archive /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a
>>> referenced by log.c:384 (libavutil/log.c:384)
>>> log.o:(av_log_default_callback) in archive /opt/media/libraries/decoder_ffmpeg/src/main/jni/ffmpeg/android-libs/arm64-v8a/libavutil.a
>>> referenced 7 more times
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

C++ build system [build] failed while executing:
/opt/android-sdk/cmake/3.22.1/bin/ninja \
-C \
/opt/media/libraries/decoder_ffmpeg/.cxx/RelWithDebInfo/3f254l4a/arm64-v8a \
ffmpegJNI
from /opt/media/libraries/decoder_ffmpeg

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
2 actionable tasks: 2 executed