• android studio ffmpeg简单使用 (cmake)


    编译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 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
    #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 "
    ", ##__VA_ARGS__)
    #define LOGD(format, ...)  printf(MY_TAG format "
    ", ##__VA_ARGS__)
    #define XLOGE(format, ...)  fprintf(stdout, AV_TAG ": " format "
    ", ##__VA_ARGS__)
    #define XLOGI(format, ...)  fprintf(stderr, AV_TAG ": " format "
    ", ##__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);//不修改的话编译一直出错 (可能是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)

    这里主要需要处理红色圈圈部分,其他部分都是自动生成的

    最后在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" />
  • 相关阅读:
    【Java Web】使用URLRewrite实现网站伪静态
    Jsp的include指令静态导入和动态导入的区别
    JSP中使用cookie存储中文
    【转】android加载大量图片内存溢出的三种解决办法
    Android调整TimePicker和DatePicker大小
    使用WebClient实现通讯(Silverlight学习笔记)
    Silverlight 用户控件与自定义控件详解
    利用WebClient和WebRequest类获得网页源代码
    Silverlight中的对象序列化/反序列化
    Flex与FLASH区别及Flex动画效果学习
  • 原文地址:https://www.cnblogs.com/rchao/p/8973966.html
Copyright © 2020-2023  润新知