如何强制 AVCodecContext 释放对任何缓冲区的所有引用

问题描述 投票:0回答:1

我正在使用 FFMPEG 解码视频流,并且我已经实现了用于

AVFrame
内存分配和取消分配的自定义函数(通过为
codec_ctx->get_buffer2
设置自定义函数)。因此,当
AVFrame
需要新内存时,我会进行内存分配并使用
AvBufferRef
av_buffer_create
包裹在其周围。我还定义了自定义的解除分配函数,因此当不再需要引用计数
AvBufferRef
时,我会进行内存清理。 这样我就可以准确记录内存何时分配以及缓冲区何时空闲。

在视频解码期间,我想要进行搜索,为此我需要清除我的

AVCodecContext
中的所有缓冲区。我正在关注官方文档:

  • 通过发送
    NULL
    到解码器
  • 进入排水模式
  • 从解码器收集所有帧
  • 冲水
    AVCodecContext

这是代码:

        avcodec_send_packet(codec_ctx, NULL);
        auto result = 0;
        while (result != AVERROR_EOF)
        {
            auto frame = av_frame_alloc();
            result = avcodec_receive_frame(codec_ctx, frame);
            av_frame_free(&frame);
        }
        avcodec_flush_buffers(codec_ctx);

但是,我可以看到(由于我的自定义内存管理)并非所有帧都被释放。 仅当我通过调用

avcodec_free_context
关闭编解码器上下文时,我才能看到所有帧都被释放。

有什么提示我可以完全释放

AVCodecContext
中的所有资源(而不关闭它)吗?

c++ ffmpeg
1个回答
0
投票

我终于可以自己回答这个问题了:

函数

avcodec_flush_buffers
将调用解码器实现中的刷新函数。就我而言(VP9 解码器),刷新函数无法正确清理所有资源。 然而,效果很好的是以下方法。

  1. 收集所有帧并刷新解码器(原始问题中的代码片段)
  2. 使用虚拟数据包(当前流中的任何有效数据包都有效)并重复将其发送到解码器,直到
    avcodec_send_packet
    返回
    AVERROR(EAGAIN)

这样,解码器上所有剩余的帧引用都将被释放。

© www.soinside.com 2019 - 2024. All rights reserved.