Phase 8.13: byte-exact end-to-end via libva (consumer target hit)
The project's consumer-side goal landed: a real VAAPI consumer
(ffmpeg with -hwaccel vaapi) drives our libva backend → V4L2
driver → daemon → byte-exact NV12 output back to ffmpeg.
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \
-hwaccel_output_format nv12 -i vp9_small.ivf \
-f rawvideo -y /tmp/vp9_via_libva.nv12
cmp /tmp/vp9_via_libva.nv12 /tmp/vp9_ref_for_libva.nv12 → match
18432-byte NV12 byte-for-byte identical to plain ffmpeg
-pix_fmt nv12 software decode. The project_consumer_target
memory's deliverable shape — "V4L2 stateless node consumed by
a real VAAPI client" — is achieved.
Two related kernel changes:
1. v4l2_ctrl_handler_setup(&ctx->hdl) after registration —
matches rkvdec/cedrus/hantro. Brings each registered
compound control out of "uninitialised" state via
std_init_compound defaults.
2. Per-request control completion in the decode path —
the real fix for "Timeout when waiting for media request".
vb2-core's vb2_buffer_done unbinds the BUFFER's req_obj
on normal decode completion, but the per-request CONTROL
object stays bound. buf_request_complete fires only from
queue-cancel paths (vb2-core line 2284), NOT from normal
buf_done. The driver must call
v4l2_ctrl_request_complete(req, hdl) explicitly from the
completion path.
struct daedalus_inflight gained a `struct media_request
*req` field, captured from src_buf->vb2_buf.req_obj.req
in device_run. daedalus_complete_resp_frame then calls
v4l2_ctrl_request_complete before
v4l2_m2m_buf_done_and_job_finish — triggers
MEDIA_REQUEST_STATE_COMPLETE and wakes the request fd
poll.
For non-request flows (test_m2m_stream direct QBUF)
inf->req is NULL; the conditional skips the call.
Both consumer styles work concurrently.
Diagnostic clarification (was Phase 8.13a):
strace traced three S_EXT_CTRLS calls per frame:
1. H264_PROFILE + H264_LEVEL → EINVAL (we don't register)
2. HEVC_PROFILE + HEVC_LEVEL → EINVAL (we don't register)
3. VP9_FRAME + VP9_COMPRESSED_HDR → SUCCESS
The first two are harmless: libva probes whether we support
H264/HEVC integer profile/level controls during config
negotiation; we don't (we expose them as stateless), so EINVAL
just falls through. The actual VP9 stateless controls (#3)
succeeded all along — the libva-side "Unable to set control(s)"
log was misleading us into thinking the control path was the
bug.
Verification on hertz (Pi 5, 6.12.75+rpt-rpi-2712):
daemon log:
REQ_DECODE cookie=1 codec=1 bitstream=1566 bytes capture=128x96 1 planes
decoder: opened vp9 context
decoder: OK 128x96 fmt=0 (yuv420p) fnv1a=0x1eb34bfe ...
ffmpeg side:
no Timeout, no Decoding error
/tmp/vp9_via_libva.nv12: 18432 bytes
cmp vs reference: byte-for-byte identical.
Roadmap update:
- 8.10/8.11, 8.12, 8.13 marked closed with closure docs.
- 8.14 = multi-frame VP9 via libva, AV1 + H.264, mpv/Firefox
higher-level consumers.
Per correctness-before-speed:
- strace + kernel-source-reading found the actual root cause
rather than guessing.
- Conditional v4l2_ctrl_request_complete preserves the existing
test_m2m_stream non-request path — both consumer styles work
concurrently without per-flow branching elsewhere.
- Byte-exact pixel comparison, not "frame size matches."
Phase 8.14 next: multi-frame stream + multi-codec via libva +
mpv/Firefox.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+56
-10
@@ -134,18 +134,64 @@ See `docs/phase_8_8_closure.md`.
|
||||
|
||||
See `docs/phase_8_9_closure.md`.
|
||||
|
||||
### Phase 8.10 — libva-v4l2-request VP9/AV1 patch + end-to-end consumer
|
||||
### Phase 8.10 + 8.11 — libva consumer integration scaffold (closed 2026-05-18)
|
||||
|
||||
1. Build libva-v4l2-request from source on hertz.
|
||||
2. Add VP9_FRAME + AV1_FRAME profile mappings; add
|
||||
V4L2_PIX_FMT_NV12 (single-plane) to our CAPTURE so
|
||||
the library's video.c picks us.
|
||||
3. End-to-end: `mpv --hwdec=vaapi` against test files;
|
||||
then Firefox.
|
||||
4. (Stretch) Upstream the patches to bootlin.
|
||||
- Forked bootlin/libva-v4l2-request to marfrit/libva-v4l2-
|
||||
request-fourier (gitea); discovered the existing fourier
|
||||
fork already had VP9/AV1/HEVC support on Rockchip.
|
||||
- Added daedalus_v4l2 to known_decoder_drivers + meson
|
||||
build option.
|
||||
- Added V4L2_PIX_FMT_NV12 single-plane + request API
|
||||
media ops + stateless control registration to our
|
||||
kernel.
|
||||
- vainfo enumerates 7 VAProfile entries via our driver.
|
||||
|
||||
After 8.10 the project's user-facing loop is closed.
|
||||
Optimisation phases (QPU dispatch, 4K) ship when motivated.
|
||||
See `docs/phase_8_10_11_closure.md`.
|
||||
|
||||
### Phase 8.12 — first VP9 frame decoded via libva (closed 2026-05-18)
|
||||
|
||||
- vb2_queue supports_requests; vb2_ops buf_out_validate +
|
||||
buf_request_complete; v4l2_ctrl_new_custom for stateless
|
||||
ctrl registration.
|
||||
- Daemon decoded byte-exact VP9 keyframe via the full
|
||||
libva path (FNV-1a 0x1eb34bfe matches standalone).
|
||||
- ffmpeg still timed out waiting for media_request
|
||||
completion (request bind state).
|
||||
|
||||
See `docs/phase_8_12_closure.md`.
|
||||
|
||||
### Phase 8.13 — byte-exact end-to-end via libva (closed 2026-05-18)
|
||||
|
||||
- Traced the misleading "Unable to set control(s):
|
||||
Invalid argument" — actually libva probing H264/HEVC
|
||||
PROFILE/LEVEL we don't expose (harmless); the real VP9
|
||||
stateless control SET succeeds.
|
||||
- Diagnosed the "Timeout when waiting for media request"
|
||||
root cause: per-request control object stays bound
|
||||
because vb2's normal buf_done path doesn't fire
|
||||
buf_request_complete (only queue-cancel does).
|
||||
- Fix: capture media_request from src_buf in inflight
|
||||
entry, call v4l2_ctrl_request_complete from the
|
||||
completion path before buf_done_and_job_finish.
|
||||
- **Byte-exact end-to-end**: ffmpeg -hwaccel vaapi →
|
||||
libva-v4l2-request-fourier → /dev/video0 →
|
||||
daedalus_v4l2 → daemon → 18432-byte NV12 byte-for-byte
|
||||
identical to ffmpeg software reference.
|
||||
- **Project consumer target hit**: V4L2 stateless node
|
||||
consumed by a real VAAPI client.
|
||||
|
||||
See `docs/phase_8_13_closure.md`.
|
||||
|
||||
### Phase 8.14 — multi-frame + AV1/H.264 + higher-level consumers
|
||||
|
||||
1. Multi-frame VP9 stream via libva (vp9_60s.ivf from 8.9
|
||||
stress test) — P-frame references across requests.
|
||||
2. AV1 + H.264 single-frame via libva.
|
||||
3. mpv --hwdec=vaapi end-to-end.
|
||||
4. Firefox / WebRTC if motivated.
|
||||
|
||||
Optimisation work (QPU dispatch, 4K, HDR-in-libva) ships
|
||||
when there's a concrete user-facing need.
|
||||
|
||||
## Effort estimate
|
||||
|
||||
|
||||
Reference in New Issue
Block a user