c++ffmpeg

How to force AVCodecContext to release all references to any buffers


I'm using FFMPEG to decode a video stream and I have implemented a custom functions for AVFrame memory allocation and de-allocation (by setting a custom function for codec_ctx->get_buffer2). So when an AVFrame requires new memory, I do the memory allocation and wrap an AvBufferRef around it using av_buffer_create. I also define my custom de-allocation function, so when the reference counted AvBufferRef is not required anymore, I do the memory clean up. This way I can log precisely when memory gets allocated and when a buffer becomes free.

During video decoding I want to do a seek, for that I need to clear out all buffers from my AVCodecContext. I'm following the official documentation for that:

This is the code for that:

        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);

However, I can see (due to my custom memory management) that not all frames are released. Only when I close the codec context by calling avcodec_free_context, I see all frames getting released.

Any hints how I can completely release all resources in AVCodecContext (without closing it)?


Solution

  • I finally can answer the question myself:

    The function avcodec_flush_buffers will call a flush function in the decoders implementation. In my case (VP9 decoder), the flush function does not correctly clean up all resources. However, what works fine is the following approach.

    1. collect all frames and flush the decoder (the code snippet in the original question)
    2. Use a dummy packet (any valid packet from the current stream works) and repeatedly send it to the decoder until avcodec_send_packet returns AVERROR(EAGAIN)

    This way, all remaining frame references on the decoder are getting freed.