Files
fresnel-fourier/phase8_iteration11_close.md
marfrit 7807326aff iter11 Phase 8 close: HEVC wire-byte search exhausted; same wall as iter9
α-13 + α-14 changed two HEVC wire-byte fields to match kdirect
(sps_max_num_reorder_pics, decode_params IRAP|IDR flags). Output
unchanged (06b2c5a0... still all-zero). 5-codec regression sweep:
zero regression.

Cumulative iter11 eliminations: 4 fields (sps_max_num_reorder_pics,
sps_max_latency_increase_plus1, IRAP/IDR flags, num_entry_point_offsets)
all confirmed kernel-ignored on RK3399 per rkvdec-hevc.c grep.

Wire-byte landscape after iter11: every observable libva-vs-kdirect
HEVC control-payload diff is in a field rkvdec ignores. Bug 5 root
cause is NOT in S_EXT_CTRLS payload.

Same wall as Bug 4 / iter9: wire-byte search exhausted. Real cause is
in OUTPUT bitstream bytes the kernel reads. iter12 candidate: extend
γ infrastructure to dump source_data pre-QBUF, compare with kdirect
byte-by-byte. Bug 4 and Bug 5 likely both close via this same
instrumentation given the parallel structure.

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

5.7 KiB
Raw Permalink Blame History

Iteration 11 — Phase 8 (close)

Closes 2026-05-14. iter11 = Bug 5 (HEVC libva all-zero) narrowing via control-payload deep diff. PARTIAL close.

Summary

Metric Value
Iteration target HEVC libva == kdirect via control-payload fix
Fork tip start e0be4e6 (iter9 close)
Fork tip end 8e2c04f (1 commit: α-13 SPS hygiene + α-14 IRAP/IDR flags)
LOC delta +53 / -5 across src/h265.c
Phase 1 criteria 5/6 PASS (C1 PARTIAL — HEVC hash unchanged)
Reviews 1 (Phase 5b CRIT-1 killed reorder_pics hypothesis; CRIT-2 redirected)
Cumulative HEVC eliminations 4 (sps_max_num_reorder_pics, sps_max_latency_increase_plus1, IRAP/IDR flags placement, num_entry_point_offsets all kernel-ignored)

Results

Codec iter11 hash Anchor Verdict
H.264 71ac099b… 71ac099b… unchanged (Bug 4 still open)
HEVC 06b2c5a0… 06b2c5a0… unchanged (Bug 5 unfixed)
VP9 4f1565e8… 4f1565e8… PASS unchanged
MPEG-2 19eefbf4… 19eefbf4… PASS unchanged
VP8 bcc57ed5… bcc57ed5… unchanged (Bug 6)

α-13 + α-14 changed two HEVC wire-byte fields to match kdirect (sps_max_num_reorder_pics from sps_max_dec_pic_buffering_minus1, decode_params.flags = IRAP_PIC|IDR_PIC from slice_params[0].nal_unit_type). Output unchanged. Reviewer's CRIT-1 confirmed empirically: rkvdec on RK3399 doesn't read these fields.

Cumulative HEVC wire-byte landscape after iter11

