Android/NDK环境下FFmpeg及AAC,MP3,X264的编译

本篇介绍在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

如果前世五百次眸回,才换来今生的擦肩而过。

Android/NDK环境下FFmpeg及AAC,MP3,X264的编译

相关文章:

你感兴趣的文章:

标签云: