High-bitrate AV1 freezes: DAV1DDecoder::InvokeDecode busy-waits on dav1d EAGAIN instead of draining frames
Categories
(Core :: Audio/Video: Playback, defect)
Tracking
()
People
(Reporter: bran.perch-07, Unassigned)
Details
Attachments
(1 file)
Summary
High-bitrate AV1 video (30+ Mbps, 4K) freezes after a few seconds of playback when using the dav1d software decoder. The freeze timing varies with bitrate but is consistently reproducible.
Root Cause
DAV1DDecoder::InvokeDecode has a do/while loop that calls dav1d_send_data followed by a single dav1d_get_picture. When dav1d_send_data returns DAV1D_ERR(EAGAIN) (internal buffer full, no data consumed) and dav1d_get_picture also returns DAV1D_ERR(EAGAIN) (no completed frame yet), the continue statement loops back to retry dav1d_send_data immediately -- but nothing has changed. This creates a tight busy-wait spin loop with no yield that competes with dav1d's own frame decode threads for CPU time.
On high-bitrate content where software AV1 decode already needs every CPU cycle, this busy-wait starves the decode threads, preventing them from completing the frames that would unblock the pipeline. The result is a vicious cycle where decode falls further behind until playback freezes.
Two issues in the current code:
-
Single frame drain per iteration: Only one GetPicture() call per loop iteration, even when dav1d_send_data returned EAGAIN (buffer full). When the buffer is full there may be multiple completed frames waiting -- retrieving only one means multiple outer loop iterations with failed dav1d_send_data calls before the buffer has room.
-
No yield on double-EAGAIN: When both dav1d_send_data and dav1d_get_picture return EAGAIN, the loop spins with no yield. Frames are in-flight on dav1d's decode threads but the busy-wait contends for CPU time those threads need to finish.
Fix
Replace the single GetPicture() call with a draining loop (matching the pattern already used in DAV1DDecoder::Drain()), and add std::this_thread::yield() when dav1d_send_data returned EAGAIN and no frames were available to drain.
Steps to Reproduce
- Play a high-bitrate AV1 video (30+ Mbps, 4K) with hardware AV1 decode disabled (to force dav1d software path)
- Video freezes within a few seconds
- Lower bitrate content may not trigger the issue because dav1d can keep up without EAGAIN contention
| Reporter | ||
Comment 1•1 day ago
|
||
Description
•