请尊重原创,转载请注明出处:http://blog.csdn.net/mabeijianxi/article/details/72904694
本人环境与工具:
- ndk:r14
- FFmpeg版本: 3.2.5
- Android Studio: 2.3.2
一、说明:
本文是经过实战总结出的经验,本文将用两种方式编译可以在Android下执行命令的FFmpeg,一种是传统的ndk-build工具,一种是cmake工具,经过我的项目实战,非常推荐cmake,因为AS 2.2以后对它支持的非常好,你可以非常方便的像debug Java代码一样去debug Native代码。本文以是在假设已经编译好了全架构的 FFmpeg 的基础上进行的,编译步骤: 编译Android下可用的全平台FFmpeg(包含libx264与libfdk-aac)。
二、传统ndk-build命令编译
所谓传统,必然就稍微没那么智能了,我们一步一步的搞。
- 打开你养家糊口的Android Studio,娴熟的新建一个项目;
-
编写一个 native 函数,如果只是测试我们在MainActivity里面搞就行了:
public native int ffmpegRun(String[] cmd);
-
新建jni目录,在目录下新建文件: jx_ffmpeg_cmd_run.c;
-
编码对应的 JNI 接口:
#include <jni.h><br> JNIEXPORT jint JNICALL Java_com_mabeijianxi_jianxiffmpegcmd_MainActivity_ffmpegRun(JNIEnv *env, jobject instance, jobjectArray cmd) { // TODO }
-
找到我们FFmpeg编译后的根目录,然后 copy:
cmdutils.c cmdutils.h cmdutils_common_opts.h config.h ffmpeg.c ffmpeg.h ffmpeg_filter.c ffmpeg_opt.c(注意需要编译后才会有config.h)到 jni 目录下,再进入到我们的编译后的产物目录,把include文件夹与所有的 .so 动态库也 copy 到jni目录下。完成后你jni目录结构应该如下图:
-
文件修改
修改ffmpeg.c与ffmpeg.h
找到ffmpeg.c,把int main(int argc, char argv) 改名为 int jxRun(int argc, char argv)
找到ffmpeg.h, 在文件末尾添加函数申明: int jxRun(int argc, char **argv);
1)修改cmdutils.c 和 cmdutils.h
找到cmdutils.c中的exit_program函数
修改前:
修改后:
2)找到cmdutils.h中exit_program的申明,也把返回类型修改为int。
修改前:
修改后:
很多教程都只修改到这里,基本没什么问题,但是你实际运行的时候会发现如果连续多次执行命令会有问题的,通过源码我们可以知道,FFmpeg每次执行完命令后会调用 ffmpeg_cleanup 函数清理内存,并且会调用exit(0)结束当前进程,但是经过我们的修改,exit()的代码已经被删掉,我们在Android中自然不能结束当前进程了,所以有些变量的值还在内存中,这样就会导致下次执行的时候可能会出错。我也尝试过fork一个进程给ffmpeg执行,完事后通过 信号来进程间通信,这样管用但是很麻烦,我们其实只需要简单的重设一些变量即可。
打开ffmpeg.c找到刚修改的jxRun函数,然后在 return 前加上如下代码即可:
nb_filtergraphs = 0; progress_avio = NULL; input_streams = NULL; nb_input_streams = 0; input_files = NULL; nb_input_files = 0; output_streams = NULL; nb_output_streams = 0; output_files = NULL; nb_output_files = 0;
-
编写调用函数
我们上面只在jx_ffmpeg_cmd_run.c新建了一个JNI接口函数,还没有实现逻辑,我们实现后的代码如下:
** * Created by jianxi on