Files
marfrit eefc378d93 iter2 phase1: HEVC backend extension goal + vendoring spec
Architecture locked: implement H.265 SPS parser in backend by
vendoring GStreamer's gst-plugins-bad/codecparsers/gsth265parser.c
directly (B1 per operator decision 2026-05-16). Drop GLib deps,
preserve LGPL header + upstream function names (gst_h265_parser_*),
add README note pinning vendored revision.

Header strategy: runtime-optional V4L2 control probe (no #ifndef
shim, per GStreamer pattern). Compile-time CID + struct defs in a
new internal header src/hevc-ctrls/v4l2-hevc-ext-controls.h
mirroring fresnel iter25 precedent.

8 success criteria for iter2:
  C1 — decode completes, 1440 frames
  C2 — HW path engaged (ioctl trace shows new CID writes)
  C3 — frame 0 byte-identical vs SW reference
  C4 — frame 720 SSIM Y in H.264-drift territory, no fixed threshold
  C5 — FPS N=3 with sigma, no fixed threshold
  C6 — dmesg clean, no rkvdec_hevc_prepare_hw_st_rps OOPS
  C7 — firefox-fourier vendor-default HEVC engagement (now possible
       with SDDM auto-login configured; not iter2-blocking)
  C8 — regression check: ampere-fourier iter1's 3-codec baseline
       still passes C1-C6 per iter1 per-codec floors

4 falsifier branches with explicit loopback edges (F1: HEVC still
OOPSes -> re-open ka#11; F2: garbage output -> parser bisect;
F3: regression -> per-driver-kind gate; F4: license issue -> revisit).

Ready for iter2 Phase 2 situation analysis.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 08:41:22 +00:00

