一,步骤概览

二,步骤详细

本次试验的开发环境和相关版本:

1, 准备相关的环境和工具;

配置Android开发环境,以及安装必要的JDK / JDK 下载地址。Android开发环境具体操作请Google 自行解决。

下载并解压NDK,具体参考Android Developers / Android NDK 下载地址

解压后将得到一个NDK的解压目录,比如我的是:/Users/hikoqiu/packages/android-ndk-r10e

备注: 后面将使用$NDK来代表NDK的目录, 比如:$NDK/ndk-build 则表示/Users/hikoqiu/packages/android-ndk-r10e/ndk-build

2, 准备ffmpeg源码

解压: tar -xf ffmpeg-2.8.4.tar.bz2

将解压后的源码文件夹复制到$NDK/sources目录,此时$NDK/sources目录下就有ffmpeg-2.8.4这个源码文件夹($NDK/sources/ffmpeg-2.8.4).

为了目录好看,我把ffmpeg-2.8.4改名为ffmpeg

3, 编译ffmpeg源代码

网上的说法是:为了让ffmpeg源码能顺利编译并用于android,需要修改configure文件的几个参数。

将#NDK/sources/ffmpeg/configure中的以下4个变量:

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_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

$NDK/sources/ffmpeg目录下新建build_ffmpeg.sh文件,文件具体内容请参考:build_ffmpeg.sh.

因为我使用Markdown写这篇文,格式不好控制,所以这里就不贴出来代码,请直接点连接查看。

注意:build_ffmpeg.sh中三个变量NDK、SYSROOT、TOOLCHAIN的需要根据你具体的NDK的解压路径进行配置。

先给build_ffmpeg.sh加上可执行的权限,再执行。

chmod a+x build_ffmpeg.sh
./build_ffmpeg.sh

备注:build_ffmpeg.sh文件中配置了./configure的一些相关参数, 然后make、make install.

顺利执行完之后,将会在$NDK/sources/ffmpeg/android/arm/lib下看到多个.so文件,在lib目录下还有多个软链文件。

在$NDK/sources/ffmpeg/android/arm目录下创建Android.mk文件,文件内容请参考: Android.mk

备注:配置在Android.mk的相关的.so类文件,将会在后面的操作$NDK/ndk-build中,复制到项目的libs里面。

4, 创建实验的Android项目并配置JNI

比如创建项目: MyJni

5, 引用.so文件,并在Java中调用

这部分更多是JNI的开发,可以去参考其他JNI的开发资料。

这里使用MyJni项目来介绍。

这个时候,顺利的话,会在MyJni的libs下生成多个ffmpeg的相关的类文件(.so).

6,调用

在Loader.java中调用,具体请参考 Loader.java

一切顺利的话,将会看到压缩之后的视频文件,20+M的视频文件,只剩下3M,而且还不是很模糊。

三,参考资料

如果上面你看不懂或者操作失败,那一定是我介绍得不清楚。这里有更多可以参考的资料,这是我在做这个实验的过程中参考的内容。

在做这个实验的时候,参考了很多很多内容,从普通的博客到多个的stackoverflow的内容,中间遇到了接近无数个问题,最终顺利弄出来。文件的所有代码以及我的测试项目的文件都已经放在我的github上,见:JNI_INVOKE_FFMPEG .

我平时是一个服务端+后端工程师,所以玩Android都是业余时间试试而已,所以优化之类的工作需要靠各位Android的工程师了。