Field libva (pre-iter11) libva (post α-14) kdirect Rkvdec uses it?
SPS sps_max_num_reorder_pics 0 4 2 NO (Phase 5b CRIT-1)
SPS sps_max_latency_increase_plus1 0 0 4 NO
PPS UNIFORM_SPACING flag unset unset set NO (don't-care non-tiled)
DECODE_PARAMS flags IRAP+IDR 0 0x03 0x03 NO (kernel doesn't branch on this either)
SLICE_PARAMS bit_size 774096 774096 773760 NO
SLICE_PARAMS num_entry_point_offsets 0 0 22 NO (Phase 5b CRIT-2)
SLICE_PARAMS slice_qp_delta 0xff (-1) 0xff (-1) 0x00 reads diff_cu_qp_delta_depth from PPS only

Every observable wire-byte diff between libva and kdirect HEVC is in a field rkvdec ignores on RK3399. The Bug 5 root cause is NOT in the per-frame S_EXT_CTRLS payload.

Where Bug 5 must be

Three remaining unexamined surfaces:

  1. OUTPUT bitstream bytes. The actual HEVC slice data libva writes to the OUTPUT buffer's source_data may differ from what kdirect writes for the same input frame. Differences could be in start-code prefixing, NAL header bytes, EBSP encoding, or trailing padding. This is the iter12 candidate.
  2. OUTPUT QBUF metadata (m.planes[0].bytesused, request_fd, timestamp). strace abbreviates per-plane bytesused; need explicit verification.
  3. Some other ioctl sequence diff (REQBUFS counts, S_FMT shape, request_fd lifecycle) — unlikely since VP9 works through the SAME backend with the same ioctl sequence.

Lessons

Lesson 1: Wire-byte search has a strict ceiling

iter11 (HEVC) replicates iter8/iter9 (H.264): when the wire-byte diff is the field that user space and reference backend disagree on, but kernel ignores that field, no amount of wire-byte fix-up changes behavior. The Phase 5b methodology (grep rkvdec source for field name before writing fix) saves wasted cycles.

Lesson 2: VAAPI gap is real but separate from rkvdec consumption

Multiple HEVC fields are "not exposed by VAAPI" in VAPictureParameterBufferHEVC. Libva backends fill them with placeholders. For some (sps_max_num_reorder_pics, sps_max_latency_increase_plus1, IRAP/IDR flags, UNIFORM_SPACING), the placeholder is wire-incorrect but rkvdec ignores it anyway. The campaign's hardcoded zeros are wire-hygiene gaps but NOT decode-correctness bugs.

Lesson 3: Bug 4 and Bug 5 share an architectural pattern

Both bugs produce wrong/zero CAPTURE output through libva while kdirect succeeds. Both have control payloads that are or can be made byte-equivalent to kdirect via libva fixes. Both must have their actual cause in the OUTPUT bitstream bytes the kernel reads — that's the common unexamined surface. iter12 targets that.

iter11 → iter12 handoff

Substrate at close:

  • Fork tip 8e2c04f on noether + fresnel + gitea.
  • Backend SHA 521c1474c51154373e2d27f99d715a5af73a5fd9f72a83d947f8b552f2755d1f on fresnel.
  • Kernel linux-fresnel-fourier 7.0-1 unchanged.
  • Diagnostic γ + IMP-1 memset preserved; α-13/α-14 in shipping state (no regression).

iter12 candidate: extend the γ infrastructure to dump OUTPUT bitstream bytes (source_data + slices_size) immediately before MEDIA_REQUEST_IOC_QUEUE. Compare byte-by-byte with kdirect's OUTPUT buffer (capture via LD_PRELOAD or analogous kdirect instrumentation). Find the diff in actual bitstream bytes.

If OUTPUT bytes match: bug is in non-ioctl path (kernel-state, hardware-state). If OUTPUT bytes differ: target the divergence in libva's picture.c::codec_store_buffer or upstream VAAPI consumer.

Bug 4 and Bug 5 likely both close via this same instrumentation, given the parallel structure.

Memory rule candidate (defer to curation)

rkvdec on RK3399 ignores most HEVC SPS / SLICE_PARAMS / DECODE_PARAMS bookkeeping fields including: sps_max_num_reorder_pics, sps_max_latency_increase_plus1, num_entry_point_offsets, bit_size, slice_qp_delta, pic_struct. The driver only reads geometry (width, height, bit_depth, CTB / PCM sizing), reference-pic counts, ref_idx tables, and a subset of flags. Future hypothesis-generation should grep rkvdec source first before assuming a particular field is load-bearing.

Worth folding into feedback-rkvdec-patch-reachability or as a sibling memory.