4

最近我将 ffmpeg 从 0.9 升级到 1.0(在 Win7x64 和 iOS 上测试),现在是avcodec_decode_video2seagfaults。长话短说:每次视频尺寸发生变化时都会发生崩溃(例如,从 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 < avci->buffer_count 在 libavcodec/utils.c:603 失败”

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

4

2 回答 2

3

您可以尝试填写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

于 2012-12-03T20:48:03.573 回答
0

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

av_init_packet(&packet_)

这里的关键是此方法将 AVPacket 的所有值重置为默认值。检查文档以获取更多信息。

于 2014-05-05T17:28:47.253 回答