本篇介绍在Android/Ndk环境下FFmpeg的编译及使用, FFmpeg自带了H264、AAC、MP3的解码器,但却没有(或没有好的)相应的编码器。相应的编码器需要使用第三方库。推荐使用的第三方库为x264(H264编码) 、FDK_AAC(AAC编码),lame(MP3编码)。
在顺序上,应该先编译好第三方库,最后再编译FFmpeg库。
【本书说明:本文作者:邵发,本文选自《FFmpeg视音频编程指南》。有关本书的详细信息请访问官网: 】
【权利声明:作者保留本文的全部权利。作者授权任何人都可以自由转载本文,但转载时必须遵守以下限制:①转载时必须全文转载,不得有任何修改,包括“权利声明”和“本书说明”部分 ② 仅限于网络转载,即最终结果公布于网络上。凡是不遵守以上两条的转载行为视为侵权行为。除非本人允许,任何人不得将本文内容用于任何的其他用途。】
1.1NDK环境的准备
本篇的演示示例使用的是android-ndk-r8e版本,但理论上也适用于更新的NDK版本。为了让你的编译过程极其顺利,应该对NDK作以下改动:
进入目录 platforms/android-14/arch-arm/usr/lib
应该可以看到一些文件,例如 crtbegin_dynamic.o ,crtbegin_static.o crtend_so.o , crtbegin_so.o ,crtend_android.o,等等。
把这个目录下的所有文件拷贝到
\toolchains\arm-linux-androideabi-4.6\prebuilt\linux-x86\lib\gcc\arm-linux-androideabi\4.6
否则在链接的时候ld会提示“找不到crtbegin_so.o和crtend_so.o”的错误。
应该把NDK的相关工具都把加PATH环境变量中,例如,
#!/bin/sh
export PATH=$PATH:/opt/ndk/android-ndk-r8e/
export PATH=$PATH: /opt/ndk/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/
1.2FDK_AAC库的编译
如果你不打算使用AAC编码的功能,则可以略过本节。目前(2015年3月),fdk_aac的官方发布地址是在source_forge上,也许以后会变,作者可以自行搜索。目前地址为:
本文使用的版本是fdk-aac-0.1.3,为减少不必要的麻烦,读者也请下载这个包。
1.2.1修改configure脚本
修改脚本的目的是去除目标库的版本号,以适应Android/NDK的对库的加载要求。简单地讲,这是因为在Android/NDK项目的java代码中,使用System.loadLibrary()函数来加载so文件时,动态库是不能加版本号的。
在fdk_aac的configure脚本里找到如下的行:
# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec=’${libname}${shared_ext} ${libname}${shared_ext} $libname${shared_ext}’
soname_spec=’${libname}${shared_ext}’
finish_cmds=’PATH="\$PATH:/sbin" ldconfig -n $libdir’
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
把粗体字部分替换为:
library_names_spec=’$libname${shared_ext} $libname.a’
1.2.2新建配置脚本
在源码的根目录下建议一个myconfig.sh脚本。这是一个SHELL脚本,要求读者自己稍微了解一些SHELL脚本的写法。在这里只强调一点:SHELL脚本是以\n结尾的,如果你是在windows下面编辑的,那么应该用dos2unix来把文本的换行符转成unix格式。
为了避免不必要的麻烦,把NDK解压缩在/opt/ndk/android-ndk-r8e目录,并将FDK的输出目录–prefix设置在/opt/ndk/openlib目录下。读者第一遍操作时,不要擅自修改目录,必须在熟练掌握之后再自行修改目录。
myconfig.sh里面内容为:
#!/bin/sh
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export AR=arm-linux-androideabi-ar
export LD=arm-linux-androideabi-ld
export AS=arm-linux-androideabi-gcc
export CFLAGS=" –sysroot=/opt/ndk/android-ndk-r8e/platforms/android-14/arch-arm -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 "
export CXXFLAGS=" –sysroot=/opt/ndk/android-ndk-r8e/platforms/android-14/arch-arm -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 "
export LDFLAGS=" -L/opt/ndk/android-ndk-r8e/platforms/android-14/arch-arm/usr/lib -march=armv7-a -Wl,–fix-cortex-a8 "
./configure –enable-static –prefix=/opt/ndk/openlib –host=arm-linux
1.2.3编译
如果你严格按照以上的操作进行,那么编译过程会非常简单。Linux下的开源软件一般都是分为三步编译 configure , make,make install,而fdk_aac也不例外。
1) ./myconfig.sh
执行上述配置脚本,开始配置
2) make
3) make install
一切正常,将在/opt/ndk/openlib下存放输出库及头文件,,注意这个库是去掉版本号的libfdk-aac。显然,Android/NDK的程序员会更喜欢不带版本号的库。
1.3LAME-MP3的编译
如果你不打算在项目中使用mp3编码,则略过本节。
本节介绍lame的编译,但遗憾的是,其动态库没有办法去掉版本号。所以本方法生成的目标动态库是带版本号的。
1.3.1新建配置脚本
新建配置文件myconfig.sh,内容如下,
#!/bin/sh
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export AR=arm-linux-androideabi-ar
export LD=arm-linux-androideabi-ld
export CFLAGS=" –sysroot=/opt/ndk/android-ndk-r8e/platforms/android-14/arch-arm "
export LDFLAGS=" -L/opt/ndk/android-ndk-r8e/platforms/android-14/arch-arm/usr/lib "
./configure –enable-static –prefix=/opt/ndk/openlib –host=arm-linux
1.3.2编译
1) ./myconfig.sh
执行上述配置脚本,开始配置
2) make
3) make install
一切正常,将在/opt/ndk/openlib下存放输出库及头文件。
1.4×264的编译
x264属于VLC的一部分,当前的源码位置为:
ftp://ftp.videolan.org/pub/videolan/x264/snapshots/
本篇使用的源码版本为x264-snapshot-20140723-2245-stable.tar.bz2
1.4.1修改configure脚本
这一步的目的是使输出的库文件不带版本号。如果你坚持认为版本号不影响你的开发,则忽略本小节。
找到这一位置:
else
echo "SOSUFFIX=so" >> config.mak
echo "SONAME=libx264.so.$API" >> config.mak
echo "SOFLAGS=-shared -Wl,-soname,\$(SONAME) $SOFLAGS" >> config.mak
fi
将粗体字修改为:(即去掉$API后缀)
echo "SONAME=libx264.so" >> config.mak
1.4.2新建配置脚本
新建myconfig.sh配置脚本,
#!/bin/sh
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export AR=arm-linux-androideabi-ar
export LD=arm-linux-androideabi-ld
export AS=arm-linux-androideabi-gcc
export CFLAGS=" –sysroot=/opt/ndk/android-ndk-r8e/platforms/android-14/arch-arm -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16"
export LDFLAGS=" -L/opt/ndk/android-ndk-r8e/platforms/android-14/arch-arm/usr/lib -march=armv7-a -Wl,–fix-cortex-a8 "
./configure –enable-static –enable-shared –prefix=/opt/ndk/openlib –host=arm-linux
1.4.3编译
1) ./myconfig.sh
执行上述配置脚本,开始配置
2) make
3) make install
1.5FFmpeg的编译
本示例使用的是FFmpeg2.1.3版本,可以从其官网ffmpeg.org上下载。如果不需要x264/aac/lame,可以直接进行本节的编译。
1.5.1修改configure脚本
本节的目的是让输出的库不含有版本号。
先找到configure的如下位置:
SHFLAGS=’-shared -Wl,-soname,$$(@F)’
LIBPREF="lib"
LIBSUF=".a"
FULLNAME=’$(NAME)$(BUILDSUF)’
LIBNAME=’$(LIBPREF)$(FULLNAME)$(LIBSUF)’
SLIBPREF="lib"
SLIBSUF=".so"
SLIBNAME=’$(SLIBPREF)$(FULLNAME)$(SLIBSUF)’
SLIBNAME_WITH_VERSION=’$(SLIBNAME).$(LIBVERSION)’
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_VERSION=’$(SLIBNAME)’
SLIBNAME_WITH_MAJOR=’$(SLIBNAME)’
LIB_INSTALL_EXTRA_CMD=’$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"’
SLIB_INSTALL_NAME=’$(SLIBNAME_WITH_VERSION)’
SLIB_INSTALL_LINKS=
1.5.2修改配置脚本
新建myconfig.sh
export NDK_ROOT=/opt/ndk
export TMPDIR=/tmp
如果前世五百次眸回,才换来今生的擦肩而过。