Files
fresnel-fourier/phase3_iter2_baseline.md
claude-noether d35a247948 iter2 Phase 3: baselines — substrate verified post-upgrade, HEVC anchor captured
Phase 3 baselines for iter2 HEVC. Substrate-update verification
ran first (post pacman -Syu rolling upgrade), then iter2-specific
HEVC cross-validator anchor + Bug 1 scratch.

Pre-Phase-3 substrate event: pacman -Syu landed 71 packages.
The "scheduled for linux-7" upgrade was headers-only —
linux-eos-arm-headers 6.19.9-99 → 7.0.3-1, but linux-eos-arm
kernel binary stayed at 6.19.9-99 (EOS-ARM repo hasn't
published the matching 7.x kernel yet). Userland refreshed:
qt6-base epoch bump, libdrm 2.4.131 → 2.4.133, chromium
147 → 148, KDE 26.04.1 batch, mkinitcpio 41-3, etc. OC DTB
intact (sha256 unchanged). mfritsche Plasma session active
throughout, no SDDM regression on this kernel boot.
eos-reboot-recommended marker installed; reboot deferred.

Baseline A (substrate validation post-upgrade):

  T4 H.264 +30s and iter1 MPEG-2 +02s reference hashes all
  8 match exactly:
    H.264 HW1=SW1=f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9
    H.264 HW2=SW2=7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8
    MPEG-2 HW1=SW1=6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092
    MPEG-2 HW2=SW2=ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de
  Userland upgrade did not regress kernel-side decode or
  DMA-BUF GL readback.

