0. 前言
ffmpeg命令很强大,但是在Android工程中无法执行可执行文件ffmpeg,即无法使用ffmpeg。
本文介绍把ffmpeg改造成库文件,然后通过JNI调用它,即可实现在Java中使用ffmpeg命令。
PS:
本工程依赖于前文Android 编译FFmpeg x264。
1. ffmpeg
1.1 main to run
(1)ffmpeg.h
进入ffmpeg源代码,修改ffmpeg.h,在文件中添加一下代码:
#ifdef FFMPEG_RUN_LIB
int run(int argc, char** argv);
#endif
(2)ffmpeg.c
修改ffmpeg.c
把
int main(int argc, char** argv)
替换为
#ifdef FFMPEG_RUN_LIB
int run(int argc, char **argv)
#else
int main(int argc, char** argv)
#endif
1.2 ffmpeg cleanup
ffmpeg 在清理阶段虽然把各个变量释放掉了,但是并没有将其置为null,会出现问题。
修改ffmpeg_cleanup函数,具体修改方法就是当调用av_freep函数后,在把变量设置为NULL。部分代码如下:
2. 修复直接退出进程
如果只完成上面修改的话,在执行ffmpeg命令会直接结束,因为原始工程作为一个进程,运行结束会进行垃圾回收,以及结束进程。
解决方法:
找到cmdutils文件,用longjmp替换exit方法
具体操作如下:
(1)修改cmdutils.c
在文件include代码块底部添加一下代码:
#ifdef FFMPEG_RUN_LIB
#include <setjmp.h>
extern jmp_buf jmp_exit;
#endif
找到并修改exit_program函数:
void exit_program(int ret)
{
if (program_exit)
program_exit(ret);
#ifdef FFMPEG_RUN_LIB
av_log(NULL, AV_LOG_INFO, "exit_program code : %d\n", ret);
longjmp(jmp_exit, ret);
#else
exit(ret);
#endif
}
(2)修改ffmpeg.c
把
exit()
函数替换为
exit_program()
(3) 添加ffmpeg_cmd文件
ffmpeg_cmd.h
//
// Created by Taylor Guo on 16/6/24.
//
#ifndef FFMPEG_BUILD_LIB_FFMPEG_MAIN_H
#define FFMPEG_BUILD_LIB_FFMPEG_MAIN_H
int run_cmd(int argc, char** argv);
#endif //FFMPEG_BUILD_LIB_FFMPEG_MAIN_H
ffmpeg_cmd.c
//
// Created by Taylor Guo on 16/6/24.
//
#include <setjmp.h>
#include "ffmpeg_cmd.h"
#include "ffmpeg.h"
#include "cmdutils.