這里介紹在Mac下使用最新版NDK(r21)編譯最新版的FFmpeg(4.3.1),在NDK r17之后棄用了gcc键思,改用clang進行編譯础爬,因此最新版本NDK主要解決用clang配置編譯ffmpeg。原地址
準備
NDK
下載NDK(r21)
解壓NDK
(這一步網(wǎng)上資料較多不再贅述)FFmpeg:
下載官網(wǎng)最新版本的FFmpeg(4.3.1):https://www.ffmpeg.org/download.html#releases
修改編譯配置
默認配置是編譯生成Linux環(huán)境下的庫吼鳞,需要修改為生成Android環(huán)境下的so
用文本編輯器(比如Sublime text)打開ffmpeg文件夾下的configure文件看蚜,找到以下配置進行替換:
# 注釋掉默認configure 文件中的配置:
# SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
# LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
# SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
# SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
# 替換為:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='?(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
創(chuàng)建編譯腳本
- 打開終端,cd到ffmpeg目錄下赔桌,執(zhí)行以下命令創(chuàng)建腳本文件:
touch build_android.sh
- 用vim打開文件:
vim build_android.sh
- 復(fù)制以下shell腳本到 build_android.sh:
(注意:NDK需要修改成自己的路徑)
#!/bin/bash
# 以下路徑需要修改成自己的NDK目錄
TOOLCHAIN=/Users/xxx/Library/Android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/
# 最低支持的android sdk版本
API=29
function build_android
{
# 打印
echo "Compiling FFmpeg for $CPU"
# 調(diào)用同級目錄下的configure文件
./configure \
# 指定輸出目錄
--prefix=$PREFIX \
# 各種配置項供炎,想詳細了解的可以打開configure文件找到Help options:查看
--disable-neon \
--disable-hwaccels \
--disable-gpl \
--disable-postproc \
--enable-shared \
--enable-jni \
--disable-mediacodec \
--disable-decoder=h264_mediacodec \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC
--cxx=$CXX
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
echo "The Compilation of FFmpeg for $CPU is completed"
}
#armv8-a
ARCH=arm64
CPU=armv8-a
# r21版本的ndk中所有的編譯器都在/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/目錄下(clang)
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
# NDK頭文件環(huán)境
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
# so輸出路徑
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
# 交叉編譯工具目錄,對應(yīng)關(guān)系如下
# armv8a -> arm64 -> aarch64-linux-android-
# armv7a -> arm -> arm-linux-androideabi-
# x86 -> x86 -> i686-linux-android-
# x86_64 -> x86_64 -> x86_64-linux-android-
# CPU架構(gòu)
#armv7-a
ARCH=arm
CPU=armv7-a
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
build_android
#x86
ARCH=x86
CPU=x86
CC=$TOOLCHAIN/bin/i686-linux-android$API-clang
CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
build_android
#x86_64
ARCH=x86_64
CPU=x86-64
CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel"
# 方法調(diào)用
build_android
- 輸入
:wq
保存
開始編譯
- 先給腳本添加權(quán)限:
chmod 777 ./build_android.sh
- 然后就可以運行腳本編譯了:
./build_android.sh
編譯完成
編譯完成后將輸出文件
常見問題
- x86版本編譯問題
如果編譯完后發(fā)現(xiàn)沒有輸出x86 so,檢查是否有輸出以下錯誤信息:
nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.
原因是編譯x86依賴匯編器nasm或者yasm沒有安裝疾党。
因此需要先安裝好匯編器音诫,這里我們選擇其一進行安裝
安裝方法:brew install yasm
(通過homebrew 進行安裝)
安裝成功再重新編譯即可。
- Android 加載x86 so問題
在運行時加載so報錯:
java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/xxx.xxx.xxx-1/lib/x86/libavcodec.so: has text relocations
原因是android 6.0之后雪位,系統(tǒng)做了限制竭钝。Android 6.0 changes
On previous versions of Android, if your app requested the system to load a shared library with text relocations, the system displayed a warning but still allowed the library to be loaded. Beginning in this release, the system rejects this library if your app's target SDK version is 23 or higher. To help you detect if a library failed to load, your app should log the dlopen(3) failure, and include the problem description text that the dlerror(3) call returns. To learn more about handling text relocations, see this guide.
解決方法:需要在編譯選項中增加參數(shù)--disable-asm
如果出現(xiàn)以下錯誤
dlopen failed: cannot locate symbol "iconv_open",”iconv_close“
只能降低API版本,修改build_android.sh:API=26
[參考]
[1] https://yesimroy.gitbooks.io/android-note/content/compile_ffmpeg_for_android.html
[2] https://stackoverflow.com/questions/57681336/build-ffmpeg-4-2-with-android-ndk-r20
[3] http://www.reibang.com/p/feab970fd74c
[4] https://juejin.im/post/6844903945496690696
[5] https://blog.csdn.net/marco_0631/article/details/73292199
[6] http://www.reibang.com/p/fd938a51b01f
[7] https://github.com/tianshaokai/ffmpegbuild