HarmonyOS 鸿蒙Next求大佬帮忙分析下为什么ffmpeg会闪退
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。