Android NDK 下 FFMPEG 的编译选项详解

在Android NDK下编译FFMPEG,除了要编写Android.mk文件外,还需要编写Application.mk来指定编译选项

一.  指定编译目标cpu的类型,使用APP_ABI 选项

如:   APP_ABI := armeabi 

APP_ABI := armeabi armeabi-v7a

APP_ABI := x86

目前,在构建 NDK 库时,可以使用三种支持的应用二进制接口(ABI):

  1. ‘armeabi’ – 默认接口,可创建出指向基于 ARM* v5TE 设备的二进制代码。具有这种目标的浮点运算使用软件浮点运算。使用此 ABI 创建的二进制代码将可以在所有 ARM* 设备上运行。
  2. ‘armeabi-v7a’ – 可创建出支持 ARM* v7 设备的二进制代码,将使用硬件 FPU 指令。
  3. ‘x86’ – 生成的二进制代码可支持包含基于硬件的浮点运算的 IA-32 指令集。

所有这些 ABI 选项均支持浮点运算。除非使用的是特定于 ARM* 的汇编指令,否则在将代码移植到 x86 时不会发生问题。其优势在于,如果碰巧您的应用仅针对‘armeabi’进行编译,而现在需要支持 x86,则您在进行大多数浮点运算时均能感觉到性能提升。


二.  指定优化级别,使用APP_OPTIM 选项

有release和debug两种选择,release表示输出二进制文件被优化,debug表示没有被优化,可以调试

如:APP_OPTIM := debug


三.  指定c,c++编译选项,使用APP_CFLAGS 和 APP_CPPFLAGS 选项,还有APP_STL

一些常用的c,c++编译选项介绍

-O0:无优化(默认)
-O和-O1:使用能减少目标文件大小以及执行时间并且不会使编译时间明显增加的优化.在编译大型程序的时候会显著增加编译时内存的使用.
-O2: 包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化.编译器不执行循环展开以及函数内联.此选项将增加编译时间和目标文件的执行性能.
-Os:专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项.并且执行专门减小目标文件大小的优化选项.
-O3: 打开所有-O2的优化选项并且增加 -finline-functions, -funswitch-loops,-fpredictive-commoning, -fgcse-after-reload and -ftree-vectorize优化选项.

-mlong-calls
生成的目标码允许同一个源文件中的函数调用 , 调用点和被调函数的距离可以超过 256K 之远 . 不需要打开这个开关选项 除非连接器给出 ``branch out of range errors`` 这样的错误。
对于arm平台,如果想编译出来的.o文件能被shell下ld命令动态加载就需要加上此参数。不然会提示 Relocation value does not fit in 26 bits.

-mstrict-align
-mno-strict-align
不允许 ( 或允许 ) 边界不对齐的访问具体用法可以参考http://blog.csdn.net/petib_wangwei/article/details/44173409


•  -ffast-math
   -ffast-math, -fno-fast-math
   设定 -fno-math-errno, -funsafe-math-optimizations, -fno-trapping-math, -ffinite-math-only, -fno-rounding-math, 以及 -fno-signaling-nans 这几个选项,以及设定预先处理器的 __FAST_MATH__ 宏。这些技术虽然较快,但是违反 IEEE 或 ISO 的规则,并且很有可能让程序算出错误的数值。

浮点优化选项 -ffast-math:极大地提高浮点运算速度

C99 浮点环境支持科学和数学级别的应用,这些应用必须有相当高的精度,但是某些应用却不是如此,注重速度高于精度。对于这些以速度为重的应用, -ffast-math 选项定义了预处理器宏 __FAST_MATH__, 指示编译不必遵循 IEEE  ISO 的浮点运算标准。

具体的分析可以参考http://blog.csdn.net/zjujoe/article/details/2604157


•  -fprefetch-loop-arrays
   -fprefetch-loop-arrays, -fno-prefetch-loop-arrays
   若目标机器支持,在存取大型数组循环执行之前预先将数组加载至内存。于 -Os 中关闭。
   其实不太会有需要存取大型数组的循环 (多媒体、数据库、科学计算软件中才比较常见),所以您可以放心将此选项关闭。


•  -fforce-mem    -fforce-addr
   -fforce-mem,   -fno-force-mem     -fforce-addr, -fno-force-addr
   强制在运算前将内存中的数值 (mem) 或内存位置 (addr) 复制到缓存器中。启动这两个选项可以做出较好的程序代码。
   这两个是好东西,启动它们!其中 -fforce-mem 已在 -O2, -O3, -Os 中启动,所以若您有用这三个选项的其中一个,只要 -fforce-addr 就够了。
•   -fomit-frame-pointer
   -fomit-frame-pointer, -fno-omit-frame-pointer
   若非必要,不将函式的 frame pointer 放进缓存器中。这将避免您的程序储存、设定、以及还原 frame pointer;也在许多函式中省下一个缓存器。这个选项可能让某些平台上的除错工作变成不可能!。若平台支持不使用 frame pointer 除错,这个选项将在 -O, -O2, -O3, -Os 中启动。
   很抱歉,x86 刚好是非这个不可才能除错的平台之一。但是... 您想对您的桌面进行除错吗?若答案为非,您可以放心启动这个选项。
•   -finline-functions
   -finline-functions, -fno-inline-functions
   将所有简单的函式整合进呼叫他们的函式中。编译器会自动试探并决定那些函式值得被整合。于 -O3 时启动。
   虽然这个选项会增加程序大小,但是他却是个增进效能的好东西。我建议您在这里启动它,然后使用下面一个指令指定 inline 条件。

