android studio ffmpeg简单使用(命令行)

大鹏一日同风起,扶摇直上九万里。这篇文章主要讲述android studio ffmpeg简单使用(命令行)相关的知识,希望能为你提供帮助。
编译ffmpeg
android studio 新建项目,勾选上

android studio ffmpeg简单使用(命令行)

文章图片

将编译好的libffmpeg.so库扔到src/main/jniLibs/armeabi下(主要这里我只编译了arm的ffmpeg的库) 
新建文件com.jni.FFmpegCmd
package com.jni; public class FFmpegCmd {static { System.loadLibrary("ffmpeg"); System.loadLibrary("ffmpeg-cmd"); }public static native int run(String[] commands); }

  在cpp下 (即有native-lib.cpp的目录) 创建一个ffmpeg-cmd.cpp文件
#include < jni.h> #include "ffmpeg.h" #include "android_log.h"extern "C" JNIEXPORT jint JNICALL java_com_jni_FFmpegCmd_run(JNIEnv *env, jobject, jobjectArray commands) { int argc = env-> GetArrayLength(commands); char *argv[argc]; for (int i = 0; i < argc; i++) { jstring js = (jstring) env-> GetObjectArrayElement(commands, i); argv[i] = (char *) env-> GetStringUTFChars(js, 0); } LOGD("============开始执行命令行==========="); return main(argc, argv); }

android_log.h
#ifdef ANDROID #include < android/log.h> #ifndef LOG_TAG #defineMY_TAG"MYTAG" #defineAV_TAG"AVLOG" #endif #define LOGE(format, ...)__android_log_print(ANDROID_LOG_ERROR, MY_TAG, format, ##__VA_ARGS__) #define LOGD(format, ...)__android_log_print(ANDROID_LOG_DEBUG,MY_TAG, format, ##__VA_ARGS__) #defineXLOGD(...)__android_log_print(ANDROID_LOG_INFO,AV_TAG,__VA_ARGS__) #defineXLOGE(...)__android_log_print(ANDROID_LOG_ERROR,AV_TAG,__VA_ARGS__) #else #define LOGE(format, ...)printf(MY_TAG format "\\n", ##__VA_ARGS__) #define LOGD(format, ...)printf(MY_TAG format "\\n", ##__VA_ARGS__) #define XLOGE(format, ...)fprintf(stdout, AV_TAG ": " format "\\n", ##__VA_ARGS__) #define XLOGI(format, ...)fprintf(stderr, AV_TAG ": " format "\\n", ##__VA_ARGS__) #endif

 
拷贝ffmpeg源码文件  cmdutils.c  cmdutils.h  ffmpeg.cffmpeg_filter.cffmpeg_opt.c  ffmpeg_hw.c 到cpp目录下
(ffmpeg-3.4之前的版本 不需要ffmpeg_hw.c文件,但是需要cmdutils_common_opts.h文件)
ffmpeg编译后的文件夹include lib也拷贝到该目录
android studio ffmpeg简单使用(命令行)

文章图片

修改ffmpeg.h  在最后添加      int main(int argc, char **argv);
android studio ffmpeg简单使用(命令行)

文章图片

修改ffmpeg.c
在main方法最后添加(听说是为了防止为了重复执行ffmpeg命令闪退问题)
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.h

修改前void exit_program(int ret) av_noreturn; 修改后int exit_program(int ret); 修改前void show_help_children(const AVClass *class, int flags); //不修改的话编译一直出错 (可能是class关键字的原因,关键字不能当变量使用) 修改后void show_help_children(const AVClass *avClass, int flags);

修改cmdutils.c
修改前 void exit_program(int ret) { if (program_exit) program_exit(ret); exit(ret); } 修改后 int exit_program(int ret) { if (program_exit) program_exit(ret); return ret; }

  CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)add_library(ffmpeg-cmd SHARED src/main/cpp/cmdutils.c src/main/cpp/ffmpeg.c src/main/cpp/ffmpeg_filter.c src/main/cpp/ffmpeg_opt.c src/main/cpp/ffmpeg_hw.c src/main/cpp/ffmpeg-cmd.cpp)find_library(log-lib log android)
#这里红色部分对应上面拷贝的两个文件夹路径,这里也可以不用拷贝这两个文件夹,直接把下面两行红色部分给成你电脑上编译好的ffmpeg的include和lib的路径 include_directories(src/main/cpp/include src/main/cpp/lib E:/ffmpeg/4.0/build/ffmpeg-4.0) add_library(ffmpeg SHARED IMPORTED) set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION E:/ffmpeg/4.0/build/android/arm/libffmpeg.so)target_link_libraries( ffmpeg-cmd ffmpeg android ${log-lib} )

  build.gradle(Module:app)
android studio ffmpeg简单使用(命令行)

文章图片

这里主要需要处理红色圈圈部分,其他部分都是自动生成的
最后在MainActivity.java 测试一下
public class MainActivity extends AppCompatActivity {private ExecutorService es = Executors.newSingleThreadExecutor(); String path = Environment.getExternalStorageDirectory().getPath(); private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { "android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE" }; private ProgressDialog progressDialog; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
try { //检测是否有写的权限 int permission = ActivityCompat.checkSelfPermission(activity, "android.permission.WRITE_EXTERNAL_STORAGE"); if (permission != PackageManager.PERMISSION_GRANTED) { // 没有写的权限,去申请写的权限,会弹出对话框 ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE); } } catch (Exception e) { e.printStackTrace(); }tv = findViewById(R.id.sample_text); tv.setText("测试"); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { progressDialog = ProgressDialog.show(MainActivity.this,"","处理中"); new Thread(new Runnable() { @Override public void run() { String str = "ffmpeg -i %s -vcodec copy -f mpegts -y %s"; //mp4 转 ts-y如果有同名名则覆盖文件。不加-y则会提示有同名文件是否覆盖,这里再次执行的话会闪退 String commandStr = String.format(str,path+"/data/qq.mp4",path+"/data/qq.ts"); String[] commands = commandStr.split("\\\\s+"); for(String command:commands){ Log.d(MainActivity.class.getName(),"command="+command); } final int sum = FFmpegCmd.run(commands); new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if(sum == 0){ if(progressDialog != null){ progressDialog.dismiss(); } tv.setText("处理成功"); }else{ tv.setText("处理失败"); } } }); } }).start(); } }); }}

 
  AndroidManifest.xml 需要添加权限
< !--网络连接--> < uses-permission android:name="android.permission.INTERNET" /> < !--sd卡读写6.0以上系统可能还需要动态申请sd卡读写权限--> < uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> < uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

【android studio ffmpeg简单使用(命令行)】 

    推荐阅读