# iter8 fork build + vainfo smoke — fresnel 2026-05-07 Companion evidence for Phase 0 deliverable #3. ## TL;DR The libva-v4l2-request-fourier fork **loads and initializes cleanly on RK3399** (Pinebook Pro / fresnel) at master tip `65969da` (iter8 Phase 4). Both V4L2 decode bindings advertise profiles via `vainfo`: - **rkvdec** (`/dev/video3` + `/dev/media1`): H.264 (5 profiles incl. MVC/Stereo), HEVCMain. - **hantro-vpu-dec** (`/dev/video5` + `/dev/media2`): MPEG-2 Simple, MPEG-2 Main. This is the first proof that ohm-hardened iter1..iter5 + iter6..iter8 incremental work doesn't trip a cross-SoC initialization bug on RK3399. Substrate confirmed. ## Substrate decision: master, not pinned-iter5 [`README.md`](../../README.md) and [`phase0_findings.md`](../../phase0_findings.md) describe the substrate as "iter5-end fork." That framing was correct on 2026-05-05 when libva-multiplanar reached the iter5 close. Between then and the fresnel-fourier scaffold (2026-05-07) the libva-multiplanar campaign continued through iter6 / iter7 / iter8 (see `~/src/libva-multiplanar/phase0_findings_iter{6,7,8}.md`). Building from master picks up the iter6–iter8 hardening: | Tip commit | Subject | Author | |---|---|---| | 65969da | iter8 Phase 4: tests/run_perf_binding_cell.sh — perf binding cell harness | claude-noether | | dcaa1f1 | docs: clarify Rockchip silicon — PineTab2 is RK3566, not RK3568 | claude-noether | | 7bd0818 | iter7 Phase 7 finalization: OUTPUT-pool teardown + test refinements | claude-noether | | 988b848 | iter7: A+B+C — slot-leak fix, cap_pool harness, msync verify harness | claude-noether | | a09c03c | iter6 fix: per-OUTPUT-slot request_fd binding via REINIT | claude-noether | | c8b6ede | iter5 sweep follow-up: remove additional DEBUG sites flagged by Phase 5 review | Markus Fritsche | | b993355 | iter5 Track E: move LAST_OUTPUT_WIDTH/HEIGHT from process-global to per-driver-data | Markus Fritsche | | 843febc | iter5 sweep: remove iter1 slice_header parse + VAPicture dump + Sync RETURN trace | Markus Fritsche | A correction commit on this campaign should land updating `README.md` and `phase0_findings.md` to read "iter8-end fork" or simply "current master." ## Build environment (verified) - Host: fresnel, kernel `6.19.9-99-eos-arm`. - Toolchain: gcc 15.2.1, ld.bfd 2.46, ninja 1.13.2, meson 1.11.1, pkgconf 2.5.1. - Dependencies: libva 1.23.0, libdrm 2.4.131, ccache available (used). - All 8 kernel UAPI symbols required by the fork are present in `/usr/include/linux/`: `MEDIA_IOC_REQUEST_ALLOC`, `V4L2_CTRL_WHICH_REQUEST_VAL`, `V4L2_PIX_FMT_MPEG2_SLICE`, `V4L2_PIX_FMT_SUNXI_TILED_NV12`, `V4L2_PIX_FMT_HEVC_SLICE`, `V4L2_PIX_FMT_VP9_FRAME`, `V4L2_PIX_FMT_VP8_FRAME`, `V4L2_PIX_FMT_H264_SLICE`. ## Compiled-in codecs From `src/meson.build`: ``` sources = [ ... 'mpeg2.c', 'h264.c', 'h264_slice_header.c', 'request_pool.c', 'cap_pool.c', # 'h265.c' ] ``` In the build: - ✅ MPEG-2 (mpeg2.c) - ✅ H.264 (h264.c + h264_slice_header.c) - ❌ HEVC (h265.c **commented out** in src/meson.build) - ❌ VP8 (no source file) - ❌ VP9 (no source file) ## Build + install Configuration: `meson setup --prefix=/usr build`. Default release mode; no debug toggles set. Build: `ninja -C build`. 20 compile/link targets, two harmless warnings from `request_pool.c` about `struct v4l2_ext_control` forward-declaration scope in `v4l2.h` (incomplete-type-in-prototype). Final artefact: - `build/src/v4l2_request_drv_video.so` — 302152 bytes, ELF aarch64, BuildID `89addcc37a8e6ed2240b0e7ef78789a2e09a2245`, debug_info present (not stripped). - Single exported symbol matching libva's expected entry: `__vaDriverInit_1_23`. Install: `sudo ninja -C build install`. Lands at `/usr/lib/dri/v4l2_request_drv_video.so`, mode 0755 root:root. Size delta vs. ohm baseline: 302 KB on fresnel vs. ~265 KB documented for ohm at iter5-end (per `~/src/libva-multiplanar/phase0_findings.md`). The +37 KB is consistent with iter6–iter8 additions (per-OUTPUT-slot REINIT, slot-leak fix, cap_pool harness, OUTPUT-pool teardown, msync verify) plus possibly different gcc minor; not investigated further. ## vainfo runs ### Pass 1 — rkvdec binding ``` LIBVA_DRIVER_NAME=v4l2_request \ LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video3 \ LIBVA_V4L2_REQUEST_MEDIA_PATH=/dev/media1 \ LIBVA_TRACE=/tmp/vainfo_rkvdec.trace \ vainfo --display drm --device /dev/dri/renderD128 ``` Output: ``` vainfo: VA-API version: 1.23 (libva 2.22.0) vainfo: Driver version: v4l2-request vainfo: Supported profile and entrypoints VAProfileH264Main : VAEntrypointVLD VAProfileH264High : VAEntrypointVLD VAProfileH264ConstrainedBaseline: VAEntrypointVLD VAProfileH264MultiviewHigh : VAEntrypointVLD VAProfileH264StereoHigh : VAEntrypointVLD VAProfileHEVCMain : VAEntrypointVLD ``` LIBVA_TRACE log shows `vaInitialize SUCCESS`, `vaQueryConfigProfiles SUCCESS`, six `vaQueryConfigEntrypoints SUCCESS` — all clean. ### Pass 2 — hantro-vpu-dec binding ``` LIBVA_DRIVER_NAME=v4l2_request \ LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video5 \ LIBVA_V4L2_REQUEST_MEDIA_PATH=/dev/media2 \ vainfo --display drm --device /dev/dri/renderD128 ``` Output: ``` vainfo: Supported profile and entrypoints VAProfileMPEG2Simple : VAEntrypointVLD VAProfileMPEG2Main : VAEntrypointVLD ``` ### Pass 3 — no env vars (sanity) ``` LIBVA_DRIVER_NAME=v4l2_request vainfo ``` Driver loads, but enumerates **zero** profiles. As expected — `request.c:149` reads `LIBVA_V4L2_REQUEST_VIDEO_PATH` to choose the V4L2 device; without it, no probe target exists and nothing gets advertised. Graceful no-op rather than crash. ## Findings worth flagging for Phase 1+ ### F1. HEVC profile enumerated despite `h265.c` not compiled `src/config.c:146` probes the V4L2 device for `V4L2_PIX_FMT_HEVC_SLICE` capability: ```c profiles[index++] = VAProfileHEVCMain; // line 151, gated by V4L2 probe ``` On rkvdec the probe succeeds (because `/dev/video3` `--list-formats-out` advertises `S265`), so `vaQueryConfigProfiles` returns HEVCMain. But `src/h265.c` is excluded from the meson build. The control-submission path (probably a `picture.c` switch over `surface->profile`) must therefore either have HEVC paths also commented out, or carry an unreachable guard, since the link succeeded with no h265 symbols defined. **A consumer that calls `vaCreateConfig(VAProfileHEVCMain)` will get a config back** (config.c:171 includes HEVCMain in the validation list) **and can attach buffers, but the actual control submission will likely fail or fault** at the dispatch step. This is a wedge between the enumerator's optimism and the build's honesty. Phase 2 source-read should map exactly which call returns what for HEVC today; Phase 4 should decide whether to: - (a) re-enable `h265.c` in the meson build (substrate revival — the iter5 sweep stripped it for build-cleanly reasons; on rkvdec the kernel surface is mainline and may "just work"), - (b) gate enumeration on a compile-time `#ifdef` so `h265.c` exclusion implies HEVCMain isn't advertised, - (c) leave both stripped permanently if HEVC can't be made to work on RK3399 cheaply. ### F2. MultiviewHigh + StereoHigh enumerated unconditionally on H.264-capable nodes `config.c:140-141` adds these two profiles without any V4L2-side capability check: ```c profiles[index++] = VAProfileH264MultiviewHigh; profiles[index++] = VAProfileH264StereoHigh; ``` RK3399 rkvdec hardware does not support MVC. A consumer asking for these profiles will succeed at config creation but fail at decode. For binding-cell scoping, fresnel-fourier's H.264 cell should explicitly use `VAProfileH264Main` or `VAProfileH264High` and never the MVC/Stereo variants. (mpv and Firefox don't ask for them anyway; chromium-fourier shouldn't either. Low risk.) ### F3. Per-codec routing is one-env-var-per-process `request.c:149`/`171` reads `LIBVA_V4L2_REQUEST_VIDEO_PATH` and `_MEDIA_PATH` once at init and binds to that single V4L2 device. That means **a single libva backend instance can talk to either rkvdec or hantro-vpu-dec, but not both.** For an mpv invocation that wants H.264 (rkvdec) and a separate one that wants MPEG-2 (hantro), the env vars differ. This was one of the open Phase 0 questions ("rkvdec node device path env var — backend likely uses LIBVA_V4L2_REQUEST_VIDEO_PATH for one node. Two nodes may need a richer config: explicit per-codec routing or a probe loop. Phase 4 design decision."). The smoke-test confirms the answer: **one env var, one device, no in-backend probe.** Phase 4 work for fresnel-fourier — if a single Plasma session needs to decode both H.264 and MPEG-2 — will need either: - (a) per-process env override (e.g., a wrapper script for mpv that picks the device based on file extension or codec hint), or - (b) a backend code change to discover both decode nodes and route by VAProfile at config time. Option (b) is the more general fix and matches the codec-coverage scope this campaign locked. Option (a) is the pragmatic hack until then. ### F4. The `Trying display: drm` path works without a Plasma session being involved Pass 1/2 used `--display drm --device /dev/dri/renderD128`. That's the headless render-node path. It succeeded without Wayland or X11 in the consumer process, which means **vainfo as a smoke test does not require the SDDM watchpoint to be green**. Useful for future scripted smoke runs (CI-style) — they can run from an SSH session with no DISPLAY/WAYLAND_DISPLAY. The `pacman -Qq linux-api-headers` query returned the package name without a version (likely a pacman query format quirk), but the symbol-presence sweep confirms the headers are functionally complete. ## Where this leaves Phase 0 | Deliverable | Status | |---|---| | #1 SDDM recovery | done as watchpoint (`phase0_recovery_2026-05-07.md`) | | #2 V4L2 inventory | done (`v4l2_inventory.txt` + `v4l2_inventory_findings.md`) | | **#3 fork build + vainfo smoke** | **done (this file) — substrate confirmed** | | #4 H.264 baseline trace | next; needs an H.264 fixture (#5 first) | | #5 per-codec test fixtures | next | | #6 chromium-fourier cross-validator trace | needs #5 | | Phase 0 close — commit + push as claude-noether | last; depends on #4 + #6 | ## Re-run incantation (for future sessions) ```bash ssh fresnel ' cd ~/src/libva-v4l2-request-fourier git pull --ff-only ninja -C build sudo ninja -C build install LIBVA_DRIVER_NAME=v4l2_request \ LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video3 \ LIBVA_V4L2_REQUEST_MEDIA_PATH=/dev/media1 \ vainfo --display drm --device /dev/dri/renderD128 ' ```