•   -finline-limit
   -finline-limit=n
   n 为决定函式是否能被 inline 的伪指令长度。预设的值为 600。
   这个数值越小,程序启动的速度越快,但是运算的速度越慢。作为桌面使用,我建议 -finline-limit=400。
•  -fmove-all-movables  -freduce-all-givs
   -fmove-all-movables, -fno-move-all-moveables
-freduce-all-givs, -fno-redduse-all-givs
   这两个是循环最佳化技术,将无关循环内容的运算改在循环外执行。编译出的执行档可能更快也可能更慢,结果跟程序的写法有很大的关系。
   虽然说效能跟程序写法有关,但是大部份的状况下这两个选项会做出比较小与比较快的程序代码,所以我建议您启动他们!
•   -freorder-blocks   -freorder-functions
   -freorder-blocks, -fno-reorder-blocks
-freorder-functions, -fno-reorder-functions
   藉由重新编排程序区块来增进效能以及减少执行档大小。
   这两个也是好东西,所以我建议您启动它们。缺点是会让编译时间变长。
   -freorder-blocks 于 -O2, -O3 时启动,于 -Os 中关闭。-freorder-functions 于 -O2, -O3, -Os 时启动。
•   -fexpensive-optimizations
   -fexpensive-optimizations, -fno-expensive-optimizations
   执行几个会加长编译时间的非主要最佳化程序。于 -O2, -O3, -Os 中预设开启。
   虽然会增加编译时间,但是能增加效能也能减少执行档大小,所以建议启用。

•  -frename-registers
   -frename-registers, -fno-rename-registers
   在作过缓存器定位之后,使用剩下来的缓存器。这个最佳化在有很多缓存器的 CPU 上最明显 (如 ARM、PowerPC... 等。x86 不属于他们的一份子)。会增加除错的困难度。
   虽然在 x86 上不明显,但是还是有用。而且 x86-64 提供更多的缓存器,所以建议您还是应该打开它。于 -O3 时启动。

C++的异常支持:

    从NDK r5就开始NDK的工具链就开始支持了C++的异常控制,只不过为了通用性的原因,所有的C++原文件被编译的时候都是默认的是-fno-exceptions,即不不支持异常控制的。

    使用-fexceptions标记可以开启异常控制。所以你只需要在你的每个模块的Android.mk中添加LOCAL_CPPFLAGS += -fexceptions就可以了。

    更简单的是,在你的Application.mk文件中添加APP_CPPFLAGS += -fexceptions,这种配置会自动应用到你工程的所有模块当中。

    注意:

     已被废弃的"arm-eabi-4.4.0"工具链提供的向后兼容的NDK是不支持异常的。

 

    参考资料:

           http://stackoverflow.com/questions/4663291/android-ndk-r5-and-support-of-c-exception

           http://bbs.sjtu.edu.cn/bbstcon?board=GNULinux&reid=1305092782

 

RTTI support:

   从NDK r5开始,NDK工具链也开始支持C++ RTTI(Runtime Type Information)了。但是,为了通用性的,所有的C++源文件被构建的时候默认是不支持RRRI的(-fno-rtti)。需要开启的话,你需要在Android.mk中添加:LOCAL_CPPFLAGS += -frtti,或者更简单的做法是在Application.mk添加APP_CPPFLAGS += -frtti。

    注意:

     已被废弃的"arm-eabi-4.4.0"工具链提供的向后兼容的NDK是不支持RTTI的。


从Android NDK r5开始支持了STL Port,在这个版本开始就可以使用部分STL库的功能了,比如说vector、string摆脱c下面容易出现的数组未初始化、越界,增强应用的健壮性。
    很多网友包含了include <vector> 这样头,但仍然无法编译,这里你首先要检查当前文件是否为.cpp后缀,同时为了使用标准库必须加入 APP_STL := stlport_static 在Application.mk文件中。相关对应还有
system - 使用默认最小的C++运行库,这样生成的应用体积小,内存占用小,但部分功能将无法支持
stlport_static - 使用STLport作为静态库,这项是Android开发网极力推荐的
stlport_shared - STLport 作为动态库,这个可能产生兼容性和部分低版本的Android固件,目前不推荐使用。
gnustl_static  - 使用 GNU libstdc++ 作为静态库
默认情况下STLPORT是不支持C++异常处理和RTTI,所以不要出现 -fexceptions 或 -frtti ,如果真的需要可以使用gnustl_static来支持标准C++的特性,但生成的文件体积会偏大,运行效率会低一些。

    支持C++异常处理,在Application.mk中加入 LOCAL_CPPFLAGS += -fexceptions这句,同理支持RTTI,则加入LOCAL_CPPFLAGS += -frtti,这里Android123再次提醒大家,第二条说的使用gnustl静态库,而不是stlport。

    强制重新编译 STLPort ,在Application.mk中加入 STLPORT_FORCE_REBUILD := true 可以强制重新编译STLPort源码,由于一些原因可能自己需要修改下STLPort库,一般普通的开发者无需使用此项。

    Android目前最新的NDK版本为r6,相关的学习可以查看NDK中的Samples整体和在PC上开发没有太大的不同。


c++支持库用APP_STL := gnustl_static指令指定


另外在编译FFMPEG时,还要加上针对arm的优化指令

EXTRA_CFLAGS="-mtune=cortex-a8 -march=armv7-a -mfpu=neon -mfloat-abi=softfp(等价于-mhard-float) -mvectorize-with-neon-quad"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值