在Android 中使用FFmpeg命令

作者: maimingliang | 来源:发表于2017-07-31 22:05 被阅读530次

    如何编译FFmpeg 并且引入Android Studio

    如何在Android 中使用FFmpeg命令 ?

    Github 项目源码 ffmpeglibrary 如果喜欢😍star走一个。

    在FFmpeg目录在找到

    cmdutils.c cmdutils.h cmdutils_common_opts.h config.h ffmpeg.c ffmpeg.h ffmpeg_filter.c ffmpeg_opt.c(注意:config.h需要编译后才有)到 cpp 目录下。

    把FFmpeg 下面的文件也需要copy 到 cpp下

    100011.png

    修改部分文件

    修改cmdutils.c 和 cmdutils.h
    找到cmdutils.c中的exit_program函数
    修改前:

    int 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;
    }
    
    

    找到cmdutils.h中exit_program的申明,也把返回类型修改为int:如下:

    int exit_program(int ret);
    

    修改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);(需要和ffmpeg.c 所起名字保持一致)

    编写文件调用:

    JNIEXPORT jint JNICALL
    Java_com_maiml_ffmpeglibrary_FFmpeg_run(JNIEnv *env, jobject instance, jobjectArray commands) {
    
        // TODO
        av_log_set_callback(my_logcat);
    
        int argc = env->GetArrayLength(commands);
        char *argv[argc];
        int i;
        for (i = 0; i < argc; i++) {
            jstring js = (jstring) env->GetObjectArrayElement(commands, i);
            argv[i] = (char *) env->GetStringUTFChars(js, 0);
        }
        return run_command(argc, argv);
    }
    

    到这里就可以运行FFmpeg命令了。一直我也是这样使用,但是我在做这个项目Cut的时候发现连续调用多次FFmpeg命令会报错(在项目需要,先改变分镜头的速度,再合成视频)。
    为什么会这样的呢?
    FFmpeg每次执行完命令后会调用 ffmpeg_cleanup 函数清理内存,并且会调用exit(0)结束当前进程,但是经过我们的修改,exit()的代码已经被删掉,而我们的App还在运行,不能杀死进程,所以有些变量的值还在内存中,这样就会导致下次执行的时候可能会出错。
    打开ffmpeg.c找到刚修改的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;
    

    参考文章
    FFmpeg
    编译Android下可执行命令的FFmpeg

    END。

    相关文章

      网友评论

      • 冰冰的冻结:我编译的so,移植到studio里找不到好多文件
      • Tyhj:终于成功了,准备刚才躺在床上的时候用手机搜了一下,发现上面这篇文章,后面的坑点里面有讲程序崩溃这个问题,其实就是改这个函数:
        int exit_program(int ret)
        {
        return ret;
        }
        其实这个东西想要马上搞好是很难的,我用FFmpeg3.0,其中有些东西和楼主不完全一样的,就是要自己去编译,去发现,少什么东西就加什么东西
        楼主最后提到解决不能重复使用的解决方案非常好
        Tyhj:这篇文章:http://www.jianshu.com/p/ceaa286d8aff
      • Tyhj:照着你的方法和源码搞了一天终于成功了,我主要是用来mp4转GIF的,之前用一个别人写好的FFmpeg的包只能调用一次 ,但是现在调用里面的方法,一次成功后直接崩溃,和二楼的情况相似?请问有什么解决办法吗?
      • Muse_Ykh:编译通不过,求解
        Error:(75) undefined reference to 'run' (这是是我修改过后代替的main函数)
        Error:(132) undefined reference to 'ANativeWindow_fromSurface'
        Error:(139) undefined reference to 'ANativeWindow_setBuffersGeometry'
        Error:(193) undefined reference to 'ANativeWindow_l
        Error:(212) undefined reference to 'ANativeWindow_unlockAndPost'

        猜测是编译的时候引用不到ffmpeg和native_window_jni头文件以及对应的实现函数
        Muse_Ykh: @Muse_Ykh 引用了,再ide下也能链接进去
        maimingliang:头文件引用了吗?
        #include "android/native_window_jni.h"
        #include "android/native_window.h"
      • Muse_Ykh:问下调用文件那边的run_command方法在哪定义?
        Muse_Ykh:看了参考,好像弄明白了,run_command就是对应刚刚ffmpeg.c 里的被修改过后的int main()方法吧?
      • 南风无影:Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 7201 (pool-1-thread-1)
        Tyhj:http://www.jianshu.com/p/ceaa286d8aff
        我终于成功了,准备刚才躺在床上的时候用手机搜了一下,发现上面这篇文章,后面的坑点里面有讲这个问题,其实就是改这个函数:
        int exit_program(int ret)
        {
        return ret;
        }
        楼主这个方法我用FFmpeg3.0来搞的,搞了很久,文件略有不同,但是楼主最后提到解决不能重复使用的解决方案也是非常棒的
        Tyhj:我也是这个问题,你解决了吗

      本文标题:在Android 中使用FFmpeg命令

      本文链接:https://www.haomeiwen.com/subject/rivklxtx.html