Understanding dav1d_send_data in libdav1d API
This article explains the purpose, operation, and integration of the
dav1d_send_data function within the libdav1d AV1 decoder
API. It covers how the function handles compressed input data, manages
memory ownership, and coordinates with the decoder’s asynchronous
decoding pipeline to output decoded video frames.
Role in the Decoding Pipeline
The dav1d library uses an asynchronous, non-blocking
“push/pull” model to decode AV1 video streams. In this model,
dav1d_send_data acts as the “push” mechanism. Developers
feed compressed AV1 bitstream data into the decoder using this function,
while retrieving decoded frames using
dav1d_get_picture.
This decoupled design allows libdav1d to leverage multi-threading efficiently, decoding multiple frames in the background while the application continues to submit new data.
Function Signature and Parameters
The typical signature of the function is:
int dav1d_send_data(Dav1dContext *c, Dav1dData *in);Dav1dContext *c: A pointer to the initialized decoder context.Dav1dData *in: A pointer to a structure containing the compressed AV1 bitstream payload, its size, and associated metadata (such as timestamps).
How dav1d_send_data Operates
When dav1d_send_data is called, the decoder executes the
following steps:
- State Verification: The function checks if the decoder context is in a valid state to receive data.
- Buffer Ownership Transfer: If the function
succeeds, libdav1d takes full ownership of the memory buffer referenced
by the
Dav1dDatastructure. The caller must not free this buffer; the decoder will automatically release it once the data has been parsed and processed. On failure, ownership remains with the caller. - Queueing: The input data is placed into the decoder’s internal queue. Internal worker threads then retrieve this data to perform parallel parsing and decoding.
Return Values and Flow Control
dav1d_send_data returns an integer status code that
dictates how the application’s feeding loop should behave:
0(Success): The data was successfully accepted by the decoder. TheDav1dDatastructure is cleared, and the caller can prepare the next packet.EAGAIN: The decoder’s internal buffers are full. The application must calldav1d_get_pictureto drain decoded frames and free up internal pipeline capacity before attempting to send this data again.ENOMEM: The system ran out of memory while trying to allocate internal resources.EINVALor other negative error codes: An error occurred, such as passing invalid arguments or feeding corrupted data that the parser cannot process.
Standard Implementation Pattern
In a typical playback loop, dav1d_send_data is used in
tandem with dav1d_get_picture in a non-blocking loop:
Dav1dData data;
// ... populate data with AV1 bitstream ...
int res = dav1d_send_data(context, &data);
if (res == EAGAIN) {
// Pipeline is full. Retrieve frames to empty it.
Dav1dPicture pic;
while (dav1d_get_picture(context, &pic) == 0) {
// Process/render the decoded picture
dav1d_picture_unref(&pic);
}
// Retry sending the data
res = dav1d_send_data(context, &data);
}
if (res < 0) {
// Handle other errors
}