【问题标题】:Decoder crashes after ffmpeg upgradeffmpeg升级后解码器崩溃
【发布时间】:2012-11-21 06:11:07
【问题描述】:

最近我将 ffmpeg 从 0.9 升级到 1.0(在 Win7x64 和 iOS 上测试),现在是 avcodec_decode_video2 seagfaults。长话短说:每次视频尺寸发生变化时都会发生崩溃(例如,从 320x240 变为 160x120,反之亦然)。

我从一些专有来源接收 mpeg4 视频流并像这样解码它:

// once, during initialization:
AVCodec *codec_ = avcodec_find_decoder(CODEC_ID_MPEG4);
AVCodecContext ctx_ = avcodec_alloc_context3(codec_);
avcodec_open2(ctx_, codec_, 0);
AVPacket packet_;
av_init_packet(&packet_);
AVFrame picture_ = avcodec_alloc_frame();

// on every frame:
int got_picture;
packet_.size = size;
packet_.data = (uint8_t *)buffer;
avcodec_decode_video2(ctx_, picture_, &got_picture, &packet_);

再一次,在我升级到 1.0 之前,上述所有操作都完美无缺。现在,每次框架尺寸发生变化时 - avcodec_decode_video2 都会崩溃。请注意,我没有在 AVCodecContext 中分配宽度/高度 - 无论是在开始时,还是在流更改时 - 这可能是原因吗?

如有任何想法,我将不胜感激!

更新:设置 ctx_.width 和 ctx_.height 没有帮助。

Update2:就在崩溃之前,我收到以下日志消息:

mpeg4,级别 24:“找到 2 个未释放的缓冲区!”。 级别 8:“断言 i buffer_count 在 libavcodec/utils.c:603 失败”

Update3 升级到 1.1.2 修复了这个崩溃问题。解码器能够再次处理动态的尺寸变化。

【问题讨论】:

  • 我认为“即时”更改帧大小是不正确的。以前可以使用的事实是一个意外。每次帧大小发生变化时,您都必须重新启动解码器。
  • @pogorskiy 多年来,它“偶然”地工作了很多年,经历了许多版本!我应该如何重新启动解码器?
  • @pogorskiy : 调用avcodec_close/avcodec_open2 解决了这个问题!请把你的评论作为答案,我会接受的。

标签: ffmpeg libavcodec


【解决方案1】:

您可以尝试填写AVPacket::side_data。如果您更改帧大小,编解码器会从中接收信息(请参阅libavcodec/utils.c apply_param_change function

这个结构可以填写如下:

int my_ff_add_param_change(AVPacket *pkt, int32_t width, int32_t height)
{
    uint32_t flags = 0;
    int size = 4 * 3;
    uint8_t *data;
    if (!pkt)
        return AVERROR(EINVAL);

    flags = AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS;
    data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size);

    if (!data)
        return AVERROR(ENOMEM);

    ((uint32_t*)data)[0] = flags;
    ((uint32_t*)data)[1] = width;
    ((uint32_t*)data)[2] = height;
    return 0;
}

每次大小变化时都需要调用这个函数。

我认为这个功能最近出现了。直到我查看了新的 ffmpeg 源,我才知道它。

UPD

在您编写时,解决问题的最简单方法是执行编解码器重新启动。只需拨打avcodec_close / avcodec_open2

【讨论】:

    【解决方案2】:

    当我的框架动态改变大小时,我遇到了同样的问题。但是,调用 avcodec_close/avcodec_open2 是多余的。更简洁的方法是在调用 avcodec_decode_video2 之前重置您的 AVPacket 数据结构。这是代码:

    av_init_packet(&packet_)

    这里的关键是该方法将 AVPacket 的所有值重置为默认值。检查docs 了解更多信息。

    【讨论】:

    • 正如我所提到的,这种(错误)行为已在 1.1.2 中修复。你用的是什么版本?
    • 嗯,前几天我刚刚从他们的 github repo 同步到他们的最新版本。也许这个问题被重新引入?无论如何,谢谢,因为你们为我指出了正确的方向来解决这里的问题。
    猜你喜欢
    • 2017-12-28
    • 1970-01-01
    • 2011-05-16
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多