HarmonyOS 鸿蒙Next求大佬帮忙分析下为什么ffmpeg会闪退

发布于 1周前 作者 yuanlaile 来自 鸿蒙OS

HarmonyOS 鸿蒙Next求大佬帮忙分析下为什么ffmpeg会闪退
<markdown _ngcontent-dwe-c237="" class="markdownPreContainer">

我编译ffmpeg到so, 然后使用官方的ffmpeg.c更改了其中的int main方法

int exe_ffmpeg_cmd(int argc, char **argv, Callbacks* callback)
{
    int i, ret;
    BenchmarkTimeStamps 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(ret);
        main_return_code = 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);
        main_return_code = 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);
        main_return_code = 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 = get_benchmark_time_stamps();
    if (transcode(callback) < 0) {
        exit_program(1);
        main_return_code = 1;
    }
    if (do_benchmark) {
        int64_t utime, stime, rtime;
        current_time = get_benchmark_time_stamps();
        utime = current_time.user_usec - ti.user_usec;
        stime = current_time.sys_usec  - ti.sys_usec;
        rtime = current_time.real_usec - ti.real_usec;
        av_log(NULL, AV_LOG_INFO,
               "bench: utime=%0.3fs stime=%0.3fs rtime=%0.3fs\n",
               utime / 1000000.0, stime / 1000000.0, rtime / 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);
        main_return_code = 69;
    }

    //exit_program(received_nb_signals ? 255 : main_return_code);
    ffmpeg_cleanup(0);
    return main_return_code;
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

去掉了其中的exit_program的中断退出方法

int exit_program(int ret)
{
    if (program_exit)
        program_exit(ret);
//<span class="hljs-keyword"><span class="hljs-keyword">exit</span></span>(ret);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> ret;

} <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

按道理是不会闪退的吧? 正常运行命令没问题, 但是只要ffmpeg的命令运行出错, 比如输入的文件不存在, 输入的文件内容错误就会闪退. 闪退的报错很诡异 是在打印日志的地方闪退

void log_call_back(void *ptr, int level, const char *fmt, va_list vl) {
    static int print_prefix = 1;
    static int count;
    static char prev[1024];
    char line[1024];
    static int is_atty;
    av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix);
    strcpy(prev, line);
    OH_LOG_ERROR(LOG_APP, "========> %{public}s", line);
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

大概是strcpy这些位置会闪退

 strcpy(prev, line);
 OH_LOG_ERROR(LOG_APP, "========> %{public}s", line);
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

请问各位有什么思路吗?

</markdown>
11 回复
大佬能分享一下 编译配置参数吗

大佬,求一个demo+编译好的ffmpeg,或者有教程也可以,万分感谢

这么巧听嘛, 早上地铁上已经看了😄

解决问题了

int exit_program(int ret);// av_noreturn;<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

注销掉这个av_noreturn即可

double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max) {
    return 1;
    /*char *tail;
    const char *error;
    double d = av_strtod(numstr, &tail);
    if (*tail)
        error = "Expected number for %s but found: %s\n";
    else if (d < min || d > max)
        error = "The value for %s was %s which is not within %f - %f\n";
    else if (type == OPT_INT64 && (int64_t)d != d)
        error = "Expected int64 for %s but found %s\n";
    else if (type == OPT_INT && (int)d != d)
        error = "Expected int for %s but found %s\n";
    else
        return d;
    av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
    exit_program(1);
    return 0;*/
}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

注释掉这里 解决

比如我故意输错 输入文件, 闪退日志

Reason:Signal:SIGSEGV(SEGV_MAPERR)@0x0000000000000040  probably caused by NULL pointer dereference
Fault thread info:
Tid:38541, Name:OS_FFRT_2_0
#00 pc 00000000000a9250 /system/lib/ld-musl-aarch64.so.1(strnlen+16)(8a1c8fdb77a87447175a6a93ae26dea2)
#01 pc 00000000001a7af8 /system/lib/ld-musl-aarch64.so.1(printf_core+2180)(8a1c8fdb77a87447175a6a93ae26dea2)
#02 pc 00000000001a70ec /system/lib/ld-musl-aarch64.so.1(vfprintf+188)(8a1c8fdb77a87447175a6a93ae26dea2)
#03 pc 00000000001b16e8 /system/lib/ld-musl-aarch64.so.1(vsnprintf+164)(8a1c8fdb77a87447175a6a93ae26dea2)
#04 pc 000000000033164c /data/storage/el1/bundle/libs/arm64/libffmpegutils.so(av_vbprintf+84)(80c006cba7c47080df7a03cb3661c89981c6b26c)
========SubmitterStacktrace========
#00 pc 0000000000013c08 /system/lib64/platformsdk/libuv.so(uv_queue_work+80)(5e97289dc82f6e538b08c684a9dca4a8)
#01 pc 0000000000057aa8 /system/lib64/platformsdk/libace_napi.z.so(NativeAsyncWork::Queue()+196)(b6e1f7201887fd380757eb122af83fe1)
#02 pc 000000000005f794 /system/lib64/platformsdk/libace_napi.z.so(napi_queue_async_work+36)(b6e1f7201887fd380757eb122af83fe1)<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

打印的ffmpeg日志如下:

 [DEBUG:napi_pfunction_binder.h(30)] NapiPFunctionBinder::Wrapper
con.xxxx...s.peiyin  E     ========> Splitting the commandline.
con.xxxx...s.peiyin  E     ========> Reading option '-y' ...
con.xxxx...s.peiyin  E     ========>  matched as option 'y' (overwrite output files) with argument '1'.
con.xxxx...s.peiyin  E     ========> Reading option '-i' ...
con.xxxx...s.peiyin  E     ========>  matched as input url with argument '/data/storage/el2/base/haps/entry/files/ai/temp.mp3'.
con.xxxx...s.peiyin  E     ========> Reading option '-i' ...
con.xxxx...s.peiyin  E     ========>  matched as input url with argument '/data/storage/el2/base/haps/entry/cache/video-cache/f1014926aab513d2632b776ec3f83a13.mp3'.
con.xxxx...s.peiyin  E     ========> Reading option '-ii' ...
con.xxxx...s.peiyin  E     ========> Unrecognized option 'ii'.
con.xxxx...s.peiyin  E     ========> Error splitting the argument list: 
========> Option not found
========> call term_exit<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

请问您是怎么编译成功的,参考的官方的教程吗?

HarmonyOS中ffmpeg闪退可能由多种原因引起,如内存不足、线程冲突、资源未正确释放或版本不兼容等。建议首先检查ffmpeg库的版本与HarmonyOS的兼容性,确保使用的库是专为HarmonyOS优化或至少是兼容的版本。其次,检查ffmpeg的调用方式,确保没有在主线程执行耗时操作或未处理的异常。此外,还应查看应用的日志输出,查找可能的错误信息和堆栈跟踪,以便精确定位问题。如果问题依旧没法解决,请加我微信,我的微信是itying888。

回到顶部