源代码中找出本文需要的代码确实是一项非常艰难的
工作。在Linux下编译运行FFmpeg代码时需要经过 configure、make、make install三步才能将FFmpeg正确的编译到Linux系统当中。其中configure阶段会生成一个configure.h和make文件,从这两个文件中可以查找出该次编译都编译了那些文件。
经研究发现在configure源代码的时候可以加入很多配置参数,其中参数分为基本选项参数、高级选项参数还有专门提供的优化参数。优化参数主要负责配置在编译时需编译的内容。对FFmpeg的修剪也恰是将本系统中不需要的文件去除,因此本文利用选择适当的优化参数的方法找出播放器所需文件。对这些参数仔细研究后,得出编译时设置的参数如下:
./configure --enable-version3 --disable-encoders --enable-encoder=h263 --enable-encoder= amr_nb --disable-parsers --disable-bsfs --enable-muxer=tgp --disable-protocols --enable-protocol =file。
以上面所示的参数配置编译源文件时,系统只将h263、amr_nb的编码方法和3gp的文件封装格式及其所有的解码格式、解封装文件的源代码部分编译到了链接库。
此时被编译到链接库的源代码集合即为本文所需的源代码有效集,通过查找configure.h和make文件中的后缀名为.o文件,后缀名为.o的文件是编译.c代码时生成的目标文件,每一个被编译的.c文件都会生成.o文件,所以通过查看所有的后缀名为.o的文件名,便可得知在该配置参数下被编译源文件有哪些,因此可以得出本文所需编译的源文件最小集合。
FFmpeg开源代码虽然能够跨平台编译运行,但其代码的设计都是针对于PC机而言的,PC机和手机从CPU处理能力、能源、内存等各方面的资源都具有很多大差异,本文中针对手机的特点主要从以下几个方面优化代码:
1. 去除冗余代码、规范
程序结构、减少if-else 的判断、调整局部和全局变量、使用寄存器变量代替局部变量,减少不必要的代码冗余,去除FFmpeg 调试过程中的打印语句;
2. 用逻辑移位运算代替乘除操作,因为乘除运算指令的执行时间远远大于逻辑移位指令,尤其是除法指令,使用逻辑移位运算可以减少指令的运行时间;
3. 注意循环函数的调用,尽量减少多重循环的使用,编写代码时尽量减弱上次循环与下次循环的相关性,减少不必要的代码计算量;
4. 设置合理的缓存。针对FFmpeg 移植的目标平台Android平台,设置适合此本台的缓存大小;。
这里对具体代码的修改就不一一重复了。
3.2 FFmpeg移植
Google发布的NDK的makefile文件即Android.mk文件语法和普通的makefile文件有很多不同之处,在跨平台编译FFmpeg源代码时并不能使用原有的makefile文件。所以移植的先决条件就是将FFmpeg里的makefile文件全部替换为NDK中的Android.mk文件。
通过分析FFmpeg的模块结构得知avutil是基础模块,avcodec模块的编译基于已经编译好的avutil模块,avformat基于前两者,按照这种模块结构本文编译移植的顺序为avutil、avcoedec、avformat,编译的步骤详细说明如下:
1. 关于config.h和config.mak
首先说明一下FFmpeg自带的 makefile的框架,FFmpeg在经过configure命令之后会产生一个config.h文件和一个config.mak文件,这两个文件加起来共有 600-700个宏定义,用来描述编译后代码的各个方面参数设置,其中有关于体系架构、编译器、链接库、头文件、版本、编解码器等等相关的宏定义。在这一部分必须要修改关于平台差异方面的定义,比如必须把体系架构改成Android平台的ARMv5TE,这时文件编译的时候指令集就会选择ARM的指令集而不是X86的指令集。这两个文件很重要,