ubuntu下编译FFmpeg so库

首先列出本次编译所需要的环境和源码版本:

  • 编译环境:VMware-15.5.6 + ubuntu-20.04.2.0
  • 编译工具:android-ndk-r22b
  • FFmpeg源码:ffmpeg-4.1.6

1. 搭建编译环境

1.1 安装Ubuntu

在Windows10电脑安装VMware,创建新的虚拟机Ubuntu,到官网下载需要版本安装即可,安装完成后执行以下命令:

  • apt-get update
  • apt-get install yasm
  • apt-get install pkg-config
  • apt-get install make
    如果安装失败,解决办法根据提示,加sudo,如:sudo apt-get install make

1.2 下载ndk

在/home下新建ffm文件夹,将ndk下载到 /home/ffm/目录下:
wget https://dl.google.com/android/repository/android-ndk-r22b-linux-x86_64.zip
下载完成后解压:
unzip android-ndk-r22b-linux-x86_64.zip

1.3 下载FFmpeg

将FFmpeg下载到 /home/ffm/目录下:
wget http://www.ffmpeg.org/releases/ffmpeg-4.1.6.tar.gz
下载完成后解压:
tar -zxvf ffmpeg-4.1.6.tar.gz

2. 编译FFmpeg

在开始编译FFmpeg之前,先简单介绍下交叉编译。引自百度百科的定义:交叉编译是在一个平台上生成另一个平台上的可执行代码,这里即是在Linux平台编译出Android平台可以使用的FFmpeg so库。
对于C/C++的编译,通常有两个工具 GCC 和 CLANG 。

  • GCC,是一个老牌的编译工具,不仅可以编译C/C++,也可以编译Java,Object-C,Go等语言。
  • CLANG,则是一个效率更高的C/C++编译工具,并且兼容GCC,Google在很早以前就开始建议使用clang进行编译,并且在ndk17以后,把GCC移除了,全面推行使用 CLANG 。

2.1 新建配置编译脚本

在ffmpeg-4.1.6源码根目录下新建脚本build.sh:vim build.sh


输入完成后,出现如下界面:

然后按下英文字母i, 底部就会出现INSERT, 表示当前可以输入文本信息,脚本内容如下:

#!/bin/bash
# 目标Android版本
API=21
ARCH=arm
CPU=armv7-a
#so库输出目录
PREFIX=$(pwd)/android/$CPU
# NDK的路径,根据自己的NDK位置进行设置
NDK=/home/root1/ffm/android-ndk-r22b
# 编译环境
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
# 编译工具链路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
OPTIMIZE_CFLAGS="-DBIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD -mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
configure()
{
    ./configure \
    --prefix=$PREFIX \
    --enable-cross-compile \
    --target-os=android \
    --arch=$ARCH \
    --cpu=$CPU \
    --sysroot=$SYSROOT \
    --cc=$TOOLCHAIN/armv7a-linux-androideabi$API-clang \
    --cxx=$TOOLCHAIN/armv7a-linux-androideabi$API-clang++ \
    --cross-prefix=$TOOLCHAIN/arm-linux-androideabi- \
    --disable-encoders \
    --disable-decoders \
    --enable-decoder=h264 \
    --enable-decoder=h264_mediacodec \
    --enable-decoder=mp3 \
    --enable-decoder=aac \
    --disable-muxers \
    --disable-demuxers \
    --enable-demuxer=flv \
    --enable-demuxer=sdp \
    --enable-demuxer=rtsp \
    --disable-filters \
    --disable-parsers \
    --enable-parser=aac \
    --enable-parser=h264 \
    --disable-bsfs \
    --enable-bsf=aac_adtstoasc \
    --enable-bsf=h264_mp4toannexb \
    --disable-protocols \
    --enable-protocol=file \
    --enable-protocol=http \
    --enable-protocol=rtmp \
    --disable-libsrt \
    --enable-neon \
    --enable-hwaccels \
    --enable-shared \
    --enable-jni \
    --enable-mediacodec \
    --disable-static \
    --disable-doc \
    --enable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --enable-avdevice \
    --disable-doc \
    --disable-symver \
    --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS" \
    $ADDITIONAL_CONFIGURE_FLAG
}

build()
{
    configure
    make clean
    make
    make install
}

build

编辑完成后按Esc键退出编辑模式,输入:wq保存退出,可以看到根目录下多了build.sh文件。
重点关注几个选项:

  • arch 选择机器架构
  • cpu 选择最低的cpu
  • target-os 设置目标系统
    在旧版本的 FFmpeg 中,对Android平台的支持并不是很完善,并没有android 这个target,所以在一些比较老的文章中都会提到,编译Android平台的so库,需要对 configure 做以下修改,否则会按照 linux 标准的方式输出so库,其命名方式和Android的so不一样,Android是无法加载的。
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)'

但是在新版本(至少从4.0开始)的FFmpeg中,这个问题已经被解决了,FFmpeg加入了android 这个 target,不再需要手动去修改,建议大家尽量使用较新的版本。

  • sysroot 用于配置交叉编译环境的根路径,编译的时候会默认从这个路径下去寻找usr/includeusr/lib这两个路径,进而找到相关的头文件和库文件。
    注意:这里的路径一定要写对,ndk路径,包括不同ndk版本下面的头文件和库文件位置可能有所不同,如果找不到就会编译失败。
    关于ndk的路径,这里有个坑,本来设置/home/ffm/android-ndk-r22b,一直提示找不到,编译失败,真实路径是/home/root1/ffm/android-ndk-r22b。大家可以右键查看ndk文件夹属性,即可看到真实路径,如下图所示:

  • cross-prefix 交叉编译工具的前缀

  • cc 指定使用何种C编译器(默认gcc)

  • cxx 指定使用何种C编译器(默认g++)
    FFmpeg 默认的编译工具是 gcc,ndk老版本中,使用的也是gcc编译,所以只要设置cross-prefix即可,要保证能找到gcc文件,比如ndk14中配置如下

TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
...
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \

对应的编译工具如下


ndk17以后,改用clang编译,需要设置cc和cxx选项,比如本例的ndk22。

TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
...
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--cc=$TOOLCHAIN/armv7a-linux-androideabi$API-clang \
--cxx=$TOOLCHAIN/armv7a-linux-androideabi$API-clang++ \

对应的编译工具如下


可以根据自己的需求对脚本进行修改
查看所有编译配置选项:./configure --help
查看支持的解码器:./configure --list-decoders
查看支持的编码器:./configure --list-encoders
查看支持的硬件加速:./configure --list-hwaccels

2.2 启动编译

赋予脚本执行权限:chmod +x build.sh
执行脚本开始编译:./build.sh
等待编译完成,将会在源码根目录下的android/armv7-a/lib/下找到我们需要的.so文件了。

你可能感兴趣的:(ubuntu下编译FFmpeg so库)