android - 调用 ffmpeg.c 的 main 两次导致应用程序崩溃

标签 android ffmpeg

使用 FFmpeg 4.0.2 并调用其 ffmpeg.c 的 main 函数两次会导致 Android 应用程序崩溃(使用 FFmpeg 共享库和 JNI)

A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 20153

尽管它适用于 FFmpeg 3.2.5

FFmpeg 4.0.2主要

int main(int argc, char **argv) {
    int i, ret;
    int64_t ti;

    init_dynload();

    register_exit(ffmpeg_cleanup);

    setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */

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

#if CONFIG_AVDEVICE
    avdevice_register_all();
#endif
    avformat_network_init();

    show_banner(argc, argv, options);

    /* parse options and open all input/output files */
    ret = ffmpeg_parse_options(argc, argv);
    if (ret < 0)
        exit_program(1);

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

    /* file converter / grab */
    if (nb_output_files <= 0) {
        av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
        exit_program(1);
    }

//     if (nb_input_files == 0) {
//         av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
//         exit_program(1);
//     }

    for (i = 0; i < nb_output_files; i++) {
        if (strcmp(output_files[i]->ctx->oformat->name, "rtp"))
            want_sdp = 0;
    }

    current_time = ti = getutime();
    if (transcode() < 0)
        exit_program(1);
    ti = getutime() - ti;
    if (do_benchmark) {
        av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0);
    }
    av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
           decode_error_stat[0], decode_error_stat[1]);
    if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1])
        exit_program(69);

    ffmpeg_cleanup(received_nb_signals ? 255 : main_return_code);
    return main_return_code;
}

FFmpeg 3.2.5主要

int main(int argc, char **argv) {
    av_log(NULL, AV_LOG_WARNING, " Command start");

    int i, ret;
    int64_t ti;
    init_dynload();

    register_exit(ffmpeg_cleanup);

    setvbuf(stderr, NULL, _IONBF, 0); /* win32 runtime needs this */

    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();
#if CONFIG_AVDEVICE
    avdevice_register_all();
#endif
    avfilter_register_all();
    av_register_all();
    avformat_network_init();

    av_log(NULL, AV_LOG_WARNING, " Register to complete the codec");

    show_banner(argc, argv, options);

    /* parse options and open all input/output files */
    ret = ffmpeg_parse_options(argc, argv);
    if (ret < 0)
        exit_program(1);

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

    /* file converter / grab */
    if (nb_output_files <= 0) {
        av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
        exit_program(1);
    }

//     if (nb_input_files == 0) {
//         av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
//         exit_program(1);
//     }

    for (i = 0; i < nb_output_files; i++) {
        if (strcmp(output_files[i]->ctx->oformat->name, "rtp"))
            want_sdp = 0;
    }

    current_time = ti = getutime();
    if (transcode() < 0)
        exit_program(1);
    ti = getutime() - ti;
    if (do_benchmark) {
        av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0);
    }
    av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
           decode_error_stat[0], decode_error_stat[1]);
    if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1])
        exit_program(69);

    exit_program(received_nb_signals ? 255 : main_return_code);

    nb_filtergraphs = 0;
    nb_input_streams = 0;
    nb_input_files = 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;

    return main_return_code;
}

那么可能出现什么问题呢? FFmpeg 4.0.2 似乎没有释放某些东西(在第一个命令后将资源或其静态变量恢复为初始值)

最佳答案

将从 FFmpeg 3.2.5 到 FFmpeg 4.0.2 的下一行添加到主函数的末尾解决了问题(我下载了 FFmpeg 3.2.5 作为某人的 Android 项目,以便用户添加了这些行)

nb_filtergraphs = 0;
nb_input_streams = 0;
nb_input_files = 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;

关于android - 调用 ffmpeg.c 的 main 两次导致应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52916376/

相关文章:

android - 我无法添加新的/更新的 Android SDK 管理器内容

android - adb 在 Windows 上未被识别为内部或外部命令

android - 如何同时按下两个(或更多)按钮

ffmpeg - 从网络摄像头编码未压缩的 avi

ffmpeg - 要求ffmpeg以原始帧速率提取帧

android - 在android中动态更改SVG图像颜色

android - 使用 mupdf 将 Pdf 页面转换为图像

video - 如何使用ffmpeg在视频中心添加透明水印?

merge - 我想加入两个 ffmpeg 命令来收集

iphone - FFmpeg + iPhone - 有趣(不正确?)的视频编码结果