记录一次ffmpeg崩溃问题的查找
一个利用ffmpeg编码推送rtmp流的库,如果没有发送音视频数据给它编码直接关闭,在delphi下被调用时发生了崩溃,而在vc下被调用是正常的。崩溃时的调用栈显示
未知函数
avcodec_close
avcodec_free_context
而崩溃的信息为 Invalid floating point operation。通过加日志,发现发生崩溃的avcodec是一个aac的编码器,在它之前运行的x264编码器avcodec_free_context调用是正常的。由于是浮点操作非法,第一感觉是发生在codec之中,而不是ffmpeg外围的其他函数,因为外围函数应该不需要用到浮点运算。
查看avcodec_close的实现
https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/utils.c
当中有一行
if (avctx->codec && avctx->codec->close)
avctx->codec->close(avctx);
这里调用了codec自己的close函数。再看aac编码器的close函数
static av_cold int aac_encode_end(AVCodecContext *avctx)
{
AACEncContext *s = avctx->priv_data;
av_log(avctx, AV_LOG_INFO, "Qavg: %.3f\n", s->lambda_sum / s->lambda_count);
ff_mdct_end(&s->mdct1024);
ff_mdct_end(&s->mdct128);
ff_psy_end(&s->psy);
ff_lpc_end(&s->lpc);
if (s->psypp)
ff_psy_preprocess_end(s->psypp);
av_freep(&s->buffer.samples);
av_freep(&s->cpe);
av_freep(&s->fdsp);
ff_af_queue_close(&s->afq);
return 0;
}
很明显因为没有编码过,所以lambda_count为0,因此发生了除0出错。但是为什么vc下面不会报错呢?写一个最简单的vc程序,看一下除0问题
float a = 2;
float b = 0;
float c = a / b;
这样的程序是可以正常运行的。但是把float类型换成int,就会报除0出错了。另一位同事在网上找到了参考信息
https://www.cnblogs.com/findumars/p/5345503.html
看来是delphi默认的浮点设置导致了不允许浮点除0。当然,通过更深入的查找,vc里面也是可以设置打开浮点异常的
https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/e9b52ceh(v=vs.100)
加一句 _control87(0, _MCW_EM); 就可以打开所有的浮点异常