Files
fresnel-fourier/phase0_evidence/2026-05-07/iter8_build_smoke.md
T
claude-noether e83298f0da phase 0 deliverables 1-3: SDDM watchpoint, V4L2 inventory, iter8 fork smoke
Three Phase 0 deliverables, three findings worth flagging.

Deliverable #1 — SDDM recovery (phase0_recovery_2026-05-07.md):

Closed as watchpoint, not as root-caused fix. Greeter is green on
this boot — mfritsche has been in Plasma Wayland on tty1 since 20:32.
The "Process crashed (exit code 1)" in journalctl -u sddm is the
post-login greeter teardown, not the pre-login crash described in
~/.claude/plans/dynamic-forging-piglet.md. No coredumps, no qFatal
strings. No package changed since the 2026-04-28 Syyuu; the only
difference between the failing boot and this one is a reboot —
likely a flaky panfrost/GBM cold-init that happened to succeed.
Plan procedures + /var/cache/pacman/pkg rollback candidates remain
ready if regression fires.

Deliverable #2 — V4L2 inventory (phase0_evidence/2026-05-07/
v4l2_inventory_findings.md, raw capture in v4l2_inventory.txt
which is gitignored as raw data):

Full v4l2-ctl --all + --list-ctrls-menus + --list-formats-out per
node, plus media-ctl topology, plus DT compatibles. Authoritative
codec map on running kernel 6.19.9-99-eos-arm:

  /dev/video3 (rkvdec, rockchip,rk3399-vdec):
    OUTPUT_MPLANE: S265 (HEVC), S264 (H.264), VP9F (VP9)
    CAPTURE_MPLANE: NV12

  /dev/video5 (hantro-vpu-dec, rockchip,rk3399-vpu):
    OUTPUT_MPLANE: MG2S (MPEG-2), VP8F (VP8)
    CAPTURE_MPLANE: NV12

This contradicts phase0_findings.md (and README.md), which both
claim hantro-vpu-dec on RK3399 also does H.264. It does not on
this kernel. Open Question #2 from phase0_findings.md ("two-block
H.264 routing") is null on RK3399. Correction commit follows.

Deliverable #3 — iter8 fork build + vainfo (phase0_evidence/
2026-05-07/iter8_build_smoke.md):

Built libva-v4l2-request-fourier master tip 65969da on fresnel
directly (no distcc per locked precedent), gcc 15.2.1, meson 1.11.1,
ninja 1.13.2, libva 1.23.0, libdrm 2.4.131. Clean build, 302 KB
.so, two harmless v4l2.h forward-decl warnings. Installed to
/usr/lib/dri/v4l2_request_drv_video.so. vainfo enumerates:

  rkvdec bind: H.264 {Main, High, ConstrainedBaseline, MultiviewHigh,
                      StereoHigh}, HEVCMain
  hantro-vpu-dec bind: MPEG-2 {Simple, Main}

Substrate is iter8 master, not iter5 as the campaign docs frame —
libva-multiplanar continued past iter5 into iter6-iter8 between the
2026-05-05 iter5 close and the 2026-05-07 fresnel-fourier scaffold.
Building from master inherits per-OUTPUT-slot REINIT, slot-leak
fix, cap_pool harness, msync verify harness, OUTPUT-pool teardown.
Correction commit follows.

HEVC anomaly worth flagging: src/config.c:146-151 probes
V4L2_PIX_FMT_HEVC_SLICE before adding VAProfileHEVCMain. rkvdec
advertises S265 so the probe succeeds; HEVCMain gets enumerated.
But src/meson.build excludes h265.c from the build. A consumer
that calls vaCreateConfig(VAProfileHEVCMain) will succeed (config.c
validation list includes HEVCMain) but actual decode will fault
at dispatch since no h265 symbols are linked. Phase 4 decision:
re-enable h265.c, gate enumeration on a compile-time #ifdef, or
strip enumeration honestly.

Per-codec routing confirmed one-env-var-per-process: request.c:149
reads LIBVA_V4L2_REQUEST_VIDEO_PATH once at init. A single backend
instance binds to either rkvdec or hantro-vpu-dec, not both. Phase 4
will need either a wrapper-script-per-consumer hack or a backend
probe-loop change to route by VAProfile across both decode nodes.

Build infrastructure (gitignore):

Switched from blanket phase*_evidence/ exclude to extension-based
allow-list — track narrative .md, ignore raw .txt/.log/.trace/.pcap/
.bin/.gz/.zst/.json/.dat/.ftrace/.strace. Keeps the V4L2 inventory
text untracked (reproducible from the v4l2-ctl invocation) while
preserving the findings narrative in-repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:54:38 +00:00

10 KiB
Raw Blame History

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 and 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 iter6iter8 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 iter6iter8 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:

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:

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)

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
'