FFmpeg的编译是一个大坑,尤其是编译安卓平台的动态库和静态库,应用于APP中。在Linux平台编译是相对简单的,但是我经过尝试在Linux编译静态库没有成功,所以又在windows平台尝试编译了ffempg的动态库,应用成功了,这里分享一下。
一、搭建编译环境
注意一定要注意NDK和FFmpeg的版本,如果你按照我的文章来的那就一定要下载NDK版本R14和FFmpeg版本3.3.9,并不一定要新版本,因为不同的FFmpeg需要不同版本的NDK支持,本文中的是验证过的。minGW的版本不用关心。
1.1 NDK配置
我使用的AndroidStudio,刚开始用自带的ndk-buidle进行编译,是通不过的,后来换到r14版本才能编译通过。
解压下载好的文件android-ndk-r14b-windows-x86_64.zip
到固定目录,尽量不要有中文,我的路径:D:\Android\android-ndk-r14b
。接下来配置到环境变量:
进入计算机->属性->高级系统设置->环境变量,在系统环境中新建NDK_PATH
,目录为刚才解压的NDK14的目录,如下:
image.png
再打开PATH
,添加刚才新建的NDK_PATH
:
image.png
然后一路确定后,测试是否配置成功。
打开cmd命令行,输入ndk-build
,如果成功有类似如下显示:
image.png
1.2 minGW安装配置
打开.exe文件,选择安装位置,我的安装目录是D:\programs\minGW
。
点击需要安装的组件,我选择全部勾选:
image.png
安装完成后,需要把两个路径添加到环境变量:D:\programs\minGW
和D:\programs\minGW\msys\1.0\bin
image.png
测试一下minGW是否配置成功:
image.png
如果就是配置成功了。
1.3 下载FFmpeg源码
切记一定下载3.3.9版本的,我试过编译4.0的是编译不过的。
image.png
下载后解压即可。
二、FFmpeg源码编译
那么问题来了,怎么执行编译命令呢?
这时候minGW上场了,还记得D:\programs\minGW\mysys\1.0\
吗,它下面有一个msys.bat
文件,双击打开就是类似于shell的环境。
2.1 修改生成的lib库文件名
编译之前首先要做件事情,就是修改源码目录下的configure
文件,因为我要的是Android平台的so库,所以要在配置文件中修改生成的库名称。使用记事本打开就行,修改方案如下:
# 原来的配置内容: 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)'
什么?你问我直接编译完了修改文件行不行,我认为是不行的,当然我也测试过。反正按照我说的做,保证行。
2.2开始编译
编译都是分三个步骤:
- configure
- make
- make install
因为ffmpeg编译时configure的参数很多,直接写在命令行会很麻烦,我们把这些写在里面就很方便了:
#!/bin/bash #NDK路径根据你自己设置的决定,注意不要直接拷贝window路径,因为linux不识别`\`,要使用`/` NDK=D:/Android/android-ndk-r14b SYSROOT=$NDK/platforms/android-18/arch-arm TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64 function build_one { ./configure \ --prefix=$PREFIX \ --enable-shared \ --disable-static \ --disable-doc \ --enable-cross-compile \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --target-os=linux \ --arch=armv7-a \ //注意平台 --sysroot=$SYSROOT \ --extra-cflags="-Os -fpic $ADDI_CFLAGS" \ --extra-ldflags="$ADDI_LDFLAGS" \ $ADDITIONAL_CONFIGURE_FLAG } CPU=armv7-a PREFIX=$(pwd)/android/$CPU ADDI_CFLAGS="-marm" build_one read -p "Press any key to continue."
保存为build_android.sh,其它名字也行。
注意里面的参数arch=armv7-a
,新版的AndroidStudio已经不支持armeabi
了,在使用so库的时候要与arch参数对应,后面会讲到。
打开mysys.bat,进入FFmpeg的源码目录:
image.png
添加可执行权限:
chmod 777 build_android.sh
image.png
可以看到,使用ls -l
是看不到有可执行权限的,不过没关系。
步骤一、执行configure
./build_android.sh //这里要等待较长的时间,我等了七八分钟的样子才有反应
如果没有报错的话就会打印:
Press any key to continue. //按任意键退出脚本
步骤二、执行make
make //这一步会编译所有的.c文件,生成很多的.o文件,时间较长
步骤三、执行make install
make install //这一步会生成头文件和lib库到步骤一中configure指定的路径android/armv7-a目录
执行这几步过程中可能会出错,如果出错,请严格对比版本号和环境变量是否正确。
生成文件目录如下:
image.png
image.png
接下来就是在AndroidStudio中使用了。
什么?为什么有带数字的,有不带数字的,该用哪个呢?用带数字的,至于为什么我也不知道,反正我试过只能用带数字的。
三、在AndroidStudio中使用编译好的FFmpeg库
我使用的较新的AndroidStudio版本,为什么要说这个呢?因为新版的AndroidStudio支持使用cmake,而不需要自己写Android.mk和Application.mk这些文件了。所以需要一定的cmake语法知识,大家可以自行搜索,需要几个简单的就行,我也会给出注释。
image.png
3.1 新建工程/Module
你需要新建支持c++的工程,再新建Module。如果你使用的工程不支持c++,新建Module时参考android studio: 为现有项目添加C++支持也可以。
我新建的支持C++的工程:
image.png
在默认Module里面会生成默认的两个文件:
image.png
build.gradle中也会生成JNI相关配置:
android { compileSdkVersion 29 buildToolsVersion "29.0.2" defaultConfig { ... externalNativeBuild { cmake { cppFlags "" } } } externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" //cmake配置文件路径 version "3.10.2" } } }