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个线程去执行编译,这样会快很多

其中在执行脚本之前,大家可以先把脚本函数中的makemake 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错误,意思是禁止汇编

到这里基本就讲述完成了,说起来内容不多,但是在不了解的情况下,出了错真的一点办法都没有。希望本文对还没有编译成功的人有帮助。

我也是刚接触这一块,若有不当之处请多多指教。

你可能感兴趣的:(Mac下交叉编译FFmpeg3.4.5出Android的so包)