Files
fresnel-fourier/phase0_findings_iter2.md
claude-noether 6e8c970c1d iter2 Phase 0 + Phase 1 lock: HEVC Main on rkvdec
Iteration 2 of the campaign 8(+1)-phase loop opens following iter1
close (dc69378). Per phase0_evidence/2026-05-07/cross_validator_
traces.md suggested ordering, iter2 attacks HEVC Main on rkvdec —
the kernel + driver path is verified working (cross-validator sweep
exit 0); broken link is the libva backend at five distinct sites:

  src/config.c HEVCMain case fall-through (analogous to iter1 Bug 1)
  src/picture.c HEVCMain explicit UNSUPPORTED_PROFILE reject (NEW)
  src/h265.c uncompiled in build (presumably staging-era CIDs;
              Phase 2 source-read decides scope of rewrite)
  include/hevc-ctrls.h staging-era local header (deferred from
              iter1 Phase 5 Nit 6; iter2 closes the loop)
  src/meson.build h265.c commented out (re-enable)

Plus possible novel issues vs iter1's MPEG-2 work:
  - HEVC has 10 stateless control IDs vs MPEG-2's 3 (much larger
    rewrite if h265.c uses staging-era API)
  - HEVC slice_params is dynamic-array (kernel rkvdec accepts up
    to 600 entries) — different submission shape vs MPEG-2 single-
    struct or H.264 fixed-shape
  - HEVC SCALING_MATRIX is conditional (only when scaling_list_
    enabled in SPS); mapping VAIQMatrixBufferHEVC to V4L2 control
  - HEVC ENTRY_POINT_OFFSETS is in kernel surface (tile/slice
    resync) but campaign fixture doesn't use tiles — defer

Locked research question:

  Make HEVC Main the third codec to pass boolean-correctness on
  fresnel via libva-v4l2-request-fourier — mpv --hwdec=vaapi
  bbb_720p10s_hevc.mp4 engages backend cleanly and DMA-BUF GL
  import yields HW pixels byte-identical to SW reference for the
  same frames.

Phase 1 success criterion (5 boolean checks, all must pass):

  1. vainfo enumerates VAProfileHEVCMain on rkvdec env binding
     (regression check; already passes today).
  2. vaCreateConfig(VAProfileHEVCMain, VLD) returns VA_STATUS_
     SUCCESS. (Pre-iter2: VA_STATUS_ERROR_UNSUPPORTED_PROFILE.)
  3. ffmpeg -hwaccel vaapi -i bbb_720p10s_hevc.mp4 -frames:v 5
     -f null - exits 0 cleanly with no Failed-to-create-decode-
     configuration lines and no S_EXT_CTRLS EINVAL on HEVC
     controls. (Phase 1 criterion 3 anchored on ffmpeg-direct,
     mirroring iter1 Phase 5 Q4 amendment for codecs mpv may
     filter out.)
  4. mpv --hwdec=vaapi --vo=image at +02s seek: 2 distinct frames
     hash-equal to SW reference, hash-differ from each other (real
     motion). DMA-BUF GL import path per memory feedback_rockchip_
     pixel_verify_path.md (NOT ffmpeg-vaapi+hwdownload, which is
     cache-stale on RK3399 for both H.264 and MPEG-2 per iter1
     Phase 6/7 findings).
  5. iter1 MPEG-2 + T4 H.264 reference hashes BOTH still match
     (regression check on prior-iteration cells):
       MPEG-2 +02s: HW1=6e7873030dbf...   HW2=ccc7ce08810d...
       H.264 +30s:  HW1=f623d5f7a416...   HW2=7d7bc6f2146d...

Substrate carry-over:

  - libva-v4l2-request-fourier master tip post-iter1-close
    (commits e7dad7a..229d6d1 stack on iter8 65969da).
  - bbb_720p10s_hevc.mp4 fixture (620 KB, HEVC Main, 1280x720,
    24fps, 10s, yuv420p; provenance phase0_evidence/2026-05-07/
    test_fixtures.md).
  - Cross-validator anchor: phase0_evidence/2026-05-07/
    cross_validator/hevc/ — 14 S_EXT_CTRLS + 5 QUERY_EXT_CTRL
    (HEVC slice_params dynamic-array introspection unique among
    the 5 codecs) + 4 REQUEST_ALLOC.
  - Memory carries forward: feedback_gitea_as_claude_noether,
    feedback_no_session_termination_attempts, feedback_header_
    deletion_check (iter1 lesson L1 — apply to hevc-ctrls.h
    deletion), feedback_review_empirical_over_theoretical
    (iter1 lesson L2 — apply to Phase 5 review responses),
    feedback_rockchip_pixel_verify_path (iter1 lesson L3 —
    DMA-BUF GL is the verifier, NOT cached-mmap).

