How to flush decoder pipeline in libdav1d

This article provides a clear, step-by-step guide on how to properly flush and drain the decoder pipeline in the libdav1d AV1 decoder. It covers both resetting the decoder state during a seek operation and draining the pipeline to retrieve final buffered frames at the end of a video stream.


Scenario 1: Resetting the Decoder (Flushing for a Seek)

When seeking to a new position in a video stream, you must discard all currently buffered frames and reset the internal state of the decoder so it can start fresh with the new packets.

  1. Stop Feeding Input Data Cease passing new packets to the decoder.

  2. Call the Flush Function Invoke the dav1d_flush function by passing your active decoder context:

    dav1d_flush(context);

    This function immediately releases all internally buffered reference frames, clears pending output pictures, and resets the sequence headers. After this call, the decoder is ready to receive new independent packets (typically starting with a keyframe).


Scenario 2: Draining the Decoder (Retrieving Buffered Frames at EOF)

AV1 decoders buffer and reorder frames. When you reach the End of Stream (EOF), you must drain the pipeline to retrieve the final decoded frames still held in the decoder’s buffer.

  1. Prepare an Empty Data Container Initialize an empty Dav1dData structure. This represents a null packet signaling the end of input:

    Dav1dData empty_data;
    memset(&empty_data, 0, sizeof(empty_data));
  2. Send the Empty Data to the Decoder Feed the empty data structure into dav1d_send_data. This signals the decoder to flush its remaining frames to the output queue:

    int result = dav1d_send_data(context, &empty_data);
  3. Retrieve the Remaining Frames Loop and call dav1d_get_picture to collect all remaining pictures. Continue this loop until the function returns -EAGAIN, which indicates that the pipeline is completely empty:

    Dav1dPicture pic;
    int res;
    while ((res = dav1d_get_picture(context, &pic)) == 0) {
        // Process and display the decoded picture
        dav1d_picture_unref(&pic); // Always release the picture when done
    }

Once dav1d_get_picture returns -EAGAIN during this draining phase, the pipeline is fully flushed, and you have successfully retrieved every decoded frame from the stream.