注意:此方法在windows平台上使用MSYS环境不可行。并且NDK版本变化快,仅供参考
改良自博客 原文 毛毛v5 ffmpeg android ndk编译,还是用的gcc,不会配置clang版的
编译环境
1 Ubuntu 64位(2020/5/19更新:windows环境下,安装自带linux子系统 ubuntu测试成功)
2 NDK r19c
3 FFmpeg 4.1.3 源码 (可以不提前下载,2020/5/19更新:4.2.2版本测试成功)
4 x264源码(可以不提前下载,2020/5/19更新:最新版本测试成功)
最近在从源码编译视频框架,但网上很多脚本都是两三年前的,不适用于最近的版本ffmpeg ,或者只针对特定cpu架构的。
编译过程 ,整个过程就编辑3个脚本文件即可。
1 下载NDK r19c (我试过 其他版本的NDK,无法完成整个过程)
1 编辑 安卓NDK工具链脚本。找一个目录 终端进入 键入 touch make_android_toolchain.sh ,创建一个脚本。文本编辑器进行编辑 输入下面的内容
#!/bin/bash
#NDK目录,你要改成自己的ndk解压缩后所在的目录
export NDK_HOME=/home/akbot/Android/android-ndk-r19c
#生成交叉编译链工具
toolchain=${NDK_HOME}/build/tools/make-standalone-toolchain.sh
#生成交叉编译链保存在当前目录子文件夹android-toolchain
install_root=`pwd`/android-toolchain-r19
#生成32位库最低支持到android4.3,64位库最低支持到android5.0
platforms=(
"android-18"
"android-18"
"android-21"
"android-18"
"android-21"
)
#支持以下5种cpu框架
archs=(
"arm"
"arm"
"arm64"
"x86"
"x86_64"
)
#cpu型号
abis=(
"armeabi"
"armeabi-v7a"
"arm64-v8a"
"x86"
"x86_64"
)
echo $NDK_HOME
echo "安装在目录:$install_root"
num=${#abis[@]}
for ((i=0; i<num; i++))
do
bash $toolchain --arch=${archs[i]} --platform=${platforms[i]} --abis=${abis[i]} --install-dir=$install_root/${abis[i]}
done
这个脚本是使用NDK自带的工具链生成工具生成编译所需要的命令行工具集,真正做编译链接流程。
2 接着在相同文件夹下创建第二个脚本,编译x264库。终端打开当前目录 输入 touch android_build_x264.sh 创建脚本 ,用文本编辑器打开
#!/bin/bash
ROOT=`pwd`/
#配置交叉编译链,未生成交叉编译链请参考https://github.com/cwj2014/android_toolchain
export TOOL_ROOT=$ROOT/android-toolchain-r19
#五种类型cpu编译链
android_toolchains=(
"armeabi"
"armeabi-v7a"
"arm64-v8a"
"x86"
"x86_64"
)
#优化编译项
extra_cflags=(
"-march=armv5te -msoft-float -D__ANDROID__ -D__ARM_ARCH_5TE__ -D__ARM_ARCH_5TEJ__"
"-march=armv7-a -mfloat-abi=softfp -mfpu=neon -mthumb -D__ANDROID__ -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -D__ARM_ARCH_7R__ -D__ARM_ARCH_7M__ -D__ARM_ARCH_7S__"
"-march=armv8-a -D__ANDROID__ -D__ARM_ARCH_8__ -D__ARM_ARCH_8A__"
"-march=i686 -mtune=i686 -m32 -mmmx -msse2 -msse3 -mssse3 -D__ANDROID__ -D__i686__"
"-march=core-avx-i -mtune=core-avx-i -m64 -mmmx -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mpopcnt -D__ANDROID__ -D__x86_64__"
)
extra_ldflags="-nostdlib -lc"
#共同配置项,可以额外增加相关配置,详情可查看源文件目录下configure
configure="--disable-cli \
--enable-static \
--enable-shared \
--disable-opencl \
--enable-strip \
--disable-cli \
--disable-win32thread \
--disable-avs \
--disable-swscale \
--disable-lavf \
--disable-ffms \
--disable-gpac \
--disable-lsmash"
#针对各版本不同的编译项
extra_configure=(
"--disable-asm"
""
""
"--disable-asm"
"--disable-asm"
)
#交叉编译后的运行环境
hosts=(
"arm-linux-androideabi"
"arm-linux-androideabi"
"aarch64-linux-android"
"i686-linux-android"
"x86_64-linux-android"
)
#交叉编译工具前缀
cross_prefix=(
"arm-linux-androideabi-"
"arm-linux-androideabi-"
"aarch64-linux-android-"
"i686-linux-android-"
"x86_64-linux-android-"
)
#当前目录下x264源文件目录
if [ ! -d "x264" ]
then
echo "下载x264源文件"
git clone https://code.videolan.org/videolan/x264.git
fi
SOURCE=x264
#安装文件夹
INSTALL_DIR="x264_install"
#安装路径,默认安装在当前执行目录下的${INSTALL_DIR}
PREFIX=$ROOT/$INSTALL_DIR
n=${#android_toolchains[@]}
cd $ROOT/$SOURCE
for((i=0; i<n; i++))
do
export PATH=$TOOL_ROOT/${android_toolchains[i]}/bin:$PATH
echo "开始配置${android_toolchains[i]}版本"
#交叉编译最重要的是配置--host、--cross-prefix、sysroot、以及extra-cflags和extra-ldflags
./configure ${configure} \
${extra_configure[i]} \
--prefix=$PREFIX/${android_toolchains[i]} \
--host=${hosts[i]} \
--cross-prefix=${cross_prefix[i]} \
--sysroot=$TOOL_ROOT/${android_toolchains[i]}/sysroot \
--extra-cflags="${extra_cflags[i]}" \
--extra-ldflags="$extra_ldflags"
make clean
echo "开始编译并安装${android_toolchains[i]}版本"
make -j4 & make install
done
这个脚本会生成针对
“armeabi”
“armeabi-v7a”
“arm64-v8a”
“x86”
“x86_64”
这些架构的cpu的 x264动态库,为后续的ffmpeg编译依赖,可以根据需要缩减
脚本中判断了当前目录是否有x264源码 ,如果没有会自动下载完进行编译。
3 创建最后一个脚本 编译最终的ffmpeg动态库 。
在与上面相同的目录,打开终端 输入 touch android_build_ffmpeg.sh,用文本编辑器打开 ,输入下面内容
#!/bin/bash
ROOT=`pwd`
if [ ! -d "ffmpeg-4.1.3" ]
then
# echo "解压ffmpeg-4.1.3源文件"
wget http://ffmpeg.org/releases/ffmpeg-4.1.3.tar.bz2
tar -xjvf ffmpeg-4.1.3.tar.bz2
fi
#当前目录下x264源文件目录
SOURCE=ffmpeg-4.1.3
#配置交叉编译链,未生成交叉编译链请参考https://github.com/cwj2014/android_toolchain
export TOOL_ROOT=$ROOT/android-toolchain-r19
#五种类型cpu编译链
android_toolchains=(
"armeabi"
"armeabi-v7a"
"arm64-v8a"
"x86"
"x86_64"
)
#优化编译项
extra_cflags=(
"-std=gnu11 -march=armv5te -msoft-float -D__ANDROID__ -D__ARM_ARCH_5TE__ -D__ARM_ARCH_5TEJ__"
"-std=gnu11 -march=armv7-a -mfloat-abi=softfp -mfpu=neon -mthumb -D__ANDROID__ -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -D__ARM_ARCH_7R__ -D__ARM_ARCH_7M__ -D__ARM_ARCH_7S__"
"-std=gnu11 -march=armv8-a -D__ANDROID__ -D__ARM_ARCH_8__ -D__ARM_ARCH_8A__"
"-std=gnu11 -march=i686 -mtune=i686 -m32 -mmmx -msse2 -msse3 -mssse3 -D__ANDROID__ -D__i686__"
"-std=gnu11 -march=core-avx-i -mtune=core-avx-i -m64 -mmmx -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mpopcnt -D__ANDROID__ -D__x86_64__"
)
#共同配置项,可以额外增加相关配置,详情可查看源文件目录下configure
#--disable-indev=v4l2 #解决libavdevice/v4l2.c:135:9: error: assigning to 'int (*)(int, unsigned long, ...)'
configure="--enable-gpl \
--enable-version3 \
--enable-nonfree \
--enable-static \
--enable-shared \
--enable-small \
--disable-ffmpeg \
--disable-doc \
--disable-htmlpages \
--disable-manpages \
--disable-podpages \
--disable-txtpages \
--disable-indev=v4l2 \
--enable-libx264"
#针对各版本不同的编译项
extra_configure=(
"--disable-asm"
""
""
"--disable-asm"
"--disable-asm"
)
#交叉编译工具前缀
cross_prefix=(
"arm-linux-androideabi-"
"arm-linux-androideabi-"
"aarch64-linux-android-"
"i686-linux-android-"
"x86_64-linux-android-"
)
#支持以下5种cpu框架
archs=(
"arm"
"arm"
"arm64"
"x86"
"x86_64"
)
#安装文件夹
INSTALL_DIR="ffmpeg_install"
#安装路径,默认安装在当前执行目录下的${INSTALL_DIR}
PREFIX=$ROOT/$INSTALL_DIR
#x264安装目录
X264_INSTALL_DIR=$ROOT/"x264_install"
#libmp3lame安装目录
LAME_INSTALL_DIR=$ROOT/"lame_install"
n=${#android_toolchains[@]}
cd $ROOT/$SOURCE
for((i=0; i<n; i++))
do
export PATH=$TOOL_ROOT/${android_toolchains[i]}/bin:$PATH
echo "开始配置${android_toolchains[i]}版本"
#配置额外库头文件和库文件路径
extra_include="-I$X264_INSTALL_DIR/${android_toolchains[i]}/include -I$LAME_INSTALL_DIR/${android_toolchains[i]}/include"
extra_lib="-L$X264_INSTALL_DIR/${android_toolchains[i]}/lib -L$LAME_INSTALL_DIR/${android_toolchains[i]}/lib -lc"
#交叉编译最重要的是配置--host、--cross-prefix、sysroot、以及extra-cflags和extra-ldflags
./configure ${configure} \
${extra_configure[i]} \
--prefix=$PREFIX/${android_toolchains[i]} \
--enable-cross-compile \
--target-os=android \
--arch=${archs[i]} \
--cross-prefix=${cross_prefix[i]} \
--sysroot=$TOOL_ROOT/${android_toolchains[i]}/sysroot \
--extra-cflags="${extra_cflags[i]} $extra_include" \
--extra-ldflags="$extra_lib"
make clean
echo "开始编译并安装${android_toolchains[i]}版本"
make -j4
make install
done
这个脚本会生成针对
“armeabi”
“armeabi-v7a”
“arm64-v8a”
“x86”
“x86_64”
这些架构的cpu的 ffmpeg动态库,可以根据需要缩减
脚本中判断了当前目录是否有FFmpeg 4.1.3源码 ,如果没有会自动下载完进行编译。
如果没有提前下载源码,则当前目录只有三个脚本文件
4 执行编译
(可选) 可能需要首先给这些脚本执行权限
终端打开当前目录 分别输入
chmod +x make_android_toolchain.sh
chmod +x android_build_x264.sh
chmod +x android_build_ffmpeg.sh
然后分别执行1 2 3 三个脚本
终端进入当前目录
依此执行
./make_android_toolchain.sh
这一步如果报
ERROR: Failed to create toolchain
可能没有最新版python 请用
apt-get install python
安装 python
接下来
./android_build_x264.sh
这一步用到了git,如果没有安装可能会报错,可以输入
sudo apt install git
进行安装,不过也可以不用,如果提前下载了x264源码并放在了x264命名的目录下的话,下面ffmpeg脚本一个道理
最后
./android_build_ffmpeg.sh
后两个耗时较长,需要耐心等待 。
执行完毕后 ,ffmpeg 编译好的内容会在 ffmpeg-install目录下
如果没有问题 你们的目录下应该与我的是一样的 ,除了android-toolchain-r15,r10,r17没有 (这三个toolchain是我自己额外生成的,没有用到)
进入 ffmpeg-install —> armeabi/armeabi-v7a/arm64-v8a/x86 —> lib 目录 就能看到编译好的动态链接库文件了
就能集成进AndroidStudio进行后续开发了。
下一篇将会介绍把编译好的动态库放入android工程,实现视频播放功能。
如果有疑问,请在下方留言。如果有帮助可以点一个赞哦。
参考资料
参考资料
后记:
1 后面引入到Android工程时,运行报错,类似 找不到 libx264.so.xxx
为了后续方便,需要在源码目录中修改两个config文件
首先,进入ffmpeg-4.1.3目录 文本编辑器打开编辑目录下面的 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)'
保存
然后打开x264目录 ,同样用文本编辑器打开 configure文件
找到
elif [ "$SYS" = "SunOS" ]; then
echo "SOSUFFIX=so" >> config.mak
echo "SONAME=libx264.so.$api" >> config.mak
echo "SOFLAGS=-shared -Wl,-h,\$(SONAME) $SOFLAGS" >> config.mak
else
echo "SOSUFFIX=so" >> config.mak
echo "SONAME=libx264.so.$api" >> config.mak
echo "SOFLAGS=-shared -Wl,-soname,\$(SONAME) $SOFLAGS" >> config.mak
改为
elif [ "$SYS" = "SunOS" ]; then
echo "SOSUFFIX=so" >> config.mak
echo "SONAME=libx264.so" >> config.mak
echo "SOFLAGS=-shared -Wl,-h,\$(SONAME) $SOFLAGS" >> config.mak
else
echo "SOSUFFIX=so" >> config.mak
echo "SONAME=libx264.so" >> config.mak
echo "SOFLAGS=-shared -Wl,-soname,\$(SONAME) $SOFLAGS" >> config.mak
因为经过上述操作已经编译好了,修改完需要重新执行一遍
chmod +x android_build_x264.sh
chmod +x android_build_ffmpeg.sh
这两个脚本,重新生成库文件。
#2019.8.30 更新
2 ffmpeg和x264编译脚本的 extra_ldflags 配置都增加了 -lc 选项,原因是为了解决后续在android项目中引入时,某些手机运行出现的 “找不到gettimeofday” 的问题。