d35a247948ca88a3d93c1e006a03d3bc2ed563ef
15 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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>
|
||
|
|
b3ba157cb4 |
iter2 Phase 2: situation analysis — six bugs in HEVC path
Phase 2 source-read of the HEVC path post-iter1-close (fork master
229d6d1). Six bugs identified, all in libva backend; kernel + driver
path proven for HEVC in Phase 0 cross-validator sweep.
Substrate timing caveat: Phase 2 conducted against fresnel kernel
6.19.9-99. Operator-scheduled rolling pacman -Syyuu to linux-7
imminent. Phase 2 source-read findings are kernel-agnostic (fork
code + UAPI + FFmpeg reference); they carry forward across the
kernel jump unchanged. Phase 3 baselines will run on linux-7.
Bug 1 — src/config.c:64-69 HEVCMain falls through to default,
returns VA_STATUS_ERROR_UNSUPPORTED_PROFILE. Verbatim match for
iter1 Bug 1 pattern; fix is 3-line break addition.
Bug 2 — src/picture.c:204-206 explicit
case VAProfileHEVCMain: return UNSUPPORTED_PROFILE
with stale comment "Fourier-local: HEVC stripped, no HW support
on RK3566." (RK3566 is ohm context; fresnel is RK3399 where
rkvdec DOES support HEVC.) Fix: replace explicit reject with
dispatch to h265_set_controls() (mirrors MPEG-2 dispatch at
picture.c:186-191).
Bug 3 — src/h265.c uses staging-era CIDs:
V4L2_CID_MPEG_VIDEO_HEVC_PPS / _SPS / _SLICE_PARAMS
These don't exist on fresnel's 6.19 kernel headers (verified via
test-compile: gcc reports undeclared identifiers, suggests
V4L2_CID_MPEG_VIDEO_DEC_PTS as nearest match). Mainline kernel
UAPI splits HEVC stateless into 7 controls:
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
(0xa40a90..0xa40a96 + extensions, V4L2_CID_CODEC_STATELESS_BASE
+ 400..407+).
Fix shape: rewrite h265.c against new split API. Substantially
larger than iter1's mpeg2.c rewrite (HEVC has 7 controls vs MPEG-2
3, + slice_params dynamic-array, + per-slice accumulation logic
needed).
Bug 4 — h265.c uses single-slice_params shape; new API is
dynamic-array. Fresnel rkvdec advertises:
hevc_slice_parameters 0xa40a92 elems=1 dims=[600] dynamic-array
Up to 600 slice_params entries per submission. Current
codec_store_buffer:115-135 OVERWRITES previous slice on
VASliceParameterBufferType arrival. Multi-slice frames need
APPEND-not-overwrite. FFmpeg reference v4l2_request_hevc.c:540-547
shows the pattern.
Fix shape: extend params.h265 to hold slice_params array (or
pointer+count); codec_store_buffer appends; h265_set_controls
flushes the array at end_picture as a single dynamic-array
S_EXT_CTRLS entry.
Bug 5 — h265.c missing controls: doesn't submit DECODE_PARAMS
(per-frame DPB info; new in modern API), SCALING_MATRIX (conditional
on iqmatrix_set + sps.scaling_list_enabled), DECODE_MODE+START_CODE
(device-wide menus, set once per context init).
Fix shape: add h265_fill_decode_params() (DPB ordering from VAAPI
ReferenceFrames[15] — preserve current extraction logic from
h265_fill_slice_params:269-315, route to new struct). Conditional
SCALING_MATRIX from VAIQMatrixBufferHEVC. Device-wide
DECODE_MODE+START_CODE either at first h265_set_controls call or
in extended context.c device-init block.
Bug 6 — src/meson.build comments out 'h265.c' (line 50) and
'h265.h' (line 73). Fix: uncomment both. Trivial.
Bug 7 (verify only) — include/hevc-ctrls.h is a 9-line shim that
just #include <linux/v4l2-controls.h>. Comment dates the
modernization to "linux-media 6.6+". Adds zero value; harmless.
Leave in place per iter1 Phase 5 Nit 6 lower-risk path.
Bug 8 (latent) — picture.c:287 params.h264.matrix_set=false
writes union byte 240. For HEVC: byte 240 lands inside
h265.picture (range [0..604), size 604) — different field than
MPEG-2's chroma_intra_quantiser_matrix. ffmpeg-vaapi's
per-frame VAPictureParameterBufferHEVC re-send overwrites the
corrupted byte before h265_set_controls reads. Latent for
clients that reuse a surface without re-sending picture params.
iter2+ Phase 4 cross-cutting backlog candidate; not iter2 scope.
Things verified NOT bugs:
- h265_fill_pps/sps/slice_params field extraction from VAAPI
structs is sound (just routes to wrong destination structs)
- NAL header parsing (data_bit_offset bit-search) is preserved
in new API — slice_params still has bit_size + data_bit_offset
- v4l2_set_controls batching API in place (used by H.264 + iter1
MPEG-2; iter2 uses same)
Substrate / kernel observation:
- Linux mainline 7.1.0-rc2 reference checkout has
drivers/staging/media/rkvdec/ with rkvdec.c, rkvdec-h264.c,
rkvdec-vp9.c — NO rkvdec_hevc.c. fresnel's HEVC support is
out-of-tree (Christian Hewitt patches per phase0_findings.md
external references). May land in stable 7.x.
- Phase 4 contract-before-code therefore can't cite kernel-side
HEVC handler source until/unless rkvdec_hevc.c lands in
mainline. UAPI doc + FFmpeg reference + Phase 3 cross-validator
bytes are the contract anchor.
Open questions tabled for Phase 3 (post-linux-7-upgrade):
1. iter1 + T4 references on linux-7 (regression check of closed
iter1 work)
2. SDDM watchpoint on linux-7
3. Cross-validator HEVC re-anchor (Baseline C equivalent for
HEVC) — verbatim payload bytes for SPS, PPS, DECODE_PARAMS,
SLICE_PARAMS array, SCALING_MATRIX
4. Pre-fix scratch test (Bug 1 + Bug 2 only, h265.c kept
commented out) — confirm collateral safe
5. Slice-count for bbb_720p10s_hevc.mp4 fixture
6. Whether linux-7 brings rkvdec_hevc.c into mainline
Predicted iter2 close shape: trivial Bugs 1+2+6 fixes + sizable
h265.c rewrite (~250-400 lines, ~3x iter1's mpeg2.c) + new
codec_store_buffer slice accumulation logic. If Phase 7 fails:
likely struct-size mismatch (run pahole), DPB ordering, or
slice_params array size encoding.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
6e8c970c1d |
iter2 Phase 0 + Phase 1 lock: HEVC Main on rkvdec
Iteration 2 of the campaign 8(+1)-phase loop opens following iter1
close (
|
||
|
|
dc6937868a |
iter1 Phase 8 close: 2/5 codecs passing, 3 lessons distilled to memory
Iteration 1 closes with all five Phase 1 boolean-correctness criteria
green. Second codec passes — campaign scoreboard 1/5 → 2/5 (H.264
in T4, MPEG-2 in iter1). Loop terminates per
feedback_dev_process.md Phase 8.
What landed:
Code (libva-v4l2-request-fourier master 65969da..229d6d1):
e7dad7a iter1 Phase 6 commit A: config.c break for MPEG-2 cases
5fe873c iter1 Phase 6 commit B: rewrite mpeg2.c against new V4L2 stateless API
3aab187 iter1 Phase 6 commit C: delete staging-era include/mpeg2-ctrls.h
229d6d1 iter1 Phase 6 commit D: drop missed mpeg2-ctrls.h include from context.c (fix-forward)
All four authored as Claude (noether) per feedback_gitea_as_claude_noether.md.
Campaign docs (fresnel-fourier):
|
||
|
|
ec9133a5e4 |
iter1 Phase 7: verification — all 5 criteria GREEN, second codec PASS
Phase 7 verification of iter1 MPEG-2 fix executed against fork tip
229d6d1 (libva-v4l2-request-fourier master = post-Commit-D).
Verbatim raw output captured to phase0_evidence/2026-05-08/
iter1_phase7/. All five Phase 1 criteria green; bonus byte-compare
confirms structural match against Baseline C with one numerical
divergence (vbv_buffer_size, kernel-ignored, non-blocking).
Phase 1 → Phase 7 scoreboard:
Criterion 1 (vainfo MPEG-2 Simple+Main enum): PASS
Criterion 2 (vaCreateConfig SUCCESS for MPEG2Main): PASS
Pre-iter1: VA_STATUS_ERROR_UNSUPPORTED_PROFILE (12)
Post-iter1: VA_STATUS_SUCCESS (verified verbatim libva trace)
Criterion 3 (ffmpeg-hwaccel-vaapi engages backend): PASS
5 frames decoded, exit 0, no Failed-to-create lines,
no S_EXT_CTRLS EINVAL on the MPEG-2 path
Criterion 4 (DMA-BUF GL HW=SW byte-identical at +02s): PASS
HW frame 1: 6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092
SW frame 1: 6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092
HW frame 2: ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de
SW frame 2: ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de
Frames 1 vs 2 differ in size (real motion).
Criterion 5 (T4 H.264 reference hashes match): PASS
HW + SW frames at +30s into bbb_1080p30_h264.mp4 match
f623d5f7... and 7d7bc6f2... exactly. No H.264 regression.
Bonus byte-compare against Phase 3 Baseline C verbatim:
count=3, ctrl_class=V4L2_CTRL_CLASS_CODEC_STATELESS=0xf010000:
SEQUENCE id=0xa409dc size=12 (matches)
PICTURE id=0xa409dd size=32 (matches structurally)
QUANTISATION id=0xa409de size=256 (intra matrix bytes
IDENTICAL to Baseline C
verbatim 64 bytes;
non_intra all 16's)
All return = 0 (kernel accepts every batched call).
One numerical divergence: sequence.vbv_buffer_size
post-fix: 0x100000 = 1 048 576 (= SOURCE_SIZE_MAX)
Baseline C: 0x151800 = 1 376 256 (= negotiated sizeimage)
Kernel ignores per v4l2-controls.h:2003 (informational).
Decode is bit-exact correct regardless. Phase 5 reviewer S2
was numerically prescient; my Phase 5 response (rejected with
"slot->size = sizeimage") was wrong empirically; operational
impact nil. Tracked as low-priority post-iter1 polish.
Phase 7 → Phase 8: clean transition, no loopback to Phase 4.
Notable observations for Phase 8 memory update:
1. V4L2 /dev/videoN numbering shuffles across reboots on RK3399.
Phase 0/3 had rkvdec=video3+media1, hantro=video5+media2; this
boot has rkvdec=video1+media0, hantro=video3+media1. Phase 1
binding cells using fixed paths fragile across reboots. Phase
4 cross-cutting fix candidate: backend probes /dev/media* for
driver=hantro-vpu/rkvdec rather than env-var stability.
2. iter1 patch-0011 cache-stale bug class also affects MPEG-2
(verified empirically; same as H.264 in T4). vaDeriveImage
readback returns all-zero NV12 via ffmpeg-vaapi+hwdownload.
Workaround: DMA-BUF GL import (mpv --vo=image) is cache-
coherency-safe. Phase 4 cross-cutting fix candidate: add
VIDIOC_EXPBUF + DMA_BUF_IOCTL_SYNC support to libva backend
image-export path.
3. src/context.c:142-155 H.264 device-init logs noisy EINVAL on
hantro every CreateContext (return value cast to (void) but
v4l2.c:484 still calls request_log). Cosmetic suppression
candidate; low priority.
4. Phase 6 commit D (fix-forward for missed mpeg2-ctrls.h
include in context.c) — Phase 2 grep audit was incomplete.
Phase 8 lesson: when deleting a header, completeness check
is git rm + clean rebuild, not grep alone.
Campaign scoreboard: 1/5 → 2/5 codecs passing
(H.264 in T4, MPEG-2 in iter1). Iter1 advances to Phase 8.
Refs:
../libva-v4l2-request-fourier@229d6d1 (the fork tip verified)
phase4_iter1_plan.md (criteria as locked, including Phase 5
amendments to criterion 3 + criterion 4)
phase5_iter1_review.md (S2 partial-correct; S3, Q4, Q5
confirmed empirically)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
0e2e1c2293 |
iter1 Phase 5: sonnet-architect review — 6 findings, 4 amendments
Phase 5 review run via Plan subagent with model: sonnet per
feedback_dev_process.md Phase 5 discipline. Review verbatim
preserved in phase5_iter1_review.md alongside per-finding response.
Findings: 1 Critical (latent), 2 Should-fix (1 valid, 1 misreading),
2 Question/clarification, 1 Nit. Reviewer's bottom-line: medium-high
confidence in the plan as written.
Resolutions:
C1 (union-aliasing reasoning was wrong; iter1 unaffected; latent bug):
Verified offsets on fresnel via gcc + libva headers:
h264.matrix_set at union byte 240
mpeg2.iqmatrix_set at union byte 376
mpeg2.iqmatrix range [88..376) — sizeof=288
Setting h264.matrix_set=false writes byte 240, which lands inside
mpeg2.iqmatrix.chroma_intra_quantiser_matrix at offset 20.
Phase 2 said the byte gets overwritten by RenderPicture before
mpeg2_set_controls reads it. That was true only because ffmpeg-
vaapi sends VAIQMatrixBufferType every frame; codec_store_buffer
then copies the full 260-byte payload over the corrupted byte.
ACCEPTED: update Phase 2 + Phase 4 wording to cite the correct
safety chain. Latent bug for clients that reuse a surface without
re-sending IQMatrix logged for iter2+ backlog.
S2 (vbv_buffer_size source — reviewer misread):
Reviewer assumed slot->size = SOURCE_SIZE_MAX (1MB). Verified
source: src/request_pool.c:71 sets pool->slots[i].size = length,
where length is the V4L2-reported buffer length from
VIDIOC_QUERYBUF (= negotiated sizeimage from S_FMT). Phase 3
Baseline C strace shows S_FMT(OUTPUT_MPLANE) returns
sizeimage=1382400=0x151800 — exactly matches Baseline C's
vbv_buffer_size payload. Plan is correct as-is.
REJECTED (reviewer's claim wrong); 1-line note added to Phase 6
Commit B message clarifying the dynamic source.
S3 (default-matrix transcription byte-verify protocol):
ACCEPTED. Phase 6 protocol amendment: when transcribing the
64-entry default_intra[] in src/mpeg2.c, derive values from
Baseline C QUANTISATION verbatim payload, then run a diff-based
assertion before commit lands. Same for non_intra (all 16's),
chroma_intra (= intra), chroma_non_intra (all 16's) — verified
against Baseline C bytes 0..63 / 64..127 / 128..191 / 192..255.
Q4 (criterion 4 — ffmpeg+hwdownload primary, not fallback):
ACCEPTED. Phase 7 harness criterion 4 changes from
mpv --hwdec=vaapi --vo=image first, ffmpeg fallback
to
ffmpeg -hwaccel vaapi -vf hwdownload,format=nv12 primary,
mpv-vaapi-vo=image backup
Critical addition: Phase 7 must check both hashes match AND
content non-zero/non-sentinel. T4 found ffmpeg-vaapi
-hwaccel_output_format nv12 returns mostly zeros via cached-mmap
on RK3399 (iter1 patch-0011 cache-stale bug class). For MPEG-2,
hwdownload may use a different readback path; if it also exposes
the cache-stale bug, swap to mpv-vaapi-vo=image. Empirical
determination during Phase 7.
Q5 (timestamp behavior is a correction, not "no semantic change"):
ACCEPTED. Phase 4 Clause 3 amendment: explicitly note that
forward_ref_ts/backward_ref_ts = 0 when reference surface is
VA_INVALID_ID is a CORRECTION vs current code's self-referencing
behavior. Old code at src/mpeg2.c:106-107, 113-115 set
forward_reference_surface = surface_object (self-ref) when ref
was VA_INVALID_ID. New code sets ts to 0. Baseline C frame 1
confirms 0-as-sentinel; FFmpeg v4l2_request_mpeg2.c:98-108
matches. Iter1 fixes a latent bug.
Nit 6 (hevc-ctrls.h left alongside removed mpeg2-ctrls.h):
ACCEPTED (lower-risk path). Phase 6 Commit B removes mpeg2-ctrls.h
include only; Commit C deletes include/mpeg2-ctrls.h only.
Hevc-ctrls.h header + include left untouched, deferred to HEVC
iteration. Optional cleanup if Phase 6 chooses to bundle, but
default is the smaller diff.
Phase 4 → Phase 6 amendments consolidated:
1. Clause 3 timestamp behavior explicit (Q5)
2. Clause 4 default-matrix Baseline-C-derived transcription (S3)
3. Phase 7 criterion 4 ffmpeg+hwdownload primary + non-zero check (Q4)
4. Hevc-ctrls.h cleanup deferred (Nit 6)
5. Phase 2 + Phase 4 wording fix on union safety chain (C1 partial)
6. Latent surface-reuse bug logged for iter2+ backlog (C1 follow-up)
Plan re-locks with these amendments. Phase 6 proceeds.
Per global ~/.claude/CLAUDE.md rule: Phase 5 reviews are never
skippable. This review was the right path forward; surfaced 2 plan
amendments + 1 latent bug worth documenting + 1 reviewer-misreading
worth pinning so the trail is clear. Material outside-look value.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
3e996d09e2 |
iter1 Phase 4: plan — contract clauses, diff scope, Phase 7 harness
Phase 4 plan for the iter1 MPEG-2 fix, structured per the feedback_dev_process.md Phase 6 contract-before-code worked example (0012-h264-omit-scaling-matrix-frame-based.patch shape): contract clauses with citations first, then code changes mapping 1:1 to clauses. Phase 1 criterion #3 re-locked per Phase 3 → Phase 1 loopback: Original: "mpv --hwdec=vaapi-copy ... engages backend" Adjusted: "ffmpeg -hwaccel vaapi ... engages backend" Phase 3 Baseline A established mpv silently filters MPEG-2 out before libva is loaded; the original wording was unfalsifiable. ffmpeg-direct exercises the path. mpv-driven testing → separate follow-up task. Other 4 criteria unchanged (vainfo regression, vaCreateConfig SUCCESS, DMA-BUF GL pixel verify HW=SW at +02s, T4 H.264 regression). Six contract clauses cited from authoritative sources: Clause 1 — Three split controls in one batched VIDIOC_S_EXT_CTRLS Authority: linux/v4l2-controls.h:1988-2105 Reference impl: FFmpeg libavcodec/v4l2_request_mpeg2.c:130-155 Empirical anchor: Phase 3 Baseline C verbatim payload Clause 2 — v4l2_ctrl_mpeg2_sequence layout (12 bytes) Authority: linux/v4l2-controls.h:2009-2017 Field-by-field VAAPI source mapping table Note: progressive_frame is used as proxy for progressive_sequence (VAAPI doesn't expose the latter; same bit for BBB). Clause 3 — v4l2_ctrl_mpeg2_picture layout (32 bytes) Authority: linux/v4l2-controls.h:2056-2065 reserved[5] MUST be zeroed (kernel doc 2052) 8 picture flags decoded; field-by-field VAAPI mapping Clause 4 — v4l2_ctrl_mpeg2_quantisation layout (256 bytes) Authority: linux/v4l2-controls.h:2089-2096 Matrices in zigzag scanning order; no permutation in libva backend (kernel hantro_mpeg2_dec_copy_qtable handles zigzag-to-raster) Decision: when iqmatrix_set is false, populate from MPEG-2 spec defaults (ISO/IEC 13818-2 Table 7-3) to avoid kernel rejecting a batch missing the QUANTISATION control. Clause 5 — Per-frame submission via v4l2_set_controls Authority: existing src/h264.c:986 pattern surface_object->request_fd binds controls to per-surface request Clause 6 — config.c MPEG-2 case must break; Authority: C semantics; H.264 case shape at config.c:62-63 Empirical anchor: Phase 3 Baseline B confirmed scratch-fix shape. Diff scope: src/config.c — 3 lines added (break for MPEG-2 cases) + drop stale #include <mpeg2-ctrls.h> src/mpeg2.c — full rewrite of mpeg2_set_controls against new split API; ~120 lines replaced; switches from 2× v4l2_set_control(single) to 1× batched v4l2_set_controls(3-control array) include/mpeg2-ctrls.h — DELETE (staging-era, masks kernel UAPI) src/picture.c, src/context.c, meson.build — no changes (verified Phase 2 + Phase 3) Phase 6 implementation order (3 logical commits): Commit A: config.c break — substrate fix in isolation Commit B: mpeg2.c rewrite + drop mpeg2-ctrls.h includes Commit C: delete include/mpeg2-ctrls.h Phase 7 verification harness (full Bash incantations included in plan body): Criterion 1: vainfo MPEG-2 enumeration regression check Criterion 2: vaCreateConfig SUCCESS via libva trace Criterion 3: ffmpeg -hwaccel vaapi exit 0, no Failed-to-create Criterion 4: mpv --hwdec=vaapi --vo=image at +02s seek; HW=SW byte-identical hashes for 2 distinct frames (fallback to ffmpeg hwdownload if mpv-vaapi also filters MPEG-2; criterion holds, harness adapts) Criterion 5: T4 H.264 hashes still f623d5f7... and 7d7bc6f2... Bonus: byte-compare post-fix S_EXT_CTRLS payload vs Baseline C Pre-identified Phase 7 → Phase 4 loopback triggers: 1. S_EXT_CTRLS EINVAL post-fix → check pic.reserved[5] memset, struct sizes, flag value collisions 2. Pixel hash mismatch → check f_code packing, field/frame interpretation, ref timestamps, IQ matrix order 3. mpv-vaapi filters MPEG-2 out (same as -copy) → fall-forward to ffmpeg hwdownload pixel verify (criterion holds, harness adapts; do not redefine criterion) 4. H.264 regression → re-locate the offending change in Bug 1 5. Header deletion breaks unaudited consumer → git grep audit Out of scope (LOCKED): HEVC/VP9/VP8 (later iterations); vaDerive Image cache-stale fix; chromium-fourier 149 install; perf metrics; long-duration stress; other MPEG-2 containers; mpv-hwdec follow-up; context.c H.264 device-init EINVAL (auxiliary, intentional); profile/chroma/progressive_sequence refinement; upstream engagement. Phase 5 entry: artifacts handover (no summary, raw bundle) per feedback_dev_process.md — phase0_findings_iter1.md, phase2_iter1_situation.md, phase3_iter1_baseline.md, phase4_iter1_plan.md, plus phase0_evidence/2026-05-07/iter1_phase3/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
b9625af278 |
iter1 Phase 3: baseline measurements — Phase 2 confirmed empirically
Four Phase 3 baselines captured on fresnel post-reboot 2026-05-08
00:39 CEST. SDDM watchpoint condition stayed green (greeter passed
cleanly on the new boot). All four baselines confirm Phase 2's
situation analysis empirically; one Phase 1 criterion needs minor
adjustment (Phase 3 → Phase 1 loopback per feedback_dev_process.md).
Baseline A — pre-patch failure mode (master tip 65969da):
ffmpeg -hwaccel vaapi -i bbb_720p10s_mpeg2.ts ... under strace +
LIBVA_TRACE captures the chain:
vaInitialize ret = SUCCESS
vaQueryConfigProfiles ret = SUCCESS
vaCreateConfig(profile=VAProfileMPEG2Main, entrypoint=VLD)
ret = VA_STATUS_ERROR_UNSUPPORTED_PROFILE
No V4L2 ioctls beyond ENUM_FMT probes from RequestQueryConfigProfiles.
Confirms Phase 2 Bug 1 (config.c:55-69 fall-through to default).
Baseline B — post Bug 1 scratch patch (the missing break added):
vaCreateConfig now returns SUCCESS. V4L2 setup proceeds:
CREATE_BUFS, QUERYBUF (40), REQBUFS, STREAMON, S_FMT, etc.
Then VIDIOC_S_EXT_CTRLS fails:
ioctl(/dev/video5, VIDIOC_S_EXT_CTRLS,
{ctrl_class=0xf010000,
count=1,
controls=[
{id=V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
size=56, ...}
]})
= -1 EINVAL
CID 0x9909fa (V4L2_CID_MPEG_BASE+250) doesn't exist on this kernel —
mainline removed it in favor of the split V4L2_CID_STATELESS_MPEG2_*
CIDs. Size 56 = sizeof(combined v4l2_ctrl_mpeg2_slice_params) from
the fork's local include/mpeg2-ctrls.h. Confirms Phase 2 Bug 2.
Auxiliary EINVAL: src/context.c:142-155 unconditionally sets H.264
device-wide controls (H264_DECODE_MODE, H264_START_CODE) on every
CreateContext, regardless of profile. EINVALs on hantro-vpu-dec
(no H.264 controls there). Intentional best-effort behavior —
return value is cast to (void) and discarded. Auxiliary, not iter1
scope.
Baseline C — cross-validator verbatim contract anchor:
ffmpeg -hwaccel v4l2request strace shows ONE batched call per frame:
ioctl(/dev/video5, VIDIOC_S_EXT_CTRLS,
{ctrl_class=0xf010000, // V4L2_CTRL_CLASS_CODEC_STATELESS
count=3,
controls=[
{id=0xa409dc, size=12, ...}, // SEQUENCE
{id=0xa409dd, size=32, ...}, // PICTURE
{id=0xa409de, size=256, ...} // QUANTISATION
]}) = 0
Field-by-field decode of frame 1 (I-picture):
SEQUENCE: 1280×720, vbv=0x151800, profile_level=0,
chroma_format=1, flags=PROGRESSIVE
PICTURE: back/fwd_ref_ts=0/0, flags=0x82
(FRAME_PRED_DCT|PROGRESSIVE), f_code=0xF×4 (I-frame
default), P_C_T=1 (I), structure=3 (FRAME),
intra_dc_precision=0
QUANTISATION: starts [8, 16, 16, 19, 16, 19, 22, 22, ...] —
canonical MPEG-2 default intra matrix in zigzag
scanning order.
Frame 2 (P-picture) shows real f_code values {{1,1},{15,15}}
and forward_ref_ts pointing to frame 1's timestamp. Confirms
Phase 2's claim that matrices arrive in zigzag order;
no permutation needed in the libva backend (kernel's
hantro_mpeg2_dec_copy_qtable handles zigzag-to-raster).
This is the iter1 contract anchor: every Phase 4 implementation
diff must produce a structurally indistinguishable
VIDIOC_S_EXT_CTRLS call.
Baseline D — H.264 regression check (Phase 1 criterion #5):
T4 reference hashes match exactly with scratch Bug 1 fix installed:
HW frame 1: f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9
SW frame 1: f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9
HW frame 2: 7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8
SW frame 2: 7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8
Bug 1 fix in isolation does not regress H.264.
Phase 1 criterion #3 needs adjustment (Phase 3 → Phase 1 loopback):
Original wording: "mpv --hwdec=vaapi-copy ... engages the backend"
Reality: mpv-vaapi-copy never loads libva for MPEG-2. mpv's hwdec
policy filters MPEG-2 out before libva is touched. Zero V4L2
ioctls, zero libva trace, silent SW fallback. Independent of
Bug 1 fix state.
Adjusted criterion #3 (proposed; locks alongside Phase 4 plan):
"ffmpeg -hwaccel vaapi -i bbb_720p10s_mpeg2.ts -frames:v 2
-f null - shows vaCreateConfig SUCCESS, no Failed to create
decode configuration lines, no EINVAL from VIDIOC_S_EXT_CTRLS,
exits 0 cleanly."
mpv-driven testing moves to a follow-up task (mpv hwdec-codecs
filter override), separate from iter1.
Other 4 Phase 1 criteria (vainfo regression, vaCreateConfig SUCCESS,
DMA-BUF GL pixel verify HW=SW, T4 H.264 regression) hold as locked.
Scratch state cleanup: scratch patch reverted, master backend
reinstalled, MPEG-2 fails again with vaCreateConfig=12 — back to
Baseline A state, no leak.
Phase 4 plan inputs:
- Diff scope: src/config.c (1 break), src/mpeg2.c (rewrite to
new API), include/mpeg2-ctrls.h (delete or empty). picture.c
+ context.c unchanged.
- Contract anchor: cite verbatim from
linux/v4l2-controls.h:1985-2105, FFmpeg
libavcodec/v4l2_request_mpeg2.c:130-155, kernel
drivers/media/platform/verisilicon/hantro_mpeg2.c, AND this
document's Baseline C verbatim payload.
- Phase 7 verification: re-run all 5 Phase 1 criteria
(with #3 adjusted), byte-by-byte compare post-fix
VIDIOC_S_EXT_CTRLS payload against Baseline C.
Evidence files:
Tracked (text):
phase3_iter1_baseline.md (writeup with verbatim raw output)
phase0_evidence/2026-05-07/iter1_phase3/baseline_A_ffmpeg/ffmpeg.stdout
phase0_evidence/2026-05-07/iter1_phase3/baseline_B_postbug1/ffmpeg.stdout
phase0_evidence/2026-05-07/iter1_phase3/baseline_C_xvalidator/ffmpeg.stdout
Gitignored (regenerable from re-run incantations in the writeup):
*.strace.* *.txt (ftrace) libva.trace.* (added the latter pattern)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
cc55a6e60a |
iter1 Phase 2: situation analysis — three bugs in MPEG-2 path
Phase 2 source-read of the libva-v4l2-request-fourier MPEG-2 path
on master tip 65969da identifies three independent bugs, all in
the libva backend (kernel + driver path proven solid by Phase 0
cross-validator sweep).
Bug 1 — fall-through to default in RequestCreateConfig
(src/config.c:55-69):
case VAProfileH264*:
// FIXME
break;
case VAProfileMPEG2Simple:
case VAProfileMPEG2Main:
case VAProfileHEVCMain:
default:
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
H.264 cases have a break, MPEG-2 + HEVC fall through to default.
This explains the vaCreateConfig: 12 (UNSUPPORTED_PROFILE) error
observed in Phase 0 cross-validator sweep for both codecs.
Likely history: H.264 was libva-multiplanar focus iter1-iter5;
the FIXME comment suggests profile-specific validation logic was
expected but never landed. MPEG-2 stayed in fall-through bucket.
Fix shape: add break for MPEG-2 cases. HEVC stays in fall-through
(h265.c excluded from build per Phase 0 finding F-C; honest
UNSUPPORTED_PROFILE is correct until h265.c is reinstated in a
later iteration).
Bug 2 — staging-era UAPI in mpeg2.c; mainline kernel removed it:
src/mpeg2.c uses:
V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS (V4L2_CID_MPEG_BASE+250 = 0x9909fa)
V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION (V4L2_CID_MPEG_BASE+251 = 0x9909fb)
Mainline kernel UAPI (include/uapi/linux/v4l2-controls.h:1985-2105):
V4L2_CID_STATELESS_MPEG2_SEQUENCE (CODEC_STATELESS_BASE+220 = 0xa409dc)
V4L2_CID_STATELESS_MPEG2_PICTURE (CODEC_STATELESS_BASE+221 = 0xa409dd)
V4L2_CID_STATELESS_MPEG2_QUANTISATION (CODEC_STATELESS_BASE+222 = 0xa409de)
Fresnel V4L2 inventory confirms kernel exposes the new IDs only.
The fork's local include/mpeg2-ctrls.h is the staging-era header
that masks the kernel's modern definitions.
Six structural changes from old to new API:
1. Slice header parsing moved to kernel — bit_size, data_bit_offset,
quantiser_scale_code GONE from new structs.
2. Reference timestamps moved from slice to picture
(forward_ref_ts, backward_ref_ts now in v4l2_ctrl_mpeg2_picture).
3. Boolean fields collapsed into v4l2_ctrl_mpeg2_picture.flags
bitmask (TOP_FIELD_FIRST, FRAME_PRED_DCT, CONCEALMENT_MV,
Q_SCALE_TYPE, INTRA_VLC, ALT_SCAN, REPEAT_FIRST, PROGRESSIVE).
4. progressive_sequence collapsed into
v4l2_ctrl_mpeg2_sequence.flags & V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE.
5. PICTURE_CODING_TYPE renamed to PIC_CODING_TYPE
(V4L2_MPEG2_PICTURE_CODING_TYPE_X → V4L2_MPEG2_PIC_CODING_TYPE_X).
6. Quantisation load_* flags removed; matrices always present;
British spelling — quantiSation not quantiZation.
Quantisation matrix order: kernel doc says zigzag scanning order;
VAAPI VAIQMatrixBufferMPEG2 also stores in zigzag scanning order;
direct memcpy works. Kernel hantro_mpeg2.c does the
zigzag-to-raster permutation kernel-side
(hantro_mpeg2_dec_copy_qtable lines 12-26). No userspace
permutation needed in the libva backend (unlike FFmpeg, which
unwinds its internal idsp.idct_permutation order).
Per-frame submission: FFmpeg reference (libavcodec/
v4l2_request_mpeg2.c:130-155) batches 3 controls in single
VIDIOC_S_EXT_CTRLS. Backend's v4l2_set_controls (src/v4l2.c:475)
already supports batching — used by iter6/7/8 H.264
(src/h264.c:986). MPEG-2 rewrite follows H.264's batched pattern.
Bug 3 — include/mpeg2-ctrls.h is the staging-era local header:
The fork's local include/mpeg2-ctrls.h is the staging-era header
that defines the old (removed) API. config.c:37 + mpeg2.c:38
include it via meson's include_directories('../include'). Should
be deleted (or emptied); rely on kernel <linux/v4l2-controls.h>
pulled transitively via <linux/videodev2.h>.
Things verified NOT to be bugs:
- src/picture.c MPEG-2 dispatch is fully wired:
- codec_store_buffer handles VAPictureParameterBuffer + VAIQMatrix
- codec_set_controls dispatches MPEG-2 to mpeg2_set_controls
- HEVC explicitly UNSUPPORTED_PROFILE (correct for build state)
- src/picture.c:287 unconditional h264.matrix_set=false reset is
benign for MPEG-2 (union aliasing puts it in mpeg2.picture or
.slice region; RenderPicture overwrites that byte before
mpeg2_set_controls reads anything).
- src/mpeg2.c field extraction from VAAPI structs is sound; only
the destination control IDs and struct shape need rewiring.
- src/v4l2.c batching API (v4l2_set_controls) is in place.
Open questions tabled for Phase 3 baseline:
1. Live ftrace of failing libva MPEG-2 attempt post Bug-1-fix
(verify expected EINVAL on VIDIOC_S_EXT_CTRLS for old CID).
2. VAAPI VAIQMatrixBufferMPEG2 matrix order from real mpv decode
(verify zigzag, no pre-permutation).
3. Cross-reference verbatim VIDIOC_S_EXT_CTRLS payload from
ffmpeg-v4l2request cross-validator anchor strace dump.
4. SDDM watchpoint resolution — fresnel SSH No route to host at
Phase 2 start (network event, SDDM regression, or operator
power-state). Resolve before Phase 3.
Predicted iter1 outcome: small mechanical diff (config.c break
+ mpeg2.c rewrite + drop local mpeg2-ctrls.h). Phase 7 verification
should land all 5 Phase 1 boolean checks green on first or second
try. Likely Phase 7 → Phase 4 loopback triggers if any: forgotten
struct padding zero, garbage timestamps on first I-frame, or
device-state precondition we missed in hantro_mpeg2.c.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f720c7784b |
iter1 Phase 0 + Phase 1 lock: MPEG-2 boolean correctness on hantro
Iteration 1 of the campaign 8(+1)-phase loop opens following the
campaign Phase 0 close (
|
||
|
|
b74551bc56 |
phase 0 close: deliverables 5 + 6 — fixtures + cross-validator anchor
Closes Phase 0 for fresnel-fourier. Per-codec test fixtures and cross-validator contract traces complete the campaign-locked boolean-correctness baseline. Deliverable #5 — per-codec test fixtures (test_fixtures.md): Generated 4 new fixtures on fresnel from the bbb_1080p30_h264.mp4 master via stock ffmpeg (libx265 ultrafast, libvpx-vp9 speed 5, mpeg2video, libvpx vp8). All 720p 10s 8-bit yuv420p — matching the silicon-supported profile/pixfmt for each codec on RK3399: bbb_720p10s_hevc.mp4 620 KB (HEVC Main, rkvdec target) bbb_720p10s_vp9.webm 3.4 MB (VP9 Profile 0, rkvdec target) bbb_720p10s_mpeg2.ts 5.3 MB (MPEG-2 Main, hantro-vpu-dec target) bbb_720p10s_vp8.webm 2.4 MB (VP8, hantro-vpu-dec target) Encode wall times on fresnel: HEVC 13s, VP9 93s, MPEG-2 6s, VP8 26s. H.264 master is 725 MB carryover from libva-multiplanar / fourier_attribution. Deliverable #6 — cross-validator anchor (cross_validator_traces.md): phase0_findings.md named chromium-fourier 149 as the cross-validator; that package isn't installed on fresnel and marfrit-packages isn't configured (no auto-install path tonight). Substituted ffmpeg -hwaccel v4l2request as a better-fit cross-validator: it's an independent V4L2 client (uses no libva at all, lives in libavcodec/v4l2_request*.c), already on the box (stock ffmpeg n8.1-13-gb57fbbe50c, the Kwiboo v4l2-request-n8.1 branch), and implements all 5 codecs the campaign locked. Headline finding: ALL 5 CODECS WORK end-to-end via the kernel direct path on RK3399. ffmpeg -hwaccel v4l2request -i bbb_<codec>.<ext> -frames:v 2 -f null - H.264: exit 0 HEVC: exit 0 VP9: exit 0 MPEG-2: exit 0 VP8: exit 0 The Linux kernel + rkvdec + hantro-vpu drivers are solid for the entire campaign codec scope. Phase 6 work scope is purely libva- backend code — no kernel patches, no upstream Linux engagement. Per-codec libva (iter8) vs ffmpeg-v4l2request status sweep: H.264 libva: PASS (T4 PASS + bit-exact pixel verify) | ffmpeg-v4l2req: PASS HEVC libva: vaCreateConfig=12 (UNSUPPORTED_PROFILE) | ffmpeg-v4l2req: PASS → src/h265.c is excluded in src/meson.build but src/config.c:151 enumerates HEVCMain via V4L2_PIX_FMT_HEVC_SLICE probe; vaCreateConfig fails downstream of the case match. VP9 libva: profile not enumerated | ffmpeg-v4l2req: PASS → no vp9.c in fork MPEG-2 libva: vaCreateConfig=12 (UNSUPPORTED_PROFILE) | ffmpeg-v4l2req: PASS → mpeg2.c IS compiled, config.c:64-65 has the case statements, yet vaCreateConfig rejects. Phase 2 source-read needed. VP8 libva: profile not enumerated | ffmpeg-v4l2req: PASS → no vp8.c in fork Suggested Phase 6 iteration order (subject to Phase 1 lock): iter1: MPEG-2 — likely cheapest (config.c-level path; mpeg2.c already compiled) iter2: HEVC — re-enable h265.c in build, audit against rkvdec iter3: VP8 — implement vp8.c on hantro iter4: VP9 — implement vp9.c on rkvdec (largest control surface) Per-codec ioctl frequency anchor (2-frame ffmpeg -hwaccel v4l2request): ioctl H.264 HEVC VP9 MPEG-2 VP8 VIDIOC_DQBUF 45 49 40 26 49 VIDIOC_QBUF 22 24 20 10 20 VIDIOC_CREATE_BUFS 17 17 17 12 17 VIDIOC_QUERYBUF 15 15 15 10 15 VIDIOC_S_EXT_CTRLS 13 14 11 5 10 VIDIOC_EXPBUF 11 11 11 6 11 VIDIOC_QUERY_EXT_CTRL 0 5 0 0 0 MEDIA_IOC_REQUEST_ALLOC 4 4 4 4 4 DMA_BUF_IOCTL_SYNC 0 0 0 4 0 MEDIA_REQUEST_IOC_REINIT 0 0 0 0 3 Architectural divergence ffmpeg-v4l2request vs libva-v4l2-request-fourier: - ffmpeg uses VIDIOC_EXPBUF + DMA-BUF for downstream readback. Our libva backend uses cached mmap via vaDeriveImage — the iter1 patch-0011 cache-stale bug class. Phase 4 work item consistent with T4's finding: adding VIDIOC_EXPBUF + DMA-BUF- backed image export to the libva backend would fix the cache-coherency issue identified in T4's H.264 readback. - ffmpeg uses 4 request_fds pooled. Our backend uses 16 (iter6 per-OUTPUT-slot binding). Both valid; different pool depth. - HEVC alone needs VIDIOC_QUERY_EXT_CTRL for hevc_slice_params dynamic-array introspection — unique among the 5 codecs. Substrate change deferred (not a Phase 0 blocker): chromium-fourier 149 install on fresnel is Phase 1+ work. When done, a follow-up trace pass per codec will cross-check ffmpeg-v4l2request and chromium contracts. For Phase 0 baseline, ffmpeg-v4l2request is the anchor. Phase 0 fully closed. Six deliverables landed. Phase 1 lock can proceed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d8a9903ef4 |
phase 0 deliverable 4: H.264 baseline trace — PASS boolean correctness
H.264 hardware decode on RK3399 / rkvdec / libva-v4l2-request-fourier
@ master tip 65969da (iter8 Phase 4) verified bit-exact correct against
software reference, when read via the cache-safe DMA-BUF GL import path.
Test method:
- mpv --hwdec=vaapi --vo=image (DMA-BUF + EGL_EXT_image_dma_buf_import
+ glReadPixels + JPEG encode — cache-coherency-safe per the iter1
patch-0011 lesson).
- Decoded 2 frames at +30s seek (mid-content bunny motion, not BBB
intro fade-in) so size + content variation is genuine.
- Compared HW JPEGs vs SW reference JPEGs (same mpv invocation with
--hwdec=no).
Result:
HW frame 1 sha256 = f623d5f7... (651,726 bytes) byte-identical
SW frame 1 sha256 = f623d5f7... (651,726 bytes) to SW reference
HW frame 2 sha256 = 7d7bc6f2... (630,433 bytes) byte-identical
SW frame 2 sha256 = 7d7bc6f2... (630,433 bytes) to SW reference
Frames 1 vs 2 differ in size — real content change captured.
Phase 0 boolean-correctness criterion for H.264: PASS.
Contract trace:
The V4L2 + media-request ioctl sequence per H.264 frame is the
canonical iter6/iter7 pattern:
S_EXT_CTRLS (CODEC_STATELESS class, request_fd=N)
QBUF CAPTURE_MPLANE index=K
QBUF OUTPUT_MPLANE index=K (compressed slice)
MEDIA_REQUEST_IOC_QUEUE (request_fd=N)
MEDIA_REQUEST_IOC_REINIT (request_fd=N) ← per-OUTPUT-slot reuse
DQBUF OUTPUT_MPLANE index=K
DQBUF CAPTURE_MPLANE index=K
REINIT-before-DQBUF works because the kernel completes decode in
~0.6 ms (request → COMPLETE state), and mainline media_request_
ioctl_reinit accepts both IDLE and COMPLETE. iter7 cap_pool
instantiates 24 slots cleanly: "v4l2-request: cap_pool_init: 24
slots ready" in mpv stdout.
No EINVAL, no EBUSY, no errors observed across 5 frames. iter4's
frame-11 EINVAL bug from libva-multiplanar does not reproduce on
RK3399 in this short window (longer-run repro is Phase 1+ work).
Side finding — cache-stale readback bug present in libva-backend's
vaDeriveImage path on RK3399:
When pixels are read via the cached-mmap path (libva's vaDeriveImage
+ vaMapBuffer, used by ffmpeg -hwaccel vaapi -hwaccel_output_format
nv12), readback is corrupted in exactly the iter1 patch-0011 pattern:
size=6,220,800 bytes (correct: 2 × 1920×1080×1.5 NV12)
non-zero=544 (0.009%)
pattern: 16 consecutive non-zero bytes at every 1920-byte row stride,
rest of buffer reads as zero
diff vs SW reference: 100% of bytes differ, MAE=53.3 per byte
This is the canonical stale-cached-mmap pattern. Kernel writes real
pixels (proven by DMA-BUF GL import readback succeeding), but the
libva backend's image-export path returns a cached pointer without
the correct cache-invalidation incantation. Userspace reads stale
all-zero memory punctuated by whichever cache lines happened to fetch
post-write.
Phase 4 work item: audit whether the iter1 patch-0011 cache-flush
fix is present, effective, or RK3399-routing-bypassed. Three
possibilities: (a) fix landed for RK3568 but cache topology differs
on RK3399, (b) fix is gated on something that's not true on RK3399,
or (c) RK3399 V4L2_MEMORY_MMAP page protection bypasses the flush.
Not gating Phase 0 — kernel-side decode is correct.
Phase 1+ binding cells must use the DMA-BUF GL import path for pixel
verification, not vaDeriveImage / cached-mmap. The iter1 lesson
restated: cached-mmap readback is unreliable on this hardware family.
Evidence files (under phase0_evidence/2026-05-07/h264_baseline_trace.md
and h264_baseline/):
- mpv.stdout — libva log, vaapi-copy engaged, cap_pool_init
- h264_baseline_trace.md — full writeup with re-run incantations
- mpv.strace.* (gitignored) — 19 per-thread ioctl/openat traces
- ftrace_v4l2.txt (gitignored) — kernel qbuf/dqbuf events
- merged_ioctls.tsv (gitignored) — time-sorted V4L2/MEDIA/DRM
ioctls across all threads
- *.jpg (gitignored) — HW vs SW JPEG comparison artefacts
- frames_hw_cached_readback.nv12 (gitignored) — broken nv12
readback for forensic reference
gitignore: extended extension list (jpg, png, nv12, yuv, tsv, strace*).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
60e62da666 |
phase 0 corrections: hantro RK3399 has no H.264; substrate is iter8 master
Two empirical corrections to the morning-of-2026-05-07 phase 0 lock,
based on V4L2 inventory + iter8 fork build smoke captured this evening
on fresnel (kernel 6.19.9-99-eos-arm).
Correction 1 — hantro-vpu-dec on RK3399 does not advertise H.264.
phase0_findings.md morning lock claimed both rkvdec (/dev/video3)
and hantro-vpu-dec (/dev/video5) advertise H.264. Empirical
v4l2-ctl --list-formats-out shows hantro-vpu-dec exposes only
MG2S (MPEG-2) and VP8F (VP8) — no S264. Likely carryover from
RK3568 (ohm) hantro, which does support H.264; the RK3399 hantro
kernel variant in drivers/media/platform/verisilicon/ registers
a different codec list. Fix:
- README.md hardware-target table: drop "+ H.264" from Decoder
block 2.
- README.md decode-side surface-area paragraph: note hantro is
MPEG-2 + VP8 only and that there is exactly one bind for H.264
(rkvdec).
- phase0_findings.md mechanism table: drop H.264 from /dev/video5
row; correct DT compatible to rockchip,rk3399-vpu (the actual
parent device compatible — sysfs reports rockchip,rk3399-vpu,
not rockchip,rk3399-vpu-dec which is just the v4l2 card type
string).
- phase0_findings.md "H.264 lands on both blocks" sentence:
inverted to "H.264 lands only on rkvdec".
- phase0_findings.md Open Question #2 (two-block H.264 routing):
marked RESOLVED 2026-05-07 evening (null). Single bind, no
routing decision, one test cell per codec.
Empirical evidence: phase0_evidence/2026-05-07/v4l2_inventory_findings.md
(distilled from v4l2_inventory.txt — the latter is gitignored as
raw data, regenerable via the v4l2-ctl invocation documented in
the findings file).
Correction 2 — substrate is iter8 master (65969da), not iter5-end.
phase0_findings.md morning lock framed the substrate as "iter5-end
fork." That was true on 2026-05-05 (iter5 close); between then and
the 2026-05-07 fresnel-fourier scaffold libva-multiplanar continued
through iter6 (per-OUTPUT-slot REINIT request_fd binding), iter7
(slot-leak fix, cap_pool harness, msync verify harness, OUTPUT-pool
teardown), and iter8 (perf binding cell harness, RK3566/3568 doc
fix). Building from master tip 65969da inherits all the iter6-iter8
hardening at zero cost. Fix:
- phase0_findings.md substrate paragraph: strikethrough the
"iter5-end" framing, add corrected paragraph naming master
tip 65969da and listing what iter6/7/8 added.
- phase0_findings.md top-of-doc: add an "Empirical corrections
2026-05-07 evening" callout linking to the evidence files,
so a reader spotting the locked-vs-corrected mismatch knows
where the empirical update came from.
Empirical evidence: phase0_evidence/2026-05-07/iter8_build_smoke.md
(clean build, vainfo profile enumeration, HEVC anomaly write-up).
What's preserved on purpose:
The strikethrough rendering in phase0_findings.md keeps the original
locked text visible alongside the correction — campaign convention
treats locks as historical record, not editable state. A reader
landing on the file from a deep link sees both the morning's
intent and the evening's empirical update. Git history has the
clean diff if anyone wants the original without strikethrough.
What's not changed:
The codec scope in the locked research question stays correct in
count — five codecs (H.264 + HEVC + VP9 + MPEG-2 + VP8). The
routing table changes (H.264 → rkvdec only; MPEG-2 → hantro only;
no shared block) but the boolean-correctness pass/fail criterion
per codec is unaffected. Phase 1 lock can proceed on the corrected
map without re-opening scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
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> |
||
|
|
c9a96cbb38 |
fresnel-fourier campaign scaffold: peer to libva-multiplanar, RK3399 target
Roll out libva-v4l2-request-fourier on fresnel (Pinebook Pro / RK3399) with broader codec scope than ohm-side libva-multiplanar: - H.264 + HEVC + VP9 via the rkvdec block (/dev/video3) - MPEG-2 + VP8 via the hantro-vpu-dec block (/dev/video5) Topology: peer campaign, independent 8(+1) loop. fresnel-fourier results do not gate libva-multiplanar Phase 8 closes. Code-side work in the shared fork (../libva-multiplanar/libva-v4l2-request-fourier/) lands per Phase 2 source-read of each iteration. Phase 0 task 1: recover fresnel from the SDDM greeter crash-loop (per ~/.claude/plans/dynamic-forging-piglet.md). Recovery is bookkept inside this campaign's Phase 0, not as an out-of-band prereq. Verified 2026-05-07 via SSH: - linux-eos-arm 6.19.9-99 has CONFIG_FTRACE=y + CONFIG_FUNCTION_TRACER=y + CONFIG_DYNAMIC_FTRACE=y + CONFIG_TRACING=y. /sys/kernel/tracing/ populated. No kernel rebuild needed for trace work. - /dev/video3 = rkvdec (NV12 capture, MPLANE). - /dev/video5 = hantro-vpu, card type rockchip,rk3399-vpu-dec. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |