【问题标题】:How to execute command line ffmpeg commands programatically in android?如何在android中以编程方式执行命令行ffmpeg命令?
【发布时间】:2013-08-14 18:34:37
【问题描述】:

我已经使用bambuser 成功地为 android 构建了 ffmpeg .现在我必须构建一个示例转换器应用程序,例如 mp4 到 3gp。我知道有命令行命令ffmpeg -i video_origine.avi video_finale.mpg。但我不知道如何以编程方式执行这些命令。我有像

这样的示例代码
jint Java_com_example_ndklearning1_MainActivity_logFileInfo(JNIEnv * env, jobject this, jstring filename)
{
    av_register_all();

    AVFormatContext *pFormatCtx;
    const jbyte *str;
    str = (*env)->GetStringUTFChars(env, filename, NULL);

    if(av_open_input_file(&pFormatCtx, str, NULL, 0, NULL)!=0)
    {
        LOGE("Can't open file '%s'\n", str);
        return 1;
    }
    else
    {
        LOGI("File was opened\n");
        LOGI("File '%s', Codec %s",
            pFormatCtx->filename,
            pFormatCtx->iformat->name
        );

    }
    return 0;
}

此代码打开一个文件并提取编解码器信息。我想要的只是将打开的文件转换为所需的格式。任何形式的帮助,例如代码 sn-p 或要遵循的步骤,都将受到高度赞赏。

ffmpeg API 可以达到我的目的吗?如果有现成的 API 可用,会更有帮助

【问题讨论】:

    标签: android android-ndk ffmpeg media codec


    【解决方案1】:

    最近我遇到了类似的问题。我的解决方案是在Java程序中模拟命令行。

    首先,我在“ffmpeg.c”文件中添加一个函数:

    int cmd_simulation(int argc, const char** argv)
    {
    OptionsContext o = { 0 };
    // int64_t ti;
    
    reset_options(&o, 0);
    
    av_log_set_flags(AV_LOG_SKIP_REPEATED);
    parse_loglevel(argc, argv, options);
    
    if(argc>1 && !strcmp(argv[1], "-d")){
        run_as_daemon=1;
        av_log_set_callback(log_callback_null);
        argc--;
        argv++;
    }
    
    avcodec_register_all();
    
    avfilter_register_all();
    av_register_all();
    avformat_network_init();
    
    //show_banner(argc, argv, options);
    
    term_init();
    
    parse_cpuflags(argc, argv, options);
    
    /* parse options */
    parse_options(&o, argc, argv, options, opt_output_file);
    
    if (nb_output_files <= 0 && nb_input_files == 0) {
        show_usage();
        av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
        exit_program(1);
    }
    
    
    if (nb_output_files <= 0) {
        av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
        exit_program(1);
    }
    
    if (transcode() < 0)
        exit_program(1);
    
    //exit_program(0);
    return 7;
    }
    

    其实这个函数只是主函数的一个拷贝,稍加修改。

    然后创建一个原生函数:

    extern const char* cmd_simulation(int, const char**);
    
    JNIEXPORT int JNICALL Java_com_test_videowatermark_VideoUtil_test(JNIEnv * env, jobject object, jobjectArray strArray);
    
    
    
    JNIEXPORT int JNICALL Java_com_test_videowatermark_VideoUtil_test(JNIEnv * env, jobject object, jobjectArray strArray)
    {
        int arrayLength = (*env)->GetArrayLength(env, strArray);
        const char* args[arrayLength];
    
        int i;
        for(i = 0; i < arrayLength; i++){
            jstring jstr = (jstring)((*env)->GetObjectArrayElement(env, strArray, i));
            args[i] = (*env)->GetStringUTFChars(env, jstr, 0);
            //strcpy(args[i], arg);
            //env->ReleaseStringUTFChars(jstr, arg);
        }
    
    
        const char** argv = args;
        return  cmd_simulation(arrayLength, argv);  
    
    }
    

    使用ffmpeg编译后,可以模拟执行ffmpeg命令如下:

    private void executeCommand(){
        String[] command = {"ffmpeg", "-i", "some video file name",};
        int result = test(command);     
    }
    

    希望这会有所帮助!

    编辑: 安卓.mk

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale libswresample libavfilter
    LOCAL_MODULE    := VideoUtilLib
    LOCAL_SRC_FILES := NativeVideoUtil.c ffmpeg.c ffmpeg_opt.c cmdutils.c ffmpeg_filter.c
    LOCAL_LDLIBS := -lz -llog
    include $(BUILD_SHARED_LIBRARY)
    include $(call all-makefiles-under,$(LOCAL_PATH))
    

    将 NativeVideoUtil.c 替换为您的原生文件。

    【讨论】:

    • 很棒的方法!我会试试你的方法!我不在办公室,所以我必须等到明天早上。同时你能告诉我,修改后我是否必须为 android 重建 ffmpeg ?我需要在我的本机代码文件中包含任何头文件吗?
    • 你需要包含的头文件只有。我将在我的答案中发布我的 Android.mk。
    • 我收到此错误:08-14 05:30:11.729: W/dalvikvm(17973): PR_CAPBSET_DROP 0 failed: Invalid argument。请确保您的内核在编译时启用了文件功能支持。
    • 我直接用ffmpeg源代码编译了我的android项目。所以我没有遇到这个问题。也许你可以尝试用ffmpeg源代码编译。
    • 可以给我们编译好的ffmpeg源码吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 2014-10-27
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 2016-10-28
    相关资源
    最近更新 更多