Mac下交叉编译FFmpeg3.4.5出Android的so包
在网上找了很多资料都从未编译成功过,一度特别失望;终于看了夏曹俊老师的视频播放器开发课之后也经过几番周折,最后成功了,在此总结一下,希望对在寻找资料的人有所帮助。
准备工作
这里两大主角就是:
- FFmpeg(版本是3.4.5)
- NDK(版本android-ndk-r15c)
特别注意这里版本是关键,下错了估计不行
我最开始下载了ffmpeg4.1不行,4.0.3还是不行,最后使用了3.4.5终于可以了;当然这里ndk我事先查资料知道了ndk16以后删除了一些东西,必须用15以及以下的才可以。
下载方式有很多,这里是官方的FFmpeg3.4.5文件,进入界面点击snapshot就能下载了,是一个.tar.gz文件,下载下来之后解压到某个目录即可,这个在哪都没有关系。
然后就是下载DNK,这个也是在官网下载就行,mac版ndk-r15c,下载好也是解压好就可以了,放哪也没有关系,但是最好放在一起。
我是建了一个ffmpeg目录,在目录下把ndk和ffmpeg-3.4.5放在一起的。
下载好之后,就可以执行命令了,并不需要修改configure文件,因为从3.4开始编译成android动态链接库的名称就是对的了。
编译过程
一般编译都有三部:
- 执行
configure
文件 - 执行
make
命令编译 - 执行
make install
命令打包
但是我们在执行configure文件的时候一般都会加一些参数,这就是本文的重点,我整理成了编译脚本,配置了armv7-a和x86的。
首先创建一个build_android.sh的脚本文件,名字随意,然后将下边的脚本复制过去修改ndk的路径即可。
使用方法
将build_android.sh脚本放到ffmpeg3.4.5目录下,然后执行chmod +x build_android.sh
命令给脚本增加权限,再直接执行./build_android.sh
即可。
当然最好先看完我下边的讲解再执行也不晚,下边有脚本的解释。当然你也可以把脚本中NDK路径修改之后,再把make和make install命令注释掉之后运行这个脚本也是可以的。如果出错了再看看下边的解释,看看配置是否有问题。
脚本如下:
#!/bin/bash
echo "进入编译ffmpeg脚本"
NDK=/Users/arvin/develop/ffmpeg/ndk/android-ndk-r15c
function buildFF
{
echo "开始编译ffmpeg"
ARM=$1
DST=$2
ABI_PREFIX=$3
PLATFORM=$NDK/platforms/android-21/arch-$ARM
TOOLCHAIN=$NDK/toolchains/$DST-4.9/prebuilt/darwin-x86_64
echo "ABI_PREFIX = ${ABI_PREFIX}"
echo "PLATFORM = ${PLATFORM}"
echo "TOOLCHAIN = ${TOOLCHAIN}"
./configure \
--prefix=$PREFIX \
--target-os=android \
--cross-prefix=$TOOLCHAIN/bin/$ABI_PREFIX- \
--arch=$ARM \
--sysroot=$PLATFORM \
--extra-cflags="$CFLAG" \
--cc=$TOOLCHAIN/bin/$ABI_PREFIX-gcc \
--nm=$TOOLCHAIN/bin/$ABI_PREFIX-nm \
--enable-shared \
--enable-runtime-cpudetect \
--enable-gpl \
--enable-small \
--enable-cross-compile \
--disable-debug \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-postproc \
--disable-avdevice \
--disable-symver \
--disable-stripping \
$ADD
make -j16
make install
echo "编译结束!"
}
###########################################################
echo "编译armv7-a支持neon和硬解码"
CPU=armv7-a
PREFIX=./android/$CPU-neon-hard
CFLAG="-I$PLATFORM/usr/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp "
ADD="--cpu=$CPU \
--enable-asm \
--enable-neon \
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--enable-hwaccel=h264_mediacodec "
buildFF arm arm-linux-androideabi arm-linux-androideabi
###########################################################
# echo "编译x86支持neon和硬解码"
# PREFIX=./android/x86-neon-hard
# CFLAG=""
# ADD="--extra-libs=-lgcc \
# --disable-asm \
# --enable-neon \
# --enable-jni \
# --enable-mediacodec \
# --enable-decoder=h264_mediacodec \
# --enable-hwaccel=h264_mediacodec "
# buildFF x86 x86 i686-linux-android
脚本解释
其中命令有一些比较重要的下边依次介绍。
-
#!/bin/bash
这个注释表示这是一个bash脚本 -
echo
是用来打印变量,方便调试的 - NDK=你的ndk路径,这种方式是命名变量并赋值
- function是定义函数,这里定义了一个buildFF函数,方便调用,后边可以加参数,在方法中通过$+数字获取,第一个参数就是$1,以此类推
- PLATFORM是编译的架构,armv7-a就是arm架构,可以看到在
ndk/platforms/android-某个版本
目录下有很多arch-各种架构
的文件 - TOOLCHAINS是交叉编译的工具,选择的目录表示在哪个系统下编译成哪个系统架构,以编译成armv7-a架构为例,就表示在mac系统下编译成arm-linux-androideabi-49。其实自己也可以去ndk/toolchains目录下看一下,就大概明白了
- 下边介绍configure的参数,
--prefix
表示make install成功之后输出文件的路径 -
--target-os
这里我们编译成android,很多文章写成linux,可能是在3.2以前可以吧,现在需要写成android,不然可能会有些头文件找不到 -
--cross-prefix
就是交叉编译工具的前缀,可以去那个目录下,你就能看到为什么这样写了 -
--arch
这个就是编译成什么架构,这里有两种armv7-a(参数需要写成arm)和x86的 -
--sysroot
这个就是platform的路径,表示在这个平台下的库文件为基础 -
--extra-cflags
是给gcc编译时增加的指令,在编译armv7-a架构的时候加上那些参数才能成功,其中-mfpu是指让gcc知道要使用neon协处理器,而在x86的编译时,这些指令都不能加,可能是x86架构下gcc对这些指令不支持,所以要去掉才能成功 -
--cc
和--nm
就是指定gcc和nm的位置 - 然后就是一系列
--enable
指令和--disable
指令,就不一一介绍了 - make -j16是开启16个线程去执行编译,这样会快很多
其中在执行脚本之前,大家可以先把脚本函数中的make
和make install
注释掉,因为编译过程也会花不少时间,注释掉之后执行,就只需要看配置是否有问题。没有error之后再解开注释执行。
注意在每次执行了脚本之后最好执行一下make clean
清理一下。
对于armv7-a和x86的编译cflag和ADD的内容不一样,cflag在上文中说了,ADD部分,前者需要添加cpu类型,后者不需要,但是需要加上--extra-libs=-lgcc
和--disable-asm
指令:
-
--extra-libs=-lgcc
是为了让x86架构下gcc执行编译不报错 -
--disable-asm
是为了让x86架构在as中使用的时候不会出现text relocation错误,意思是禁止汇编
到这里基本就讲述完成了,说起来内容不多,但是在不了解的情况下,出了错真的一点办法都没有。希望本文对还没有编译成功的人有帮助。
我也是刚接触这一块,若有不当之处请多多指教。