`finish` showed `outputs.last()` and retired every other picture an access unit
bumped out of the DPB without ever displaying it, and nothing flushed the DPB at
end of stream. Measured on .25 against the vendored vectors: 225 of 250 frames
for H.264, 204 of 250 for H.265, 45 of 50 for HEVC Main 10. D3D11VA and Vulkan
deliver every frame, so this was the rung's alone. All four legs now deliver
250 / 250 / 50 / 250.
The same function carried a second defect. `DmabufFrame::keyframe` was stamped
with the CURRENT access unit's `is_idr`, not the flag of the picture it was
about to display, and on a reordering stream those are different pictures: the
IDR is bumped out several units after it decodes and arrived flagged `false` on
all three legs' first frame, while a later AU draining the DPB flagged some old
trailing picture as a keyframe. That field is `DecodedImage::is_keyframe`, the
pump's post-loss re-anchor signal, so a mislabel re-anchors on the wrong frame.
Three changes, all inside this rung:
* **A deliverable queue**, the same shape as `video_vk_native`'s — extend, ship
the front, trim the oldest past the bound, count and rate-limit the drops into
`DecodeHealth::dropped`. Its DEPTH is derived differently and the divergence is
documented: the Vulkan rung's bound is `HOLD_HEADROOM - PIPELINE_HOLD` = 1
because a queued frame there counts against the pool ON TOP of the DPB's own
residency. Here the three claims are disjoint and a bumped picture MOVES from
`pending`/slot to `held`, so the queue inherits the claim rather than adding
one. The bound is the DPB's depth — the deepest carry-over a bump can leave —
and the measured cost is at most one surface (zero on H.264, whose three
seven-picture IDR drains are the deepest bursts these vectors have). A bound of
1 would have left 235 of 250 on H.264, most of the defect still in place.
* **An end-of-stream flush.** This rung has no EOS signal and cannot have one:
the pump feeds access units until the session ends and then drops the decoder.
So `flush` has the two honest callers — `Drop`, where nothing can be presented
and the job is to release the queue's surfaces and the DPB's before the pool
goes, and a caller that KNOWS the stream ended, which today is the conformance
harness. One walk, not a production path and an untested teardown path. AV1
needs none: it shows at most one frame per temporal unit and buffers nothing,
which its 250/250 says out loud.
* **`PictureFacts` recorded when a picture decodes**, and read back when it is
displayed. `keyframe` was the defect; `color` and `display` are the same
mistake one field along — an in-band HDR switch changes the VUI mid-stream and
AV1's render region is per-frame, so a queued frame shown two units later would
have been drawn with the newest picture's signalling.
Concealment answers `Ok(None)` and deliberately does NOT drain the queue, which
is the Vulkan rung's order and is load-bearing: `clears_demotion_streak` is
`delivered || !concealed`, so shipping a queued frame on a concealed AU would
zero the streak and take away the escape hatch that stops a rung concealing
forever from holding a frozen picture.
The three delivered-count assertions moved with the fix, and so did the CPU
derivation that reproduces them without a GPU — it now simulates the whole
delivery model (ledger, queue, one-per-AU hand-off, flush) in the order `decode`
does it, and carries the old behaviour beside the new one as a counterfactual:
a queue bound of 0 with no flush still reproduces 225/204/45 exactly, and the
test fails if it ever stops being SHORT. `settle` was split out as the pure half
of `finish` so the claim walk, the display ordering and the picture facts are
all assertable with no device; `the_queue_never_needs_a_surface_the_pool_does_not_have`
runs the surface-lifetime arithmetic over the real vectors and pins the peak
claims (9 of a 16-surface pool on H.264, 8 of 14 on both HEVC vectors), with an
unbounded queue as the counterfactual that shows the bound doing its job.
Gates run: `cargo fmt --all -- --check`, `cargo clippy -p pf-client-core
-p pf-vaadec --all-targets --features sdl3/build-from-source -- -D warnings`,
`cargo test -p pf-client-core --lib --features sdl3/build-from-source` (176
pass), the same filtered to `video_vaapi_native -- --include-ignored` (23 pass,
0 ignored) and `cargo test -p pf-vaadec` (48 pass) — all on .25 (Radeon 780M,
RDNA3, radeonsi, Mesa 26.0.3, VA-API 1.23); plus `cargo fmt --all -- --check`
and `cargo clippy --workspace --all-targets -- -D warnings` in pf-lxcheck2.