標籤:gets sts flags external lte dex str blog form
編譯ffmpeg
android studio 建立項目,勾選上
將編譯好的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 JNICALLJava_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#define MY_TAG "MYTAG"#define AV_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__)#define XLOGD(...) __android_log_print(ANDROID_LOG_INFO,AV_TAG,__VA_ARGS__)#define XLOGE(...) __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也拷貝到該目錄
修改ffmpeg.h 在最後添加 int main(int argc, char **argv);
修改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);//不修改的話編譯一直出錯 不清楚什麼原因修改後 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)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)
該主要需要處理紅色部分,其他部分都是自動產生的
最後在MainActivity.java 測試一下
public class MainActivity extends AppCompatActivity { private ExecutorService es = Executors.newSingleThreadExecutor(); String path = Environment.getExternalStorageDirectory().getPath(); private ProgressDialog progressDialog; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); 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(); } }); }}
android studio ffmpeg簡單使用(命令列)