Skip to content

drain: Properly fix a desync between next and first

Victorien Le Couviour--Tuffet requested to merge psilokos/dav1d:fix416 into master

We can't increment first when no data is there, otherwise we might do it while the first frame was not yet decoded, messing up ordering: imagine having a framedelay of 8, and a file with 7 frames. We feed 7 frames over 8 slots, now next points to [7] (empty entry), and we start draining cause EOF. We do need next to be incremented to reach the first frame ([0]), so it can be outputted, and only then first too.

Fixes #418 (closed).

The code in dav1d_drain_picture could result in a desync between c->task_thread.first (oldest submitted frame) and c->frame_thread.next (first frame to retrieve and/or next submit location). As we loop through drain, we always increment next, but first only if the frame has data. If the frame is visible we return. The problem arises when encountering (an) invisible frame(s), and the next entries haven't been fed yet, we then keep on looping increasing next but not first, as these have no data.

We should always return when we encountered data (visible or invisible decoded frame): for visible, the code already returns, for invisible, we can store a boolean indicating we drained at least one frame, whenever we reach an empty entry after that, we return (all subsequent entries are guaranteed to be empty anyway), not incrementing next nor first. This will have the effect to insert the next frame at the first free spot (which is much better than the weird skips it's doing now).

So basically, c->frame_thread.next could skip some (empty) entries. Now it's contiguous.

Fixes #416 (closed).

Edited by Victorien Le Couviour--Tuffet

Merge request reports