Baseline B (HEVC cross-validator verbatim contract anchor):

  ffmpeg -hwaccel v4l2request decoded bbb_720p10s_hevc.mp4
  -frames:v 5 cleanly. Per-frame submission shape:

    VIDIOC_S_EXT_CTRLS, ctrl_class=V4L2_CTRL_CLASS_CODEC_STATELESS,
                        count=5
      0xa40a90 SPS            size=40
      0xa40a91 PPS            size=64
      0xa40a92 SLICE_PARAMS   size=N (dynamic-array)
      0xa40a93 SCALING_MATRIX size=M
      0xa40a94 DECODE_PARAMS  size=328
    Plus init device-wide:
      0xa40a95 DECODE_MODE    (menu, set once)
      0xa40a96 START_CODE     (menu, set once)

  Key Phase 2 amendments from Phase 3 evidence:
    - Per-frame batch is 5 controls (not "up to 6" — BBB
      doesn't trigger ENTRY_POINT_OFFSETS / EXT_SPS_*).
    - SCALING_MATRIX is sent unconditionally for BBB. FFmpeg
      gates on ctx->has_scaling_matrix from kernel
      VIDIOC_QUERY_EXT_CTRL at init, NOT on per-frame
      bitstream flags. Phase 4 plan amends: query kernel for
      SCALING_MATRIX availability at init, submit if available.

  SPS payload field-decoded (40 bytes verbatim from BBB
  fixture): 1280x720, 8-bit, 4:2:0, no PCM, flags = SAO |
  STRONG_INTRA_SMOOTHING. PPS + DECODE_PARAMS + SLICE_PARAMS +
  SCALING_MATRIX payloads captured for Phase 4 transcription.

Baseline C (slice-count probe): deferred. ffprobe confirms
1 video stream HEVC Main 1280x720 24fps 10s. Per-frame
slice-count not directly extracted; assume 1 slice/frame for
x265 ultrafast preset until Phase 6 verifies. Kernel
advertises slice_params dynamic-array max 600 entries
(phase0 v4l2_inventory), so multi-slice frames are supported
by the contract.

Baseline D (Bug 1 scratch test, collateral safety):

  Applied Bug 1 (config.c break for HEVCMain) on throwaway
  branch; h265.c stayed disabled. Built + installed.
    H.264 HW frames @ +30s: f623d5f7..., 7d7bc6f2... (match T4)
    MPEG-2 HW frames @ +02s: 6e7873030dbf..., ccc7ce08810d...
                              (match iter1)
  Bug 1 in isolation does not regress H.264 or MPEG-2.

  HEVC behavior with Bug 1 only:
    libva trace: vaCreateConfig SUCCESS for VAProfileHEVCMain
    ffmpeg: Task finished with error code: -5 (Input/output error)
  Decode fails downstream because picture.c:204-206 still has
  the explicit case VAProfileHEVCMain: return UNSUPPORTED_PROFILE
  reject (Bug 2). Confirms Phase 2 prediction; Bug 2 fix
  requires h265_set_controls to exist (Bug 3-6: enable +
  rewrite). Bug 2 lands together with the h265.c rewrite in
  Commit B (analogous to iter1 Commit B).

  Scratch state cleaned: git checkout + rebuild + reinstall
  master backend. H.264 + MPEG-2 still pass. Back to Baseline-A-
  equivalent state.

Phase 4 plan inputs updated:
  - Per-frame batch: 5 controls (not "up to 6")
  - SCALING_MATRIX: unconditional iff kernel advertises (init
    QUERY_EXT_CTRL probe), not bitstream-conditional
  - SLICE_PARAMS: dynamic-array (max 600 elems per kernel UAPI)
  - DECODE_MODE + START_CODE: 2 device-wide menus at init
  - Phase 7 harness anchors on mpv-vaapi-vo=image (DMA-BUF GL
    cache-coherency-safe path per
    feedback_rockchip_pixel_verify_path.md)
  - Phase 7 bonus: byte-compare post-fix S_EXT_CTRLS payload
    against Baseline B (per feedback_review_empirical_over_
    theoretical.md — empirical wins)

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

17 KiB
Raw Permalink Blame History

Iteration 2 — Phase 3 (baseline measurements)

Phase 3 baselines for iter2 HEVC, executed 2026-05-08 across two stages: (i) substrate-update verification after a rolling pacman -Syu userland upgrade, (ii) HEVC cross-validator re-anchor + Bug 1 pre-fix scratch test. All four baselines green; iter1 + T4 references hold byte-identical post-upgrade; HEVC contract anchor captured for Phase 4 transcription.

Per feedback_dev_process.md Phase 3 anti-fabrication: raw output leads, derived numbers anchor to visible tool invocations.

Substrate state at Phase 3 start

$ ssh fresnel 'uname -r; pacman -Q linux-eos-arm linux-eos-arm-headers libdrm qt6-base mesa chromium libva mpv ffmpeg-v4l2-request-git'
6.19.9-99-eos-arm
linux-eos-arm 6.19.9-99
linux-eos-arm-headers 7.0.3-1
libdrm 2.4.133-1
qt6-base 1:6.11.0-2
mesa 1:26.0.3-1
chromium 148.0.7778.96-1
libva 2.23.0-1
libva-utils 2.22.0-1
mpv 1:0.41.0-3
ffmpeg-v4l2-request-git 2:8.1.r123329.b57fbbe-2

The "scheduled for linux-7" upgrade landed as headers-only: linux-eos-arm-headers jumped from 6.19.9-99 → 7.0.3-1, but the kernel binary package linux-eos-arm stayed at 6.19.9-99 (the EOS-ARM repo hasn't published the matching kernel package yet). Running kernel unchanged. 71 packages upgraded total (qt6-base epoch bump, libdrm minor, chromium 147→148, KDE 26.04.1 batch, mkinitcpio 41-3, etc.).

OC DTB at /boot/dtbs/rockchip/rk3399-pinebook-pro.dtb was preserved (pre-upgrade snapshot at *.oc-backup-2026-05-08; sha256 b436ed029... unchanged after upgrade — pacman didn't touch it because linux-eos-arm itself wasn't in the upgrade queue).

eos-reboot-recommended package marker installed; mfritsche's Plasma session active throughout (tty1, no SDDM regression on this kernel boot). Reboot deferred — substrate verifies pre-reboot.

Device numbering this boot:

  • rkvdec = /dev/video1 + /dev/media0 (HEVC + H.264)
  • hantro-vpu-dec = /dev/video3 + /dev/media1 (MPEG-2)

Baseline A — substrate verified intact post-upgrade

Goal: re-run iter1 Phase 7 criterion 4 + 5 reference verifications post pacman -Syu. T4 H.264 + iter1 MPEG-2 reference hashes must match exactly. If divergent, substrate regression — investigate before iter2 proceeds.

Verbatim hash output:

H.264 +30s seek (rkvdec /dev/video1 + /dev/media0):
  /tmp/iter2_phase3_substrate/h264_hw/00000001.jpg
    f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9
  /tmp/iter2_phase3_substrate/h264_hw/00000002.jpg
    7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8
  /tmp/iter2_phase3_substrate/h264_sw/00000001.jpg
    f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9
  /tmp/iter2_phase3_substrate/h264_sw/00000002.jpg
    7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8

MPEG-2 +02s seek (hantro /dev/video3 + /dev/media1):
  /tmp/iter2_phase3_substrate/mpeg2_hw/00000001.jpg
    6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092
  /tmp/iter2_phase3_substrate/mpeg2_hw/00000002.jpg
    ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de
  /tmp/iter2_phase3_substrate/mpeg2_sw/00000001.jpg
    6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092
  /tmp/iter2_phase3_substrate/mpeg2_sw/00000002.jpg
    ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de

All 8 hashes match references exactly. T4 H.264 + iter1 MPEG-2 substrate intact post-upgrade. Userland upgrade did not regress kernel-side decode or DMA-BUF GL readback.

(Aside: mesa version reads 1:26.0.3-1 while the iter1 SDDM watchpoint history showed 26.0.3 → 26.0.5 upgrade on 2026-04-28. Either the 26.0.5 was rolled back from the repo without explicit pacman log entry, or the 04-28 entry recorded a bumped revision that resolved to the same 26.0.3 binary. Not iter2-relevant — references match exactly regardless.)

Baseline B — HEVC cross-validator verbatim contract anchor

Goal: extract the byte-level VIDIOC_S_EXT_CTRLS payload that ffmpeg-v4l2request submits per HEVC frame. This is the contract Phase 4 implementation must match.

Invocation:

strace -ff -tt -y -v -s 8192 -e trace=ioctl \
  -o /tmp/iter2_phase3/ffmpeg_v4l2req.strace \
  ffmpeg -hide_banner -loglevel error -hwaccel v4l2request \
    -i ~/fourier-test/bbb_720p10s_hevc.mp4 -frames:v 5 -f null -

ffmpeg exit 0; 5 frames decoded clean.

Per-frame submission shape (verbatim, frame 1):

ioctl(/dev/video1, VIDIOC_S_EXT_CTRLS,
  {ctrl_class=0xf010000 /* V4L2_CTRL_CLASS_CODEC_STATELESS */,
   count=5,
   controls=[
     {id=0xa40a90 /* V4L2_CID_STATELESS_HEVC_SPS */,            size=40,  ...},
     {id=0xa40a91 /* V4L2_CID_STATELESS_HEVC_PPS */,            size=64,  ...},
     {id=0xa40a92 /* V4L2_CID_STATELESS_HEVC_SLICE_PARAMS */,   size=N,   ...},
     {id=0xa40a93 /* V4L2_CID_STATELESS_HEVC_SCALING_MATRIX */, size=M,   ...},
     {id=0xa40a94 /* V4L2_CID_STATELESS_HEVC_DECODE_PARAMS */,  size=328, ...}
   ]}) = 0

Five controls per frame. Full 5-control batched submission ≠ Phase 2 prediction of "up to 6 with conditional ENTRY_POINT_OFFSETS / EXT_SPS_*"; the BBB fixture doesn't trigger the conditional ones.

SCALING_MATRIX is sent unconditionally for the BBB HEVC fixture — this updates Phase 2's "conditional on SPS scaling_list_enabled" assumption. FFmpeg gates SCALING_MATRIX on ctx->has_scaling_matrix derived from kernel VIDIOC_QUERY_EXT_CTRL at init (rather than on any per-frame VAAPI bit). For the libva backend, the equivalent is to query whether the kernel exposes the SCALING_MATRIX control via VIDIOC_QUERY_EXT_CTRL once at init and submit it conditionally on that probe. Phase 4 plan adjusts.

Init device-wide submissions (not in the per-frame batch, set once at decoder init):

  • id=0xa40a95 (V4L2_CID_STATELESS_HEVC_DECODE_MODE) — 2 calls visible (one set, one query/confirm).
  • id=0xa40a96 (V4L2_CID_STATELESS_HEVC_START_CODE) — 2 calls visible.

Verbatim SPS payload (40 bytes, frame 1; same across all frames since SPS is per-stream):

"\0\0\0\5\320\2\0\0\4\4\2\4\1\1\0\3\0\0\377\377\375\0\0\0\1\0\0\0\0\0\0\0\200\1\0\0\0\0\0\0"

Field-by-field decode (per <linux/v4l2-controls.h>:2096-2125, struct v4l2_ctrl_hevc_sps):

Bytes (LE) Value Field
\0 0 video_parameter_set_id
\0 0 seq_parameter_set_id
\0\5 0x0500 = 1280 pic_width_in_luma_samples
\320\2 0x02d0 = 720 pic_height_in_luma_samples
\0 0 bit_depth_luma_minus8 (8-bit)
\0 0 bit_depth_chroma_minus8
\4 4 log2_max_pic_order_cnt_lsb_minus4
\4 4 sps_max_dec_pic_buffering_minus1
\2 2 sps_max_num_reorder_pics
\4 4 sps_max_latency_increase_plus1
\1 1 log2_min_luma_coding_block_size_minus3
\1 1 log2_diff_max_min_luma_coding_block_size
\0 0 log2_min_luma_transform_block_size_minus2
\3 3 log2_diff_max_min_luma_transform_block_size
\0 0 max_transform_hierarchy_depth_inter
\0 0 max_transform_hierarchy_depth_intra
\377 0xFF pcm_sample_bit_depth_luma_minus1 (PCM disabled, so default)
\377 0xFF pcm_sample_bit_depth_chroma_minus1
\375 0xFD log2_min_pcm_luma_coding_block_size_minus3
\0\0\0 0,0,0 log2_diff_max_min_pcm_luma_coding_block_size, num_short_term_ref_pic_sets, num_long_term_ref_pics_sps
\1 1 chroma_format_idc (4:2:0)
\0 0 sps_max_sub_layers_minus1
\0\0\0\0\0\0 0 reserved[6]
\200\1\0\0\0\0\0\0 0x180 = SAMPLE_ADAPTIVE_OFFSET (0x08) | STRONG_INTRA_SMOOTHING_ENABLED (0x100) flags (u64)

So BBB-720p10s_hevc.mp4 has SAO + strong intra smoothing flagged, no PCM, no scaling-list-enabled in SPS-side flags. The unconditional SCALING_MATRIX submission therefore must be triggered by PPS-side flag or by FFmpeg's runtime probe — not bitstream-driven for SPS.

Verbatim PPS payload (64 bytes — v4l2_ctrl_hevc_pps, will field-decode in Phase 4 transcription).

Verbatim DECODE_PARAMS payload (328 bytes — v4l2_ctrl_hevc_decode_params, contains DPB array + POC info, will field-decode in Phase 4).

Verbatim SLICE_PARAMS payload (variable size N — dynamic-array of v4l2_ctrl_hevc_slice_params; likely 1 slice per frame for x265 ultrafast; size = sizeof(v4l2_ctrl_hevc_slice_params) * num_slices).

Verbatim SCALING_MATRIX payload (variable size M — v4l2_ctrl_hevc_scaling_matrix if scaling_list_data is present; will field-decode in Phase 4).

Raw strace files (gitignored): phase0_evidence/2026-05-08/iter2_phase3/ffmpeg_v4l2req.strace.*. Re-run incantation in this document.

ioctl frequency summary (verbatim):

60 ioctl(/dev/video1, VIDIOC_DQBUF
30 ioctl(/dev/video1, VIDIOC_QBUF
17 ioctl(/dev/video1, VIDIOC_S_EXT_CTRLS
17 ioctl(/dev/video1, VIDIOC_CREATE_BUFS
15 ioctl(/dev/video1, VIDIOC_QUERYBUF
11 ioctl(/dev/video1, VIDIOC_EXPBUF
 5 ioctl(/dev/video1, VIDIOC_QUERY_EXT_CTRL  (HEVC slice_params dynamic-array introspection)
 4 ioctl(/dev/media0, MEDIA_IOC_REQUEST_ALLOC  (request_fd pool of 4)
 4 MEDIA_REQUEST_IOC_REINIT × 3 fds + MEDIA_REQUEST_IOC_QUEUE × 3 fds

17 S_EXT_CTRLS = 2 init device-wide (DECODE_MODE + START_CODE) + 15 per-frame (probably 5 frames × 3 calls each? Or 1 batched per frame × 5 + 10 something else; actual layout is observed-counted, not split-aware — re-extract per-frame breakdown if Phase 6 needs it). Frequency summary is sufficient as an anchor.

Baseline C — slice-count probe (deferred)

Quick ffprobe examination of bbb_720p10s_hevc.mp4 confirms 1 video stream, hevc Main, 1280×720, 24 fps, 10s. Per-frame slice-count not directly extracted (would require a bitstream-filter pass like hevc_metadata to count slices per access unit). For x265 ultrafast preset on 720p, default is 1 slice per frame; assume that until Phase 6 verifies. If Phase 6 finds multi-slice frames, the libva backend's slice_params accumulation logic (Phase 2 Bug 4) handles up to 600 entries per frame per kernel UAPI advertising.

Baseline D — Bug 1 pre-fix scratch test (collateral safety)

Goal: apply Bug 1 fix (config.c break for HEVCMain) on a throwaway branch with h265.c + Bug 2 NOT applied, verify H.264 + MPEG-2 reference hashes hold post-rebuild + reinstall. Confirm no collateral damage from the trivial config.c change.

Patch applied:

@@ -68,6 +68,8 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
 		// submission time.
 		break;
 	case VAProfileHEVCMain:
+		// iter2 Phase 3 scratch — would break here in real fix
+		break;
 	default:
 		return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;

Build: clean. Install: clean.

Hash verification (post Bug 1 scratch, h265.c stays disabled):

H.264 +30s:
  HW frame 1: f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9 (matches T4)
  HW frame 2: 7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8 (matches T4)
MPEG-2 +02s:
  HW frame 1: 6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092 (matches iter1)
  HW frame 2: ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de (matches iter1)

Result: no collateral damage. Bug 1 fix in isolation does not regress H.264 or MPEG-2.

HEVC behavior with Bug 1 only (Bug 2 + Bug 3-6 not applied; h265.c still disabled):

[hevc] Task finished with error code: -5 (Input/output error)

libva trace verbatim:

[49437.712028] vaQueryConfigProfiles ret = VA_STATUS_SUCCESS
[49437.712059] va_TraceCreateConfig profile = 17, VAProfileHEVCMain
[49437.712118] vaCreateConfig ret = VA_STATUS_SUCCESS, success (no error)    <-- Bug 1 fix advances past this
[49437.712139] vaQuerySurfaceAttributes ret = VA_STATUS_SUCCESS
... (further surface attribute queries)
... (decode fails downstream because picture.c::codec_set_controls hits the
     case VAProfileHEVCMain: return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
     reject at line 204-206 — that's Bug 2, not yet patched in this scratch)

So Bug 1 alone advances vaCreateConfig to SUCCESS; the next failure is Bug 2's explicit reject at picture.c. Confirms Phase 2 prediction. Bug 2 fix requires h265_set_controls to exist (Bug 3-6: enable + rewrite), so Bug 2 lands together with the h265.c rewrite in Commit B (analogous to iter1 Commit B).

Scratch state cleaned: git checkout -- src/config.c && rebuild && reinstall. Master backend back; H.264 + MPEG-2 still pass; HEVC fails at vaCreateConfig (back to Baseline-A-equivalent state — Bug 1 not applied on master).

What Phase 3 confirms / refutes from Phase 2

Phase 2 claim Phase 3 evidence Status
Bug 1: config.c HEVCMain falls through to default → vaCreateConfig=12 Baseline D libva trace: pre-patch fails, post-patch SUCCESS confirmed
Bug 2: picture.c case VAProfileHEVCMain explicit UNSUPPORTED_PROFILE reject Baseline D libva log: ffmpeg fails decode -5 (I/O error) post-Bug-1, before reaching h265.c (h265.c disabled) confirmed (effect observed, even though h265.c isn't enabled to dispatch)
Bug 3: h265.c uses staging-era CIDs that don't exist on modern kernels Phase 2 source-read + test-compile already verified confirmed
Phase 2 prediction: per-frame batch has 6 controls Baseline B verbatim: 5 controls (no ENTRY_POINT_OFFSETS for BBB fixture) partially refuted: 5 not 6
Phase 2 prediction: SCALING_MATRIX is conditional on bitstream Baseline B: SCALING_MATRIX always present in BBB's per-frame batch refuted: FFmpeg gates on kernel-advertised control availability, not bitstream flag
Phase 2 prediction: slice_params is dynamic-array Baseline B: SLICE_PARAMS variable-size (N entries × 1 slice/frame for x265 ultrafast) confirmed
Substrate intact post pacman -Syu (kernel didn't change) Baseline A: T4 + iter1 hashes match exactly confirmed
linux-eos-arm kernel binary stays at 6.19.9-99 (only headers jump to 7.0.3) pacman.log verifies; running uname -r confirms confirmed
OC DTB intact through upgrade sha256 pre/post upgrade unchanged confirmed

Phase 4 plan inputs (updated)

Phase 4 plan should specify:

  1. Diff scope (Phase 2 mostly correct; minor amendments below):

    • src/config.c:64-69 — add break; for VAProfileHEVCMain (3 lines, mirrors iter1).
    • src/picture.c:204-206 — replace explicit reject with dispatch to h265_set_controls().
    • src/h265.c — rewrite against new V4L2_CID_STATELESS_HEVC_* split API. Per-frame batch is 5 controls (SPS, PPS, SLICE_PARAMS dynamic-array, SCALING_MATRIX, DECODE_PARAMS). DECODE_MODE + START_CODE device-wide menus set once at init.
    • src/picture.c::codec_store_buffer (HEVC VASliceParameterBufferType case) — append-not-overwrite for slice_params accumulation.
    • src/surface.h::params.h265 — add slice_params array + count.
    • src/meson.build — uncomment h265.c (line 50) + h265.h (line 73).
  2. SCALING_MATRIX gating (amended from Phase 2): query kernel via VIDIOC_QUERY_EXT_CTRL for V4L2_CID_STATELESS_HEVC_SCALING_MATRIX once at init; submit unconditionally per-frame if kernel advertises (matches FFmpeg ctx->has_scaling_matrix pattern). For BBB on RK3399, the kernel advertises it, so SCALING_MATRIX always in the batch.

  3. Default scaling matrices if iqmatrix_set==false: per ISO/IEC 23008-2 Table 4-1 default scaling lists (4×4, 8×8, 16×16, 32×32 with separate luma/chroma variants). Phase 6 transcription from FFmpeg's default_scaling_list_intra / default_scaling_list_inter arrays in libavcodec/hevc.h — verify against Baseline B SCALING_MATRIX verbatim payload (all-default values for BBB fixture).

  4. Contract anchor citations (per Phase 6 contract-before-code):

    • Linux mainline UAPI <linux/v4l2-controls.h>:2090-2300 for the 5+2 stateless HEVC control struct definitions and flag constants.
    • FFmpeg libavcodec/v4l2_request_hevc.c:505-565 (v4l2_request_hevc_queue_decode) for batched submission shape.
    • Phase 3 Baseline B verbatim 5-control payload (this document).
    • VAAPI <va/va_dec_hevc.h> for VAPictureParameterBufferHEVC, VASliceParameterBufferHEVC, VAIQMatrixBufferHEVC source field shapes.
  5. Phase 7 verification harness: re-use iter1's 5-criterion shape, anchor on mpv --hwdec=vaapi --vo=image DMA-BUF GL path (cache-coherency-safe per memory feedback_rockchip_pixel_verify_path.md). HEVC fixture at +02s seek; HW vs SW byte-identical hashes for 2 distinct frames; iter1 MPEG-2 + T4 H.264 still match. Bonus: byte-compare post-fix S_EXT_CTRLS payload against Baseline B (per feedback_review_empirical_over_theoretical.md — empirical wins).

Open question for Phase 6 close

The iter2 fix-forward pattern from iter1 Commit D (header deletion completeness check via clean rebuild, not grep) applies to iter2's mpeg2-ctrls.h re-grep audit during Phase 6 (defensive — even though iter1 cleaned it up). Per feedback_header_deletion_check.md. iter2 does NOT delete include/hevc-ctrls.h (it's a thin shim, not a duplication header per Phase 2 Bug 7).

Phase 3 → Phase 4 close

All four baselines green. Substrate intact post-upgrade. HEVC contract anchor captured for Phase 4 transcription. Bug 1 scratch confirms collateral safety. Phase 4 can proceed; estimated h265.c rewrite ~250-400 lines (per Phase 2 estimate; Phase 3 confirms 5-control batch + dynamic-array slice_params + unconditional SCALING_MATRIX as the structural facts to plan against).