Out-of-scope (LOCKED): VP9/VP8 (later iterations); HEVC Main 10
(silicon support unverified); HEVC Main Still Picture; performance
metrics; long-duration HEVC stress; tile / wavefront parallel
processing (ENTRY_POINT_OFFSETS); Phase 4 cross-cutting backlog
(B1 device-discovery, B3 BeginPicture profile-aware reset, B4
context.c log suppression, B5 vbv_buffer_size negotiation, L3
vaDeriveImage cache-stale fix); chromium-fourier 149 install;
src/context.c changes; upstream engagement.

Predecessor open questions:
  - iter1 B3 latent surface-reuse bug (picture.c:287
    h264.matrix_set=false hits union byte 240) — for HEVC, the
    union member is params.h265.{picture,slice,iqmatrix,
    iqmatrix_set}. params.h265 layout differs from params.mpeg2.
    Phase 2 source-read action item: verify whether byte 240 lands
    in a meaningful HEVC field. If so, iter2 may need to address
    even though MPEG-2 didn't.

Phase 2 source-read targets (queued for next phase):
  - src/h265.c (~267 lines) — current state, target API
  - src/picture.c:204-206 (the explicit HEVC reject)
  - src/config.c:55-69 (confirm HEVCMain fall-through)
  - src/surface.h:103-108 (params.h265 struct)
  - include/hevc-ctrls.h (staging-era; identify CID/struct refs)
  - src/meson.build (commented-out h265.c)
  - linux/v4l2-controls.h:2110+ (modern HEVC stateless UAPI)
  - drivers/staging/media/rkvdec/rkvdec_hevc.c (rkvdec contract)
  - libavcodec/v4l2_request_hevc.c (FFmpeg reference impl)
  - va/va_dec_hevc.h (VAAPI HEVC buffer structs)

Predicted iter2 close shape: similar pattern to iter1 (config
break + h265.c new-API rewrite + header delete + meson re-enable
+ picture.c reject removal). Larger code change than iter1
(predicting 250-400 lines for h265.c rewrite vs iter1's ~120 lines
for mpeg2.c). One novel construct (slice_params dynamic-array)
worth Phase 4 contract-clause-level attention. Expect Phase 6
takes longer than iter1; Phase 7 harness re-uses iter1's pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:44:30 +00:00

