记录一次ffmpeg崩溃问题的查找

2021-04-16  本文已影响0人  叶迎宪

一个利用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); 就可以打开所有的浮点异常

https://stackoverflow.com/questions/39684161/why-an-application-starts-with-fpu-control-word-different-than-default8087cw

上一篇 下一篇

猜你喜欢

热点阅读