最近边搞tensorflow边搞ffmpeg,心好累
想在android上执行ffmpeg命令,就开始研究,结果中间公司给任务帮web端搞tensorflow,所以东一下西一下,不过差不多同时完成,也算不错
网上资料很多,可是我按他们的来总是一堆错误,不过都跨过去了
想在android上执行ffmpeg命令需要一个已经编译过的ffmpeg源码,编译网上资料很多,想了想有空还是写一篇关于编译的博客吧
先做好备份
复制ffmpeg.h,ffmpeg.c,cmdutils.h,cmdutils.c,ffmpeg_filter.c,ffmpeg_opt.c到项目的cpp文件夹
然后在
源码内删除这些文件,没错就是删除这些文件,不然会报错,这个错误我搞了很久,网上都是复制没有删除,可我就是报错,删了就OK
修改ffmpeg.c与ffmpeg.h
把ffmpeg.c的int main(int argc, char argv) 改名为 int run(int argc, char argv)
在ffmpeg.h内添加
int run(int argc, char **argv);
在run函数内的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;
修改cmdutils.c 和 cmdutils.h
找到cmdutils.c中的exit_program函数,把exit_program函数改成
找到cmdutils.c中的exit_program函数,把exit_program函数改成
int exit_program(int ret) { if (program_exit) program_exit(ret); return ret; }
再在cmdutils.h修改
int exit_program(int ret) av_noreturn;
改成
int exit_program(int ret);
改好后开始写代码
在CMakeLists.txt代码
add_library( ffmpeg_run SHARED src/main/cpp/ffmpeg_run.cpp src/main/cpp/ffmpeg.c src/main/cpp/cmdutils.c src/main/cpp/ffmpeg_filter.c src/main/cpp/ffmpeg_opt.c) find_library( log-lib log ) set(distribution_DIR ../../../../libs) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") set(CMAKE_VERBOSE_MAKEFILE on) include_directories(C:/f/ffmpeg-3.3.2) add_library( avcodec-57 SHARED IMPORTED) add_library( avdevice-57 SHARED IMPORTED) add_library( avfilter-6 SHARED IMPORTED) add_library( avformat-57 SHARED IMPORTED) add_library( avutil-55 SHARED IMPORTED) add_library( swresample-2 SHARED IMPORTED) add_library( swscale-4 SHARED IMPORTED) set_target_properties( avcodec-57 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libavcodec-57.so) set_target_properties( avdevice-57 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libavdevice-57.so) set_target_properties( avfilter-6 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libavfilter-6.so) set_target_properties( avformat-57 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libavformat-57.so) set_target_properties( avutil-55 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libavutil-55.so) set_target_properties( swresample-2 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libswresample-2.so) set_target_properties( swscale-4 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libswscale-4.so) target_link_libraries( ffmpeg_run avcodec-57 avdevice-57 avfilter-6 avformat-57 avutil-55 swresample-2 swscale-4 ${log-lib} android)
include_directories自己的ffmpeg源码路径
java代码FfmpegCmd.java
public class FfmpegCmd { static { System.loadLibrary("ffmpeg_run"); } public static native int ffmpegRun(String[] cmd); }
c++代码
extern "C" JNIEXPORT jint JNICALL Java_com_ffmpeg_run_FfmpegCmd_ffmpegRun(JNIEnv *env, jobject instance, jobjectArray cmd) { // TODO int argc = env->GetArrayLength(cmd); char *argv[argc]; int i; for (i = 0; i < argc; i++) { jstring js = (jstring) env->GetObjectArrayElement(cmd, i); argv[i] = (char *) env->GetStringUTFChars(js, 0); } return run(argc,argv); }
执行代码
Thread thread = new Thread(){ @Override public void run() { super.run(); String base = "/storage/emulated/0/360"; String[] commands = new String[16]; commands[0] = "ffmpeg"; commands[1] = "-i"; commands[2] = base + "/test10086.mp4"; commands[3] = "-r"; commands[4] = "5"; commands[5] = "-q:v"; commands[6] = "2"; commands[7] = "-s"; commands[8] = "1280x720"; commands[9] = "-ss"; commands[10] = "0:0:0"; commands[11] = "-t"; commands[12] = "0:0:15"; commands[13] = "-f"; commands[14] = "image2"; commands[15] = base + "/merge%d.png"; FfmpegCmd.ffmpegRun(commands); } }; thread.start();
完成,中间还碰到其他问题,一时想不起来在哪里,就简单说一下
有一个参数名是class,编译会报错,说在()内有错误,坑死了,把这个参数改成avClass
还有个错误是报什么c++11错误
是一个什么64的宏和双引号"太近了,加个空格就OK了