158 lines
20 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.
# Iteration 2 — Phase 0 (substrate / motivation / inventory) → Phase 1 lock
Opens 2026-05-08 immediately after iter1 close ([`phase8_iteration1_close.md`](phase8_iteration1_close.md), commit `dc69378`). Per `feedback_dev_process.md` Phase 0, this document captures iter2's locked research question + substrate + scope, ending with the Phase 1 measurable success criterion.
## Locked research question (iteration 2)
> **"Make HEVC Main the third codec to pass boolean-correctness on fresnel via the libva-v4l2-request-fourier path — `mpv --hwdec=vaapi bbb_720p10s_hevc.mp4` engages the backend cleanly and DMA-BUF GL import yields HW pixels byte-identical to a software-decoded reference for the same frames."**
Pass/fail (boolean):
1. **Profile enumeration regression check.** `vainfo` with the rkvdec env binding (`LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video<N>`, `LIBVA_V4L2_REQUEST_MEDIA_PATH=/dev/media<M>` where `N`/`M` are this-boot's rkvdec node numbers — see device-numbering caveat below) continues to list `VAProfileHEVCMain`. (The enumerator already advertises HEVCMain unconditionally on rkvdec, gated only by the V4L2 `V4L2_PIX_FMT_HEVC_SLICE` format probe; this exists to confirm iter2 work doesn't strip the enumeration.)
2. **Config creation succeeds.** `vaCreateConfig(VAProfileHEVCMain, VAEntrypointVLD)` returns `VA_STATUS_SUCCESS`. (Today returns `12 = VA_STATUS_ERROR_UNSUPPORTED_PROFILE` per [`phase0_evidence/2026-05-07/cross_validator_traces.md`](phase0_evidence/2026-05-07/cross_validator_traces.md) — same fall-through bug iter1 fixed for MPEG-2.)
3. **End-to-end decode engages the backend.** `ffmpeg -hwaccel vaapi -i ~/fourier-test/bbb_720p10s_hevc.mp4 -frames:v 5 -f null -` (with rkvdec env binding) shows the libva chain in stderr, libva trace shows `vaCreateConfig SUCCESS`, no `Failed to create decode configuration`, no `EINVAL` from `VIDIOC_S_EXT_CTRLS`, exits 0. (Phase 1 criterion #3 wording is ffmpeg-direct, mirroring iter1 Phase 5 Q4 amendment — mpv `--hwdec=vaapi-copy` may also silently filter HEVC out before libva is loaded; ffmpeg-direct exercises the path. mpv-driven testing follows in criterion #4 via DMA-BUF GL.)
4. **Cache-safe pixel verification matches SW reference.** `mpv --hwdec=vaapi --vo=image --frames=2 --start=00:00:02` against `bbb_720p10s_hevc.mp4` and the equivalent `--hwdec=no` SW run produce JPEGs whose `sha256sum` outputs match for both frame 1 and frame 2. Frames 1 and 2 must hash-differ between each other (real motion content, not solid color) AND hash-equal across HW vs SW. Per [`memory/feedback_rockchip_pixel_verify_path.md`](../../.claude/projects/-home-mfritsche-src-fresnel-fourier/memory/feedback_rockchip_pixel_verify_path.md): DMA-BUF GL is the cache-coherency-safe verifier; do NOT use ffmpeg-vaapi+hwdownload (vaDeriveImage cache-stale class returns all-zero on RK3399).
5. **Regression check on iter1 MPEG-2 AND T4 H.264.** Both prior-iteration boolean cells continue to pass:
- MPEG-2 hashes at +02s seek still `6e7873030dbf...` and `ccc7ce08810d...` (iter1 Phase 7 reference).
- T4 H.264 hashes at +30s seek still `f623d5f7...` and `7d7bc6f2...` (iter1 Phase 7 + T4 reference).
Iter2 must not regress either codec.
A clean iter2 close has all five checks green. Anything less loops back to Phase 4 per `feedback_dev_process.md` Phase 7 → Phase 4 edge.
## Mechanism the question targets
Phase 0 cross-validator sweep ([`phase0_evidence/2026-05-07/cross_validator_traces.md`](phase0_evidence/2026-05-07/cross_validator_traces.md)) established the kernel + rkvdec driver path works for HEVC: `ffmpeg -hwaccel v4l2request -i bbb_720p10s_hevc.mp4 -frames:v 2 -f null - = exit 0`. So the broken link is the libva backend. From iter1 Phase 2 source-read of the master tip:
- `src/config.c:55-69` `RequestCreateConfig``case VAProfileHEVCMain:` falls through to `default:` returning `VA_STATUS_ERROR_UNSUPPORTED_PROFILE`. iter1 added a `break;` for the MPEG-2 cases; HEVC stays in the fall-through bucket.
- `src/picture.c:204-206` `codec_set_controls``case VAProfileHEVCMain:` explicitly returns `VA_STATUS_ERROR_UNSUPPORTED_PROFILE` with the comment `/* Fourier-local: HEVC stripped, no HW support on RK3566. */`. The "no HW support on RK3566" rationale was for ohm (PineTab2 RK3566/RK3568) at libva-multiplanar iter5 close; on RK3399 fresnel rkvdec, HEVC IS supported in silicon (cross-validator confirms).
- `src/meson.build``# 'h265.c'` is commented out in the `sources` list. Re-enable.
- `src/h265.c` — uncompiled today; likely uses staging-era control IDs from `include/hevc-ctrls.h` (analogous to mpeg2.c using staging-era `mpeg2-ctrls.h` before iter1). The new mainline kernel UAPI for HEVC stateless controls lives at `include/uapi/linux/v4l2-controls.h:2110+` with control IDs `V4L2_CID_STATELESS_HEVC_{SPS,PPS,SLICE_PARAMS,SCALING_MATRIX,DECODE_PARAMS,DECODE_MODE,START_CODE,ENTRY_POINT_OFFSETS,EXT_SPS_ST_RPS,EXT_SPS_LT_RPS}` (10 control IDs total — substantially more than MPEG-2's 3).
- `include/hevc-ctrls.h` — local fork header, staging-era. iter1 Phase 5 Nit 6 deferred this deletion; iter2 closes that loop.
iter2 likely encounters **four bugs** structurally analogous to iter1, plus possibly more:
- **B1 (analogous to iter1 Bug 1)**: config.c HEVCMain case fall-through. Fix shape: 3-line `break;` addition.
- **B2 (analogous to iter1 Bug 2)**: src/h265.c using staging-era CIDs. Fix shape: rewrite against the new V4L2_CID_STATELESS_HEVC_* split API. Larger than iter1's mpeg2.c rewrite because HEVC has 10 control IDs vs MPEG-2's 3.
- **B3 (analogous to iter1 Bug 3)**: `include/hevc-ctrls.h` is the staging-era local header. Fix shape: delete the file; verify no remaining includes via clean rebuild after include-removal patches (per [`memory/feedback_header_deletion_check.md`](../../.claude/projects/-home-mfritsche-src-fresnel-fourier/memory/feedback_header_deletion_check.md) — grep alone is insufficient).
- **B4 (NEW)**: picture.c::codec_set_controls explicitly returns UNSUPPORTED_PROFILE for HEVCMain. Fix shape: replace the explicit reject with a dispatch to `h265_set_controls`.
- **B5 (meson)**: src/meson.build comments out `h265.c`. Fix shape: uncomment.
Plus possibly:
- **B6**: VAAPI VAPicture/VASlice/VAIQMatrix HEVC structs may not map 1:1 to the new V4L2 control structs. Phase 2 source-read of `<va/va_dec_hevc.h>` + the kernel UAPI HEVC structs will identify any mismatches.
- **B7**: HEVC slice_params is a dynamic-array control (kernel UAPI `v4l2-controls.h:2117` `V4L2_CID_STATELESS_HEVC_SLICE_PARAMS` is per-slice; rkvdec accepts up to 600 entries per Phase 0 v4l2-ctl inventory). The libva backend must accumulate per-slice params and submit them as a dynamic-array. Different shape from H.264 (which uses single VASliceParameter per RenderPicture call) and MPEG-2 (which doesn't have slice params at all in the new API).
Phase 4 plan must cite the contract before patching (`feedback_dev_process.md` Phase 6 contract-before-code): read kernel `drivers/staging/media/rkvdec/rkvdec_hevc.c` (the rkvdec HEVC driver source), read FFmpeg downstream `libavcodec/v4l2_request_hevc.c`, read mainline `include/uapi/linux/v4l2-controls.h:2110+`, state the HEVC control-submission contract explicitly before any code lands.
## Predecessor carry-over (iter1 → iter2)
### State that carries forward (re-verified at iter2 open)
- **Hardware**: fresnel RK3399, kernel `6.19.9-99-eos-arm`. ftrace + tracing enabled. mpv 0.41.0 stock, ffmpeg n8.1-13 (Kwiboo branch), libva 1.23.0.
- **rkvdec node**: Phase 7 verified `/dev/video1` + `/dev/media0` on the boot of 2026-05-08 morning. **Caveat**: V4L2 `/dev/videoN` numbering shuffles across reboots (per iter1 Phase 8 backlog B1). iter2 binding cells should re-verify `v4l2-ctl --info` at session start. Long-term fix candidate: backend-side device-discovery probe (Phase 4 cross-cutting, not iter2).
- **Decoder formats** (rkvdec, from [`phase0_evidence/2026-05-07/v4l2_inventory.txt`](phase0_evidence/2026-05-07/v4l2_inventory.txt)): OUTPUT_MPLANE = `S265` (HEVC Parsed Slice Data) + `S264` (H.264) + `VP9F` (VP9). CAPTURE_MPLANE = `NV12`.
- **Stateless control payloads** kernel exposes (rkvdec, HEVC): `hevc_sequence_parameter_set` (`0x00a40a90`), `hevc_picture_parameter_set` (`0x00a40a91`), `hevc_slice_parameters` (`0x00a40a92`, dynamic-array max 600 elems), `hevc_scaling_matrix` (`0x00a40a93`), `hevc_decode_parameters` (`0x00a40a94`), `hevc_decode_mode` (`0x00a40a95`, menu, FRAME_BASED only), `hevc_start_code` (`0x00a40a96`, menu, ANNEX_B only).
- **HEVC profile menu** (rkvdec): Main, Main Still Picture, Main 10. RK3399 silicon support for Main 10 (10-bit) is unverified; iter2 fixture is 8-bit Main only.
- **Backend build state**: libva-v4l2-request-fourier master tip post-iter1-close, including:
- iter1 commits: `e7dad7a` (config.c break) + `5fe873c` (mpeg2.c rewrite) + `3aab187` (delete include/mpeg2-ctrls.h) + `229d6d1` (commit D fix-forward).
- iter1's MPEG-2 path is a working reference for the patch shape (config.c break + new-API rewrite + header delete + grep-audit incompleteness fix).
- `src/h265.c` is **already in the source tree** (267 lines per Phase 0 inventory) — Phase 2 will audit whether it uses staging-era or modern API. If staging-era, rewrite is the bulk of iter2 work. If somehow already on modern API, the work is much smaller.
- **Test fixture**: `~/fourier-test/bbb_720p10s_hevc.mp4` on fresnel (620 KB, HEVC Main, 1280×720@24fps, yuv420p, 10s, generated 2026-05-07 23:34 from H.264 master via libx265 ultrafast). Provenance: [`phase0_evidence/2026-05-07/test_fixtures.md`](phase0_evidence/2026-05-07/test_fixtures.md).
- **Reference fixtures for regression**: `~/fourier-test/bbb_1080p30_h264.mp4` (T4 reference) and `~/fourier-test/bbb_720p10s_mpeg2.ts` (iter1 reference).
- **iter1 + T4 reference hashes for regression criterion 5**:
- H.264 (T4) at +30s: HW frame 1 `f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9`, frame 2 `7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8`.
- MPEG-2 (iter1) at +02s: HW frame 1 `6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092`, frame 2 `ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de`.
- **Cross-validator anchor**: ffmpeg-v4l2request HEVC contract from [`phase0_evidence/2026-05-07/cross_validator/hevc/`](phase0_evidence/2026-05-07/cross_validator/hevc/). 14 `S_EXT_CTRLS`, 5 `QUERY_EXT_CTRL` (HEVC slice_params dynamic-array introspection — unique among the 5 codecs), 4 `MEDIA_IOC_REQUEST_ALLOC`. 60 ftrace v4l2 events for 2 frames.
- **Cache-safe verify path**: `mpv --hwdec=vaapi --vo=image` (DMA-BUF GL import). Confirmed for H.264 (T4) and MPEG-2 (iter1 Phase 7); iter2 expects the same path to work for HEVC.
### Data that does NOT carry forward (re-acquire if needed)
- ohm/RK3568 hantro HEVC behavior — there is none; RK3568 hantro doesn't decode HEVC. RK3399 rkvdec is the first time the libva-v4l2-request-fourier fork sees HEVC on real hardware. Reference history: zero.
- libva-multiplanar iter1-iter5 close docs' "HEVC stripped" disposition — that was an ohm-side build-cleanly decision, not an empirical "HEVC doesn't work" finding. iter2 reverses the strip.
### Open questions inherited from iter1 close
- **B3 latent surface-reuse bug** ([`phase8_iteration1_close.md`](phase8_iteration1_close.md) backlog): `picture.c:287` `params.h264.matrix_set = false` writes union byte 240, lands inside `mpeg2.iqmatrix.chroma_intra_quantiser_matrix[20]`. For HEVC, the union member is `params.h265.{picture, slice, iqmatrix, iqmatrix_set}`. The `params.h265` struct layout differs from `params.mpeg2` (per [`src/surface.h:90-109`](../libva-multiplanar/libva-v4l2-request-fourier/src/surface.h)). iter2 should verify whether byte 240 lands inside `h265.iqmatrix` or elsewhere; if it lands in a meaningful HEVC field, the latent bug becomes acute for iter2's binding cells. **Phase 2 source-read action item**.
- **Phase 4 cross-cutting work items** (vaDeriveImage fix, V4L2 device-discovery, BeginPicture profile-aware reset, context.c log suppression): not iter2 scope; iter2 works around them via DMA-BUF GL verify path and re-checked device numbers.
## Tooling and measurement-instrument inventory (live verification)
Re-verified at iter2 open (carries forward from iter1, all proven working):
- `strace -ff -tt -y -v -e trace=ioctl,openat,close` — captures V4L2 + media-request ioctl sequence per thread.
- `LIBVA_TRACE` environment variable — captures vaCreate/vaQuery/vaInitialize call traces with status return codes.
- `sudo sh -c "echo 1 > /sys/kernel/tracing/events/v4l2/enable"` — captures kernel v4l2 tracepoints (qbuf/dqbuf events).
- `mpv --hwdec=vaapi --vo=image` — cache-coherency-safe pixel verifier (DMA-BUF GL import).
- `ffmpeg -hwaccel v4l2request` — independent V4L2 client cross-validator (different code path than libva).
- Backend build harness on fresnel: `ninja -C ~/src/libva-v4l2-request-fourier/build && sudo ninja -C build install`.
- Empirical HEVC decode of `bbb_720p10s_hevc.mp4` via ffmpeg-v4l2request DRM_PRIME path — proven works in cross-validator sweep.
iter2 will likely add per-source debug `printf`/`fprintf(stderr, ...)` instrumentation in `src/h265.c` during Phase 6. That instrumentation is iter2-internal scratch; clean sweep at iter2 close per Phase 5 review precedent.
## In-scope (LOCKED 2026-05-08 for iteration 2)
- libva-v4l2-request-fourier backend HEVC Main path on rkvdec.
- `src/config.c::RequestCreateConfig` — add `break;` for `VAProfileHEVCMain` case (analogous to iter1 Commit A pattern for MPEG-2).
- `src/picture.c::codec_set_controls` — replace the explicit `case VAProfileHEVCMain: return UNSUPPORTED_PROFILE` with a dispatch to `h265_set_controls`.
- `src/h265.c` — Phase 2 source-read decides the scope: if it uses staging-era CIDs, full rewrite against new split API. If somehow already modern, the audit produces a delta. Plus any fixes needed for VAAPI ↔ V4L2 control struct mapping (slice_params dynamic-array semantics, scaling_matrix conditional, decode_params per-frame).
- `include/hevc-ctrls.h` — DELETE (iter1 Phase 5 Nit 6 deferred this; iter2 closes the loop). Apply [`memory/feedback_header_deletion_check.md`](../../.claude/projects/-home-mfritsche-src-fresnel-fourier/memory/feedback_header_deletion_check.md) discipline: drop `#include` from all callsites + clean rebuild + then `git rm`.
- `src/meson.build` — uncomment `'h265.c'` in the sources list.
- iter2 binding-cell test harness: re-run iter1's Phase 7 5-criterion harness substituting HEVC fixture, plus iter1's MPEG-2 + T4 H.264 regression checks.
- Cache-safe pixel verify must use DMA-BUF GL import (not vaDeriveImage), per memory `feedback_rockchip_pixel_verify_path.md`.
## Out-of-scope (LOCKED 2026-05-08 for iteration 2)
- VP9, VP8 work (iter3/iter4).
- HEVC Main 10 (10-bit). Silicon support unverified; campaign codec scope is 8-bit yuv420p.
- HEVC Main Still Picture profile (rkvdec advertises it via the menu, but the campaign fixture is Main, not Main Still Picture; defer).
- Performance metrics (Phase 1+ separate iteration).
- Long-duration HEVC stress (>10s).
- HEVC tile / wavefront parallel processing (`ENTRY_POINT_OFFSETS` is in the kernel surface but the campaign fixture doesn't use tiles; defer).
- Phase 4 cross-cutting backlog items B1 (V4L2 device-discovery), B3 (BeginPicture profile-aware reset), B4 (context.c log suppression), B5 (vbv_buffer_size negotiation), L3 (vaDeriveImage cache-stale fix). All carry forward from iter1; not iter2 scope.
- chromium-fourier 149 install on fresnel (carry-over from iter1 deferred).
- `src/context.c` — no changes (the H.264 device-init unconditional-EINVAL is auxiliary noise per iter1 Phase 7; benign for HEVC binding cells).
- Upstream Linux engagement (per `feedback_no_upstream.md`). Kernel-side works; nothing to file.
## Phase 1 success criterion (LOCKED 2026-05-08)
The five Pass/fail bullets at the top of this document are the iter2 success criterion. Phase 3 baseline measurements feed Phase 4 plan; Phase 7 verification re-runs all five against the patched backend.
If Phase 3 baseline reveals the chosen criterion is the wrong target (Phase 3 → Phase 1 loopback per `feedback_dev_process.md`), the criterion will be rewritten and re-locked. Plausible reasons that would trigger the loopback:
- The HEVC fixture is malformed in a way that exposes a fixture-side bug rather than a backend-side bug. (Mitigation: ffmpeg-v4l2request decodes the same fixture cleanly per Phase 0 cross-validator sweep, so this is unlikely.)
- HEVC slice_params dynamic-array semantics on rkvdec require a different submission shape than expected (e.g., per-slice `S_EXT_CTRLS` vs single batched submission with a slice_params array). Phase 3 baseline of ffmpeg-v4l2request HEVC trace will resolve.
- mpv `--hwdec=vaapi` (DMA-BUF) ALSO filters HEVC out (Phase 5 Q4 amendment for iter1 ended up being non-blocking because mpv-vaapi engages MPEG-2; we'll see if HEVC behaves the same). Mitigation: fall-forward to ffmpeg-v4l2request DRM_PRIME + hwdownload pixel verify (we know that works; criterion holds, harness adapts).
- VAAPI HEVC consumer pattern requires VAEncSliceParameterBufferType to be sent in some specific order; iter1 didn't have to handle this. Phase 2 source-read will identify.
The other four Phase 1 criteria (vainfo enumeration, vaCreateConfig success, ffmpeg-direct exit 0, MPEG-2+T4 regression) hold as locked — no adjustment expected.
## Phase 2 source-read targets
For the upcoming Phase 2 situation analysis:
- `src/h265.c` (entire file, ~267 lines) — current state, what API it targets, what VAAPI buffers it reads, what V4L2 controls it submits.
- `src/picture.c:204-206` — the explicit HEVC reject; verify the surrounding context.
- `src/config.c:55-69` — confirm HEVC fall-through (already inspected during iter1 Phase 2; nothing should have changed).
- `src/surface.h:103-108` (`params.h265` struct) — VAAPI HEVC buffers in the surface union.
- `include/hevc-ctrls.h` (entire file) — staging-era definitions; identify which CIDs and structs are referenced from `src/h265.c`.
- `src/meson.build` — confirm `h265.c` commented out; identify any conditional compile flags.
- Kernel UAPI `<linux/v4l2-controls.h>` lines 2110+ — modern HEVC stateless control IDs and struct layouts.
- Linux mainline kernel `drivers/staging/media/rkvdec/rkvdec_hevc.c` — the rkvdec HEVC driver source. Specifically: which controls are mandatory, which are optional, what's the slice_params dynamic-array contract, what's the decode_params contract.
- FFmpeg downstream `libavcodec/v4l2_request_hevc.c` — independent V4L2 client implementation. Submission shape, per-slice params batching, scaling_matrix conditionality.
- VAAPI `<va/va_dec_hevc.h>` — VAAPI HEVC buffer struct definitions (especially `VAPictureParameterBufferHEVC`, `VASliceParameterBufferHEVC` (and any 422/444 ext variants), `VAIQMatrixBufferHEVC`).
## What "iteration 2 close" looks like
A clean iter2 close per `feedback_dev_process.md` Phase 8:
- All 5 Phase 1 criteria green.
- `phase8_iteration2_close.md` summarizing the bug, contract, fix, binding-cell numbers.
- Third-codec passing on the campaign-level scoreboard: 2/5 → 3/5.
- Memory entries distilled for any new lessons (iter1 produced 3; iter2 may produce 0 if the work mirrors iter1's MPEG-2 pattern cleanly, or more if HEVC surfaces novel issues).
- Debug-instrumentation sweep at close.
- Phase 5 sonnet-architect review pass signed off.
- Commits all authored as `claude-noether` per [`memory/feedback_gitea_as_claude_noether.md`](../../.claude/projects/-home-mfritsche-src-fresnel-fourier/memory/feedback_gitea_as_claude_noether.md).
- `include/hevc-ctrls.h` deleted (closing iter1 Phase 5 Nit 6).
- `src/h265.c` re-enabled in `src/meson.build`, modernized against new V4L2 stateless API, dispatched correctly from picture.c.
Predicted iter2 difficulty vs iter1: similar shape (config break + new-API rewrite + header delete + grep-audit completeness), larger scope (10 control IDs vs 3), one novel construct (slice_params dynamic-array). Expect Phase 6 to take longer than iter1 (~120 lines mpeg2.c rewrite vs probably 250-400 lines for h265.c). Phase 7 verification harness re-uses iter1's pattern verbatim.