63 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 1 — iter2 goal formulation (HEVC backend EXT_SPS_*_RPS extension)
Locked 2026-05-16, post-Phase-0-update with upstream-survey resolution.
## Iter2 goal (one sentence)
**Extend `libva-v4l2-request-fourier` to populate `V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS` and `_LT_RPS` for VDPU381/VDPU383 HEVC, by vendoring GStreamer's `gst-plugins-bad/codecparsers/gsth265parser.c` (dropping GLib deps), and using a runtime-optional control probe so the same backend binary works against both 7.0-and-later kernels (HEVC engages) and earlier kernels (HEVC falls back to whatever the pre-7.0 path did) — until ampere HEVC HW decode passes the ampere-fourier iter1 C1-C6 success criteria per the per-codec floors, with HEVC SSIM-Y-at-f720 expected in H.264-drift territory (~0.65 ± 0.05).**
## Resolved Phase 0 open questions
- **Q1 (architecture)**: B — implement H.265 SPS parser in backend, mirroring GStreamer's `gst_v4l2_codec_h265_dec_fill_ext_sps_rps`.
- **Q2 (UAPI shim vs bump)**: header strategy is runtime-optional control probe (no `#ifndef` shim), per GStreamer's pattern. Compile-time CID + struct definitions: ship a minimal internal header at `src/hevc-ctrls/v4l2-hevc-ext-controls.h` (the new file matches the precedent of fresnel iter25's image_fmt shim approach — minimal, scope-tagged to what the new UAPI added in 7.0). The headers package on ampere stays at 6.19-1; no `pacman -Syu` needed.
- **Parser source sub-question**: B1 — vendor GStreamer's `gsth265parser.c` directly. Operator-confirmed 2026-05-16.
## Vendoring spec for the GStreamer parser
- Source: `gitlab.freedesktop.org/gstreamer/gstreamer``subprojects/gst-plugins-bad/codecparsers/gsth265parser.c` + companion header. Take the version that landed alongside or after MR !10820 (GStreamer 1.28).
- Target location in backend: `src/h265_parser.{c,h}` OR `src/gsth265parser/{gsth265parser.c, gsth265parser.h}` — TBD in Phase 4 (file-naming detail; the vendored content itself is licence-pinned by upstream's LGPL header which we preserve).
- License: file keeps GStreamer's LGPL header (authorship + source URL preserved). Backend's existing COPYING.LGPL covers redistribution. MIT remains for the rest of the backend. Add a top-level note in `README.md` listing the vendored file as an LGPL-licensed third-party component.
- GLib dependency removal: replace `GArray` with plain dynamically-sized C arrays (size + pointer); replace `g_slice_*` / `g_malloc` with libc `malloc`/`free`; replace `GstBitReader` with the backend's own `bit_reader.{c,h}` style (or a vendored copy if backend lacks one — check during Phase 2).
- Function-name namespace: keep `gst_h265_parser_*` for the vendored functions (don't rename — that breaks the upstream-bug-fix-sync we're paying for by vendoring). The backend's call sites use the GStreamer names directly.
- Tracking upstream: README note pinning the vendored revision (sha + tag); when GStreamer ships a parser fix, the backend pulls it manually (no submodule machinery in this iteration).
## Success criteria
For HEVC, mirroring ampere-fourier iter1's C1-C6 with per-codec-floor refinement:
| # | Criterion | Phase 3 instrument | Phase 7 anchor |
|---|-----------|--------------------|----------------|
| **C1** | HEVC libva HW decode runs to completion on `bbb_60s_720p.hevc.mp4`, exit 0, frame count = 1440 frames | `ffmpeg -benchmark -hwaccel vaapi -hwaccel_output_format vaapi -i $clip -vf hwdownload,format=nv12 -f null -`; frame= count | post-iter2 patch installed |
| **C2** | HW path engaged via ioctl trace; new `MEDIA_REQUEST_IOC_QUEUE` count includes the EXT_SPS_*_RPS controls (i.e. higher per-frame ioctl count vs ampere-fourier iter1's H.264 baseline) | `strace -ff -e trace=ioctl -p $PID`; count `VIDIOC_S_EXT_CTRLS` invocations involving the new CID values | iter1 H.264 ioctl counts as reference history |
| **C3** | HEVC frame 0 byte-identical vs ffmpeg SW reference (HEVC I-frame, no inter-prediction) | `cmp` of 1 382 400 bytes (one 720p yuv420p frame) | iter1 all-codec sha `3214803d8be74416` |
| **C4** | HEVC frame 720 (t=30 s) SSIM Y in H.264-drift territory (~0.65 ± 0.05); no fixed PASS threshold | `ffmpeg -lavfi "[0:v][1:v]ssim"` at frame 720 | fresnel iter1 HEVC SSIM Y was 1.000 (byte-identical) on RK3399 — does NOT carry as anchor; ampere RK3588 may behave differently. Track and accept whatever drift territory shows up; if it's surprising (way better OR worse than ~0.65 ± 0.05), Phase 7 surfaces it for Phase 4 plan refinement |
| **C5** | HEVC FPS reported at N=3 with σ; mean within an order of magnitude of iter1's H.264 461 FPS / VP8 217 FPS / MPEG-2 200 FPS (all 8x-20x realtime). No fixed threshold | wall-time around `ffmpeg`; mean + σ | iter1 numbers as reference history only |
| **C6** | dmesg clean across the full sweep — specifically no OOPS in `rkvdec_hevc_prepare_hw_st_rps` or related | diff pre vs post `dmesg --time-format=ctime` | iter1 empty diff |
| **C7** | (carried over from iter1, was deferred) firefox-fourier vendor-default HEVC engagement — now testable since SDDM auto-login was set up post-iter1 | empty-profile sweep, count `Got VA-API DMABufSurface` for HEVC autoplay | optional — capture if rig allows but not iter2-blocking |
| **C8** | **regression check** — ampere-fourier iter1's 3-codec baseline (H.264, VP8, MPEG-2) still passes C1-C6 per iter1 per-codec floors | re-run `~/measurements/p3_*.sh` post-patch | iter1 numbers verbatim |
## Hypothesis
With the vendored GStreamer parser + EXT_SPS_*_RPS control population:
- C1-C3, C5-C6, C8 pass
- C4 falls in H.264-drift territory (~0.65 ± 0.05) per fresnel + ampere iter1 convergent observations — RK3588 rkvdec is conformant within H.265 spec tolerance but not bit-identical to libavcodec SW
- C7 passes if rig (auto-login Wayland session) holds at test time
## Hypothesis falsifiers (loopback edges)
- **F1**: HEVC decode still OOPSes despite the new controls being set with valid GStreamer-parser data → loopback Phase 0 with re-opened `kernel-agent#11`. Mechanism is something other than UAPI-gap; needs deeper kernel-side debugging.
- **F2**: HEVC decode succeeds (no OOPS) but produces garbage output (C3 fails — frame 0 not byte-identical) → loopback Phase 4. The parser is producing wrong field values; bisect against GStreamer's reference output or FFmpeg's WIP equivalent on the same clip.
- **F3**: HEVC decode succeeds and produces clean output but ampere-fourier iter1 regression (C8 fails) → loopback Phase 4. The patch is touching shared HEVC code in a way Phase 5 review didn't catch (e.g. unconditional control submission breaks RK3399 path). Per-driver gate via `driver_data->driver_kind` per `feedback_per_driver_kludge_gating`.
- **F4**: Parser vendoring hits LGPL/MIT/license compatibility issues at distribution time → not a code falsifier; revisit at Phase 6 with the operator if it surfaces.
## Out of iter2
- VP9 — that's iter3.
- AV1 — that's `libva-v4l2-request-fourier#2` outside this meta-campaign.
- Kernel-side defense-in-depth NULL/uninit guard for `rkvdec_hevc_prepare_hw_st_rps` — upstream-defense work, optional follow-up issue against kernel-agent or directly upstream.
- IOMMU restore patch verification (Phase 0 open Q4) — passive substrate check during iter2 Phase 2.
## Phase 1 close
Goal, eight success criteria (C1-C8), four falsifier paths. Parser-source decision locked. Ready for iter2 Phase 2 (situation analysis + reset-context).