Two empirical corrections to the morning-of-2026-05-07 phase 0 lock,
based on V4L2 inventory + iter8 fork build smoke captured this evening
on fresnel (kernel 6.19.9-99-eos-arm).
Correction 1 — hantro-vpu-dec on RK3399 does not advertise H.264.
phase0_findings.md morning lock claimed both rkvdec (/dev/video3)
and hantro-vpu-dec (/dev/video5) advertise H.264. Empirical
v4l2-ctl --list-formats-out shows hantro-vpu-dec exposes only
MG2S (MPEG-2) and VP8F (VP8) — no S264. Likely carryover from
RK3568 (ohm) hantro, which does support H.264; the RK3399 hantro
kernel variant in drivers/media/platform/verisilicon/ registers
a different codec list. Fix:
- README.md hardware-target table: drop "+ H.264" from Decoder
block 2.
- README.md decode-side surface-area paragraph: note hantro is
MPEG-2 + VP8 only and that there is exactly one bind for H.264
(rkvdec).
- phase0_findings.md mechanism table: drop H.264 from /dev/video5
row; correct DT compatible to rockchip,rk3399-vpu (the actual
parent device compatible — sysfs reports rockchip,rk3399-vpu,
not rockchip,rk3399-vpu-dec which is just the v4l2 card type
string).
- phase0_findings.md "H.264 lands on both blocks" sentence:
inverted to "H.264 lands only on rkvdec".
- phase0_findings.md Open Question #2 (two-block H.264 routing):
marked RESOLVED 2026-05-07 evening (null). Single bind, no
routing decision, one test cell per codec.
Empirical evidence: phase0_evidence/2026-05-07/v4l2_inventory_findings.md
(distilled from v4l2_inventory.txt — the latter is gitignored as
raw data, regenerable via the v4l2-ctl invocation documented in
the findings file).
Correction 2 — substrate is iter8 master (65969da), not iter5-end.
phase0_findings.md morning lock framed the substrate as "iter5-end
fork." That was true on 2026-05-05 (iter5 close); between then and
the 2026-05-07 fresnel-fourier scaffold libva-multiplanar continued
through iter6 (per-OUTPUT-slot REINIT request_fd binding), iter7
(slot-leak fix, cap_pool harness, msync verify harness, OUTPUT-pool
teardown), and iter8 (perf binding cell harness, RK3566/3568 doc
fix). Building from master tip 65969da inherits all the iter6-iter8
hardening at zero cost. Fix:
- phase0_findings.md substrate paragraph: strikethrough the
"iter5-end" framing, add corrected paragraph naming master
tip 65969da and listing what iter6/7/8 added.
- phase0_findings.md top-of-doc: add an "Empirical corrections
2026-05-07 evening" callout linking to the evidence files,
so a reader spotting the locked-vs-corrected mismatch knows
where the empirical update came from.
Empirical evidence: phase0_evidence/2026-05-07/iter8_build_smoke.md
(clean build, vainfo profile enumeration, HEVC anomaly write-up).
What's preserved on purpose:
The strikethrough rendering in phase0_findings.md keeps the original
locked text visible alongside the correction — campaign convention
treats locks as historical record, not editable state. A reader
landing on the file from a deep link sees both the morning's
intent and the evening's empirical update. Git history has the
clean diff if anyone wants the original without strikethrough.
What's not changed:
The codec scope in the locked research question stays correct in
count — five codecs (H.264 + HEVC + VP9 + MPEG-2 + VP8). The
routing table changes (H.264 → rkvdec only; MPEG-2 → hantro only;
no shared block) but the boolean-correctness pass/fail criterion
per codec is unaffected. Phase 1 lock can proceed on the corrected
map without re-opening scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
19 KiB
Phase 0 — fresnel-fourier
This campaign's substrate, locked research question, and pre-Phase-1 inventory work for the fresnel/RK3399 leg of the libva-v4l2-request-fourier rollout. Peer to libva-multiplanar (ohm/RK3568); see README.md for topology.
Empirical corrections 2026-05-07 evening. This document was locked 2026-05-07 morning before the V4L2 surface was empirically enumerated and before iter6–iter8 work in libva-multiplanar was reflected in fresnel-fourier's substrate framing. Two facts have been corrected inline: (1) hantro-vpu-dec on RK3399 does not advertise H.264 — only MPEG-2 + VP8 (so Open Question #2 is null); (2) substrate is libva-v4l2-request-fourier master tip 65969da (iter8 Phase 4), not "iter5-end". See phase0_evidence/2026-05-07/v4l2_inventory_findings.md and phase0_evidence/2026-05-07/iter8_build_smoke.md for the empirical evidence.
Campaign-contained data discipline (governing rule)
Per feedback_dev_process.md Phase 0 + feedback_replicate_baseline_first.md:
This campaign acquires its own measurement data on fresnel in-session. libva-multiplanar's ohm-side findings (iter1..iter5 close documents, the patch-0011 cache-coherency lesson, the FFmpeg/GStreamer source-read references, the H.264 control-submission corrections) are documented for state carry-over — bug catalog, contract analysis, source pointers, build recipe shapes — but every claim that depends on hardware behaviour ("hantro accepts X", "the parser rejects Y", "DPB needs Z") is reference history until re-verified on RK3399's rkvdec and rk3399-vpu-dec blocks. Different silicon, possibly different firmware, definitely different driver path: don't assume.
Research question (LOCKED 2026-05-07)
"Make libva-v4l2-request-fourier accepted by VA-API consumers on fresnel (Rockchip RK3399), providing access to all decode-capable codecs the SoC ships — H.264 + HEVC + VP9 via the rkvdec block, MPEG-2 + VP8 via the hantro-vpu-dec block — end-to-end. Performance metrics are explicitly deferred to a follow-up iteration."
Pass/fail is boolean correctness per codec, not throughput:
- For each of {H.264, HEVC, VP9, MPEG-2, VP8}: does the consumer dlopen
v4l2_request_drv_video.so, complete the VA-API surface lifecycle without falling back to SW, route to the correct V4L2 device node (rkvdec vs hantro-vpu-dec), and produce a CAPTURE buffer with non-zero, non-sentinel, semantically-correct decoded pixels (cache-coherency-safe verification, per the libva-multiplanar iter1 0011-sentinel lesson)?
If yes for a codec → that codec passes for the iteration. Frame-rate / CPU% / drops measurement is a separate iteration whose binding cells will be locked separately.
Mechanism the question targets
fresnel exposes two V4L2 stateless decode interfaces (verified 2026-05-07 via v4l2-ctl --info + --list-formats):
| Node | Driver | DT compatible | Codecs (kernel CIDs) | Capture format |
|---|---|---|---|---|
/dev/video3 |
rkvdec |
rockchip,rk3399-vdec |
H.264 (V4L2_PIX_FMT_H264_SLICE), HEVC (V4L2_PIX_FMT_HEVC_SLICE), VP9 (V4L2_PIX_FMT_VP9_FRAME) |
NV12 |
/dev/video5 |
hantro-vpu |
rockchip,rk3399-vpu |
MPEG-2 (V4L2_PIX_FMT_MPEG2_SLICE), VP8 (V4L2_PIX_FMT_VP8_FRAME) |
NV12 |
Both are V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, both speak the request-API for control submission, both produce NV12 output. H.264 lands only on rkvdec — RK3399's hantro-vpu-dec does not advertise H.264 (corrected 2026-05-07 evening; the original lock cited H.264 on hantro, which was incorrect on running kernel 6.19.9-99-eos-arm). There is no two-block routing decision for H.264 on this SoC.
VA-API consumers (mpv, Firefox, chromium-fourier, vainfo) speak libva. The bridge they expect is libva-v4l2-request-fourier. As of libva-multiplanar iter5-close (2026-05-05), the fork is hardened against ohm's hantro-vpu (rk3568-vpu) — the test consumers run end-to-end on H.264 with all known iter1..iter4 bugs fixed. Whether that hardening transfers to:
- fresnel's hantro-vpu-dec (
rk3399-vpu-dec) — same driver family, possibly different SoC quirks - fresnel's rkvdec — a different driver entirely; new code paths in the libva backend may be needed
- HEVC + VP9 + MPEG-2 + VP8 — codecs the fork has never decoded on real hardware to date
are open empirical questions that this campaign answers.
External pointers (carried from libva-multiplanar/phase0_findings.md):
- Mozilla bug 1833354 / 1965646 — Firefox HW decode on RK35xx via libva-v4l2-request.
- Bootlin upstream
bootlin/libva-v4l2-request— dormant since 2021, sunxi-cedrus single-plane only. - Linux kernel
drivers/staging/media/rkvdec/— the rkvdec driver source. H.264 + HEVC + VP9 control-submission contract reference for fresnel. - Linux kernel
drivers/media/platform/verisilicon/hantro_*— the hantro-vpu driver source. RK3399-vpu-dec MPEG-2/H.264/VP8 control protocol reference. - Christian Hewitt patch series (LKML 2025/12/26/206) — RK3566 rkvdec2/vdpu346 (NOT applicable here; fresnel's rkvdec is mainline and works).
Predecessor close-out summary (state carry-over, not data)
From ~/src/libva-multiplanar/ — iter1..iter5 closed on ohm
The full chain of bugs found and fixed on ohm/RK3568 hantro is the substrate. Read in order:
phase8_iteration1_close.md— iter1: contract trace lands; surface-export DMA-BUF lifecycle race; multi-resolution session corruption; Mesa WSI 64-pitch alignment; patch-0011 sentinel cache-coherency bug (the readback was lying — kernel was writing zeros).phase8_iteration2_close.md— iter2: Fix 1 (resolution-change format-cache invalidation), Fix 2 (DRM_FORMAT_MOD_INVALID conditional for non-64 pitch), Fix 3 (decoupledcap_poolwith LRU recycling).phase8_iteration3_close.md— iter3: Firefox RDD sandbox fix (broker policy + seccomp +select() → poll()driver migration); frame-11 EINVAL reproduced deterministically.phase8_iteration4_close.md— iter4: frame-11 EINVAL fixed (DPBfields=FRAME_REF, fresh request_fd per frame, B-slice L1 reflist.fieldscopy-paste). mpv 2130 BeginPictures over 90s with 0 EINVAL.phase8_iteration5_close.md— iter5: ~339 lines of debug instrumentation removed; firefox-fourier 150.0.1-1.1 rebuilt non-PGO (21× smaller libxul, 2.7× faster decode);LAST_OUTPUT_*moved per-driver-data; mpv--vo=gpu0 segfaults. iter6+ caveat: cap_pool resolution-change race latent under untested consumer probe patterns (Phase 5 sonnet C4).
The iter5-end fork is the substrate fresnel-fourier starts from. Corrected 2026-05-07 evening: the substrate is master tip 65969da (iter8 Phase 4) — libva-multiplanar continued past iter5 into iter6 (per-OUTPUT-slot REINIT request_fd binding), iter7 (slot-leak fix, cap_pool harness, msync verify, OUTPUT-pool teardown), and iter8 (perf binding cell harness) between the 2026-05-05 iter5 close and the 2026-05-07 fresnel-fourier scaffold. Building from master inherits all that hardening at zero cost. Codepaths not exercised on ohm — the rkvdec driver path entirely; HEVC + VP9 + MPEG-2 + VP8 control submission — are unknown territory and the most likely Phase 6 work.
From the libva-v4l2-request-fourier fork itself
Carry-over state (re-verify before treating as current):
- 12 commits ahead of bootlin
a3c2476plus 5 iterations of patches, all onmaster. Build harness:meson setup+ninja. Install:/usr/lib/dri/v4l2_request_drv_video.so. Activation:LIBVA_DRIVER_NAME=v4l2_request+LIBVA_V4L2_REQUEST_VIDEO_PATH=...+LIBVA_V4L2_REQUEST_MEDIA_PATH=.... - Build artefact size on ohm: ~265 KB
.so(small — no distcc).
From the SDDM-greeter recovery plan (~/.claude/plans/dynamic-forging-piglet.md)
fresnel currently cannot graphical-login — /usr/bin/sddm-greeter-qt6 crash-loops with a qFatal() call from libqxcb-glx-integration.so after QOpenGLContext::create returned failure. Coredump bt confirmed; qt6-base-fourier is exonerated (downgrade to stock didn't fix it; bt path is GLX, our patches gate on ES 3+). The plan lists three step-1 invocations to capture the qFatal message, an iterative downgrade test against the recent pacman -Syyuu (mesa, qt6-base, qt6-declarative, libdrm-pinebookpro candidates), and two workaround options (Wayland greeter via SDDM Compositor, or TTY autologin with exec startplasma-wayland).
This recovery is fresnel-fourier Phase 0 task 1 (LOCKED 2026-05-07). Without graphical login there's no Plasma session to host VAAPI consumers under; headless Xvfb is documented (libva-multiplanar phase0) to give the wrong answer for Firefox.
Current fresnel state (verified 2026-05-07 over SSH)
- Kernel:
linux-eos-arm 6.19.9-99(custom OC kernel, ALARM/EndeavourOS-ARM).CONFIG_FTRACE=y, CONFIG_FUNCTION_TRACER=y, CONFIG_DYNAMIC_FTRACE=y, CONFIG_TRACING=yconfirmed viazcat /proc/config.gz./sys/kernel/tracing/populated. - V4L2 decode nodes:
/dev/video3(rkvdec),/dev/video5(hantro-vpu-dec) — listed above. - Encoder:
/dev/video4(hantro-vpu-enc, JPEG only). - RGA:
/dev/video0(rockchip-rga, scaling/format-conversion accelerator — out of scope but worth knowing about). - USB cameras:
/dev/video{1,2}— irrelevant. - Graphical session: DOWN — sddm-greeter-qt6 crash-loop. Phase 0 task 1.
In-scope (LOCKED 2026-05-07)
- libva-v4l2-request-fourier backend only.
- Hardware target: fresnel RK3399, both decode nodes (rkvdec + hantro-vpu-dec).
- Codecs: H.264 + HEVC + VP9 + MPEG-2 + VP8 — everything fresnel can hardware-decode. Each codec is a separate boolean cell.
- Test consumers (LOCKED 2026-05-07):
vainfo— smoke test, enumerates profiles + entrypoints per codec.mpv --hwdec=vaapi(and--hwdec=vaapi-copyfor the headless intermediate runs) — most directly testable end-to-end consumer for HW decode validation.- Firefox via
media.ffmpeg.vaapi.enabled=true+ LIBVA env — Mozilla bug 1965646 anchor. - chromium-fourier 149 — regression check inherited from libva-multiplanar.
- Brave 1.89 — deferred (chromeos-pipeline gating is upstream of libva, same as libva-multiplanar's reasoning).
- Phase 1 success criterion: per-codec boolean correctness including cache-coherency-safe pixel-content verification (NOT the patch-0011 mmap pattern — that lesson is non-negotiable per libva-multiplanar iter1 close).
- Phase 0 task 1: recover fresnel SDDM (per
dynamic-forging-piglet.md). Bookkept inside this campaign.
Out-of-scope (LOCKED 2026-05-07)
- Front-end libva.
- Other hardware (ohm in libva-multiplanar; ampere/boltzmann RK3588 are a separate not-yet-named campaign).
- AV1 (no decoder block on RK3399 supports it).
- Userspace bitstream parsing (kernel V4L2-stateless does this).
- Performance metrics (CPU%, fps, drops_60s, panfrost freq, GPU residency). Explicitly deferred. Do not lock Phase 1 binding cells around performance.
- KWin / panfrost / Mali-T860 work — orthogonal until proven otherwise. A
kwin-fourier-fresnelcampaign would be a separate decision. cros-codecsRust replacement (peruser_stance_rust.md).- Bootlin / Collabora upstreaming — default-deferred (per
feedback_no_upstream.md). Same discipline as libva-multiplanar. /dev/video0rockchip-rga acceleration — not on the libva path.
Open questions before Phase 1 lock
- SDDM recovery root cause — is the
qFatalfrom a Mesa 26.0.5 panfrost regression on Mali-T860 (Midgard), Qt 6.11.0 xcb-glx-integration internals, or qt6-declarative? Phase 0 task 1 must determine this before Phase 1 locks, because it affects rig stability for measurement. Two-block H.264 routing— RESOLVED 2026-05-07 evening (null). Empirical V4L2 enumeration showed hantro-vpu-dec on RK3399 does not advertise H.264. Only rkvdec accepts H.264 on this SoC. Single bind, no routing decision, single test cell per codec.- HEVC control-submission contract on rkvdec — the fork has had HEVC stripped per the libva-multiplanar build-cleanly stack. Re-introducing it for rkvdec is a code addition, not a regression-test. Phase 2 source-read of rkvdec H.265 path + FFmpeg's
v4l2_request_hevc.cis gating. - VP9 control-submission contract on rkvdec — never been in the fork. Same Phase 2 source-read need: kernel
rkvdec_vp9.c+ FFmpegv4l2_request_vp9.c. Plus VAAPI-VP9 consumer testing — does mpv exercise it? does Firefox? - MPEG-2 control-submission contract on hantro-vpu-dec — was iter1 backlog in libva-multiplanar, dropped at iter6 close because A55 CPU handles it fine. On RK3399 the A53 cluster is weaker; HW MPEG-2 decode might be more useful. Phase 2 source-read: kernel
hantro_mpeg2.c+ FFmpegv4l2_request_mpeg2.c. - VP8 control-submission contract on hantro-vpu-dec — same shape: source-read kernel + FFmpeg. VP8 consumer matrix is thin; mostly Firefox / WebRTC paths.
- rkvdec node device path env var — backend likely uses
LIBVA_V4L2_REQUEST_VIDEO_PATHfor one node. Two nodes may need a richer config: explicit per-codec routing or a probe loop. Phase 4 design decision. - firefox-fourier suitability for fresnel — the iter3 RDD sandbox patch is Mali-G52-rig-tested. Does it apply on Mali-T860 / panfrost on RK3399 unchanged, or are sandbox-side surprises lurking? Phase 0 inventory item: confirm the iter5 firefox-fourier package installs and runs on fresnel.
- Test corpus per codec —
bbb_1080p30_h264.mp4(carryover). HEVC, VP9, MPEG-2, VP8 test clips need sourcing or generating. Doppler //moviedata/fourier-test/may already have some. - Brave 1.89 / chromium-fourier 149 binaries on aarch64 for fresnel — both already exist for ohm. Same aarch64 architecture; should run on fresnel without rebuild. Verify.
What Phase 0 will deliver
Independent of detail, Phase 0 produces:
- fresnel SDDM recovered — either root-caused + downgraded to a working version, or workaround-A (Wayland greeter) installed. Findings logged in this directory under
phase0_recovery_<date>.md. Loop back to phase 0 (not phase 1) if a root cause has campaign-relevant implications (e.g., a Mesa 26.0.5 panfrost regression that also affects video display paths). - fresnel V4L2 inventory written —
v4l2-ctlenumeration of every codec controls + supported formats per node, captured tophase0_evidence/<date>/v4l2_inventory.txt. Already partially done in this document; expand to include--list-ctrls-menus,--allper node, and supportedOUTPUT_MPLANEcodec formats. - iter5-end fork built on fresnel and installed —
meson setup && ninjadirectly on fresnel (no distcc per libva-multiplanar precedent). Install to/usr/lib/dri/v4l2_request_drv_video.so. Run vainfo, capture profile enumeration. This is the smoke test before any iteration even starts — does the existing fork even load on RK3399? - H.264 baseline trace —
mpv --hwdec=vaapi-copy --frames=2againstbbb_1080p30_h264.mp4on fresnel, ftrace-instrumented, with cache-coherency-safe pixel verification per the libva-multiplanar iter1 patch-0011 lesson. Compare control-submission ioctl sequence against ohm's iter5 trace. Identify divergences. - Per-codec test fixture inventory — what test clips exist for HEVC / VP9 / MPEG-2 / VP8, what we need to source or generate, and where they'll live.
- Phase 0 baseline anchor — for the boolean-success criterion per codec, the anchor is again a contract trace, not a metric distribution. Capture the V4L2 request-API ioctl sequence on a known-working consumer per codec on fresnel — chromium-fourier 149 binary is the cross-validator (does it engage rkvdec for HEVC? VP9? for the codecs it natively uses) — for 1 frame's decode each, in-session, before any fork modifications.
Phase 0 is not the place to start coding HEVC/VP9 support in the fork. That work, if it lands, is Phase 4 onwards of an iteration whose Phase 1 has already locked the codec scope.
Source-read references (carried + extended for fresnel)
For Phase 2 source-read and Phase 6 implementation:
Carried from libva-multiplanar (H.264 path):
- FFmpeg —
libavcodec/v4l2_request.c,v4l2_request_buffer.c,v4l2_request_h264.c. Active downstream:code.ffmpeg.org/Kwiboo/FFmpeg.gitbranchv4l2-request-n8.1. - GStreamer v4l2codecs —
gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c+gstv4l2codecsh264dec.c. - Chromium —
media/gpu/v4l2/v4l2_video_decoder_backend_stateless.{h,cc}+v4l2_queue.cc.
Added for fresnel (HEVC/VP9/MPEG-2/VP8):
- FFmpeg
v4l2_request_hevc.c— HEVC slice-mode control submission. - FFmpeg
v4l2_request_vp9.c— VP9 frame control submission. - FFmpeg
v4l2_request_mpeg2.c— MPEG-2 slice control submission. - FFmpeg
v4l2_request_vp8.c— VP8 frame control submission. - GStreamer —
gstv4l2codecsh265dec.c,gstv4l2codecsvp9dec.c,gstv4l2codecsmpeg2dec.c,gstv4l2codecsvp8dec.c. - Linux kernel —
drivers/staging/media/rkvdec/{rkvdec_h264.c, rkvdec_hevc.c, rkvdec_vp9.c}for the rkvdec block;drivers/media/platform/verisilicon/hantro_h264.c, hantro_mpeg2.c, hantro_vp8.cfor the hantro block.
Test fixtures
- H.264:
bbb_1080p30_h264.mp4(carry-over fromfourier_attribution/ libva-multiplanar). Pull via hertzlxc file pullfromdata:/moviedata/fourier-test/or copy from ohm's/home/mfritsche/fourier-test/. - HEVC, VP9, MPEG-2, VP8: TBD per Phase 0 deliverable #5. Likely Big Buck Bunny in those codecs from the same operator-internal
/moviedata/if available; otherwise generate viaffmpeg -i bbb_1080p30_h264.mp4 -c:v <codec> -y bbb_1080p30_<codec>.<ext>.
Build + install on fresnel
meson setup build && ninja -C builddirectly on fresnel. Same default as libva-multiplanar: small library, no distcc.- Install path:
/usr/lib/dri/v4l2_request_drv_video.so. - Activation:
LIBVA_DRIVER_NAME=v4l2_request+ (per-node env vars; exact layout depends on Phase 4 device-routing decision). - Once a working state is reached: package as
marfrit/libva-v4l2-request-fourier-fresnelnext to existing fourier packages — out of Phase 1 scope, post-Phase-7.
Cross-link to libva-multiplanar
This campaign is a peer, not a child. libva-multiplanar Phase 8 closes happen iteration-by-iteration on ohm independently of fresnel-fourier progress. Cross-references:
- libva-multiplanar/README.md:87 names fresnel + RK3588 as "future iterations after ohm path is solid" — that promise is now formally taken up here.
- Code-side work in the shared fork (
../libva-multiplanar/libva-v4l2-request-fourier/) lands either as#ifdef/runtime-detected paths onmaster(preferred when behavior is RK3399-specific but doesn't break ohm) or on a feature branch (when scope diverges sharply). Phase 2 source-read of each iteration decides. - libva-multiplanar's iter1 patch-0011 cache-coherency lesson is non-negotiable for fresnel-fourier: pixel-content verification must use cache-flushed reads (e.g. mpv
--vo=image-sequence, or DMA-BUF GL import via mpv--vo=gpu, or a small C reproducer withmsync(MS_SYNC|MS_INVALIDATE)), never the cached mmap readback pattern.