FFmpeg是一套用于录制、转换和流化音视频的完整的跨平台解决方案,它的强大之处不用过多描述,本文主要介绍如何编译出so文件和在Android Studio工程中的引入
交叉编译出so文件
交叉编译
在一个平台上生成另一个平台上的可执行代码叫做交叉编译,比如我们接下来要做的就是在PC平台上编译出Android系统能用的so
编译环境与工具链
既然是要编译出能在Android系统中可执行的so文件,那么我们肯定是不能在PC的环境下直接编译的,交叉编译最重要的就是配置好编译过程中需要使用的相关环境
对于C/C 的编译,通常有GCC和CLANG两种工具
GCC是比较老牌的编译工具,不仅可以编译C/C ,也可以编译Java,OC,Go等语言
CLANG则是一个效率更高的C/C 编译工具,且兼容GCC,Google在NDK17开始就不再支持GCC
所以接下来我们就采用CLANG来编译FFMpeg源码
使用clang编译FFmpeg so
编译环境:Mac NDK r21d FFMpeg5.0.1
最主要的两个目录
代码语言:javascript复制编译工具链:
toolchains/llvm/prebuilt/darwin-x86_64/bin
交叉编译环境:
toolchains/llvm/prebuilt/darwin-x86_64/sysroot
手头的OPPO Reno ACE是64位机型,API30的版本,所以选择这两个工具
下载FFMpeg5.0.1后使用Xcode打开configure文件,
- 搜索CMDLINE_SET,新增cross_prefix_clang
- 修改编译工具路径设置
- 新建编译脚本build_android_clang.sh
#!/bin/bash
#配置NDK路径
NDK=/Users/xyq/Desktop/tool/SDKandNDK/android-ndk-r21d
#配置toolchain路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
#配置交叉编译环境的根路径
SYSROOT=$TOOLCHAIN/sysroot
#arm64-v8a
API=30
ARCH=arm64
CPU=armv8-a
CROSS_PREFIX="$TOOLCHAIN/bin/aarch64-linux-android"
CROSS_PREFIX_CLANG="$TOOLCHAIN/bin/aarch64-linux-android$API"
#armeabi-v7a
#API=30
#ARCH=arm
#CPU=armv7-a
#CROSS_PREFIX="$TOOLCHAIN/bin/arm-linux-androideabi"
#CROSS_PREFIX_CLANG="$TOOLCHAIN/bin/armv7a-linux-androideabi$API"
OPTIMIZE_CFLAGS="-march=$CPU"
#配置so输出路径
OUTPUT=/Users/xyq/Desktop/test/ffmpeg-5.0.1/android/$CPU
fun build
{
./configure
--prefix=$OUTPUT
--target-os=android
--arch=$ARCH
--cpu=$CPU
--enable-neon
--enable-cross-compile
--enable-shared
--enable-jni
--disable-static
--disable-asm
--disable-doc
--disable-ffplay
--disable-ffprobe
--disable-symver
--disable-ffmpeg
--disable-avdevice
--disable-debug
--disable-postproc
--sysroot=$SYSROOT
--cross-prefix=$CROSS_PREFIX-
--cross_prefix_clang=$CROSS_PREFIX_CLANG-
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS"
make clean all
make -j8
make install
}
build
- 编译脚本添加执行权限并执行即可
chmod x build_android_clang.sh
./build_android_clang.sh
编译结束后我们得到了头文件、so文件和一些examples
构建脚本的一些解释
当我们配置--target-os=android时,默认的编译工具就是clang
configure脚本中ar, cc, cxx, nm的路径都是通过cross_prefix进行拼接,但实际上在NDK中的cc/cxx的路径是拼接了Android API版本号的
代码语言:javascript复制// ar
aarch64-linux-android-ar
// nm
aarch64-linux-android-nm
// cc, cxx
aarch64-linux-android30-clang
aarch64-linux-android30-clang
这也就是为什么我们需要添加cross_prefix_clang的原因
FFmpeg学习的第一步就是编译出so,很多怀揣热情的同学在编译过程中经常会遇到各种各样的编译问题,一泼冷水下来还没开始就被劝退......
通常来说编译的问题基本都是最终拼接下来的交叉编译工具路径不对,详细的异常信息可以通过查看config.log来进一步分析
使用FFmpeg so动态库
执行编译脚本后,我们得到了FFmpeg的so和头文件,接下来就导入到AS工程中用起来
- AS新建Native C 工程并导入FFMpeg头文件和so,so需要放到libs目录下
- 配置CMakeLists.txt
设置so的路径和头文件路径并include,然后添加每个so
FFmpeg的so我们放到libs目录下而不是放到jniLibs目录下,是因为本地新建的AS工程默认采用的7.3.3的gradle版本,放里面反而会出现编译错误
链接FFmpeg的so到我们工程的libffmpgdemo.so
- 验证FFmpeg
获取下avutil的version,然后在官网上找到下载编译so的这个版本校验下
至此,我们就完成了FFmpeg的编译和导入so/头文件到AS工程并使用了起来
~~END~~