前几天发了一篇FFmpeg调用Android MediaCodec进行硬解码的文章。 上面的技术点并不算太难,调用FFmpeg依然是常见的socket操作ffmpeg源码编译环境搭建,但关键点是FFmpeg版本选择和编译选项必须开启MediaCodec。 好的。
关于FFmpeg的编译,是老生常谈的话题了。 很多初学者都会卡在如何编译so的动态库上。 这似乎是 Android 开发转换音频和视频的主要绊脚石。 我什至没有时间写一行 FFmpeg 代码。 你不得不担心编译问题很久了。
当然,编译问题肯定是FFmpeg的错。 由于其不断升级,从最初的2.x版本到现在的4.x版本,调用socket发生了变化,编译选项也调整了不少。 不过网上各种Android so动态库编译文章还没有相应更新。 ,一些教程仍然是2.x版本。 如果你按照它们来编译,肯定会出现兼容性问题。
举几个例子:
早期编译版本需要更改 FFmpeg 中的一些源代码。 最常见的是下面的代码:
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)'
以前需要更改编译库名的连接方式,但在最新版本中不再需要这样做(最新版本是指ffmpeg的release/4.4分支版本)。
这也是一个常见的兼容性问题。
选择NDK版本实际上就是选择编译器。 早期的编译可能使用了GCC编译。 后来Google在NDK r18b版本中删除了GCC编译工具。 详情请参考以下链接:
因此,今天最新的动态库编译是使用Clang进行的。 为了与时俱进,没必要使用以前的NDK版本,直接使用最新的。
为了避免大家花费精力去编译FFmpeg,我会直接提供一个Github Repo,并将所有的编译脚本放在这个仓库中。
地址如下:
FFmpeg编译
FFmpeg源代码作为仓库的子模块加载。 下载时请注意以下事项:
git clone --recursive https://github.com/glumes/ffmpeg_android
复制
下载后进入build_android.sh文件,将NDK替换为自己的路径。 最好使用r20b版本,保持一致。
#!/bin/bash
#你的NDK路径
NDK=/Users/glumes/Downloads/android-ndk-r20b
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
API=21
复制
替换后ffmpeg源码编译环境搭建,赋予脚本可执行运行权限。 编译好的动态库位于ffmpeg_library文件夹中。 目前仅编译了armeabi-v7a架构。
android文件夹对应的是加载so的Android工程,也是FFmpeg调用Android MediaCodec的源码。
这个工程目录下不需要更改FFmpeg,FFmpeg的很多编译选项开关都放在config-env.sh目录下。 如有必要,您可以在文件中进行更改。 当前的选项是启用mediacodec编码,但其更改不会影响主编译脚本的运行。
顺便贴一下源码:
这里是专门执行编译的函数。 函数使用的一些参数必须在外部定义:
function build_android
{
echo "Compiling FFmpeg for $CPU"
./configure
--prefix=$PREFIX
--libdir=$LIB_DIR
--enable-shared
--disable-static
--enable-jni
--disable-doc
--disable-symver
--disable-programs
--target-os=android
--arch=$ARCH
--cpu=$CPU
--cc=$CC
--cxx=$CXX
--enable-cross-compile
--sysroot=$SYSROOT
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS"
--extra-ldflags="$ADDI_LDFLAGS"
--disable-asm
# 这些编译参数在 config-env.sh 文件中定义了
$COMMON_FF_CFG_FLAGS
make clean
make -j8 # 这里是定义用几个CPU编译
make install
echo "The Compilation of FFmpeg for $CPU is completed"
}
复制
接下来定义相关参数即可执行:
// 编译的 configure 可执行文件在 ffmpeg 源码目录中,要先进入到目录里
cd ffmpeg
// 定义好编译的架构
OUTPUT_FOLDER="armeabi-v7a"
ARCH="arm"
CPU="armv7-a"
TOOL_CPU_NAME=armv7a
TOOL_PREFIX="$TOOLCHAIN/bin/arm-linux-androideabi"
CC="$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang"
CXX="$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++"
SYSROOT="$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
PREFIX="${PWD}/../ffmpeg_library/android/$OUTPUT_FOLDER"
LIB_DIR="${PWD}/../ffmpeg_library/android/libs/$OUTPUT_FOLDER"
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
复制
由于我们的编译脚本没有放在FFmpeg源目录下,所以我们需要对路径进行一些更改,以便绝对不改变FFmpeg内容。
通过上面的参数设置,应该可以编译出正确的Android动态库了。 如果您在编译过程中遇到任何问题,请随时在Momo ezglumes上与我联系,并及时进行调整,以确保编译过程轻松完成。