2918dda2e0581fbd8878d7c0a3e59f0793f54c94
23 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2918dda2e0 |
iter3 Phase 4: plan — 10 contract clauses, ~308-LOC patch, 3 commits
Locks the iter3 patch shape against Phase 3 verbatim cross-validator
payload + Phase 2 contract surface. 10 contract clauses cite kernel
UAPI + VAAPI + FFmpeg ref + Phase 3 byte anchors throughout.
Patch shape (mirrors iter1 ABCD pattern):
Commit A: src/config.c — enumeration block + CreateConfig case +
QueryConfigEntrypoints case (3 sites, +16 LOC, 1 file).
After: vainfo lists VP8Version0_3.
Commit B: NEW src/vp8.c (~200 LOC) + NEW src/vp8.h (~40 LOC) +
meson.build sources/headers entries (+2). 3 files
(2 new + 1 modified).
After: vp8.o compiles standalone.
Commit C: src/picture.c — codec_set_controls dispatch +
codec_store_buffer 4 buffer-type cases + outer
VAProbabilityDataBufferType case + BeginPicture
per-frame reset (4 sites, +40 LOC) + src/surface.h
params.vp8 union member (+10 LOC). 2 files modified.
After: end-to-end VP8 decode through libva backend.
Total: ~308 LOC, 6 files (2 new + 4 modified), 3 commits.
Contract clauses summary:
1. Submission shape — single VIDIOC_S_EXT_CTRLS, count=1, ctrl_class=
V4L2_CTRL_CLASS_CODEC_STATELESS (0xf010000), id=0xa409c8,
size=1232 bytes
2. Local struct alloc + zero-init (memset clears all padding)
3. Frame geometry + version + per-frame scalars (off-by-one
num_dct_parts = num_of_partitions - 1)
4. DPB timestamp resolution (3 refs: last/golden/alt; 0-sentinel
when SURFACE() returns NULL — mirrors iter1 mpeg2.c pattern)
5. Loop filter mapping (6 fields + 3 flag bits)
6. Quantization base + delta derivation (segment 0 = base via
iqmatrix[0][0]; deltas = iqmatrix[0][N+1] - iqmatrix[0][0]
signed; per-segment quant_update[1..3] only when segmentation
enabled)
7. Segment fields (segment_probs direct copy; flags assembled +
DELTA_VALUE_MODE set unconditionally per FFmpeg pattern)
8. Entropy table mapping — 3 VAAPI sources (Picture: y_mode +
uv_mode + mv_probs; ProbabilityData: coeff_probs[4][8][3][11]
direct memcpy; IQMatrix: quant)
9. Coder state + first-partition fields + flags (6 mainline-
documented bits only; bit 0x40 + EXPERIMENTAL NOT replicated
vs ffmpeg-v4l2-request-git anomaly; first_part_header_bits=0
fallback documented as known fidelity gap)
10. Final batched submission via v4l2_set_controls
Phase 5 review questions queued (7 items): quantization derivation
correctness, per-segment quant_update semantics, first_part_header_
bits=0 safety, probability buffer ordering, endianness, struct size
sizeof correctness, field-availability test-compile per memory
feedback_review_empirical_over_theoretical Direction 2.
Cross-cutting backlog deferred (B1, B3, B4, B5, B6, L3 inherited;
iter3-Q1 first_part_header_bits + iter3-flags 0x40 anomaly NEW).
Refs:
phase0_findings_iter3.md (Phase 1 lock)
phase2_iter3_situation.md (Phase 2 contract surface)
phase3_iter3_baseline.md (Phase 3 verbatim payload anchors)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
fd3fce86a6 |
iter3 Phase 3: baselines — VP8 cross-validator + 3-codec regression
+ SW reference
Captured on fresnel 2026-05-08 across two suspend cycles (laptop
dropped twice mid-run, captures preserved on /tmp/iter3_phase3).
All Phase 3 deliverables green.
Substrate verification:
backend SHA256: 9e27...6258 (matches iter2 close)
3-codec regression block: ALL 6 reference hashes match byte-for-
byte vs iter1+iter2 (H.264 +30s, MPEG-2 +02s, HEVC +02s on rkvdec/
hantro). Substrate has not regressed; criterion-5 anchor solid.
Cross-validator anchor (ffmpeg-v4l2request VP8 strace):
- VIDIOC_S_EXT_CTRLS, count=1, ctrl_class=V4L2_CTRL_CLASS_CODEC_
STATELESS, id=0xa409c8, size=1232 bytes
- struct size CORRECTED: v4l2_ctrl_vp8_frame = 1232 bytes (NOT
400 as one might assume; entropy.coeff_probs[4][8][3][11] alone
is 1056 bytes)
- keyframe (frame 1) verbatim payload captured: y_ac_qi=8,
last/golden/alt ts all 0, flags=0x0d (KEY|SHOW|NOSKIP),
y_mode_probs=[145,156,163,128] (matches FFmpeg keyframe const)
- inter frame verbatim payload captured: y_ac_qi=122, all DPB
timestamps non-zero, flags=0x66 (anomaly: bit 0x40 not in
mainline UAPI; vendor-patched ffmpeg-v4l2-request-git;
kernel hantro_vp8.c only inspects KEY_FRAME bit, ignores
bit 0x40)
VP8 SW pixel-verify reference (criterion-4 anchor):
vp8_sw_001.jpg: e43757a40e5d71ad176455c0fda14c2cbf9351b702188fc8ad
584d789db2c984
vp8_sw_002.jpg: a86bf885e588257731ff6cf8d2ccc5756be550e85220eee1c3
e6ea8c0c78e97a
Frame 1 != Frame 2 (real motion). These are the Phase 7 byte-
compare HW-vs-SW targets.
Open-question resolution (5 of 6 answered empirically):
Q1 first_part_header_bits — varies per frame (key=6550, inter
ranges 86..254); VAAPI doesn't expose. Phase 4 fallback:
leave 0 and check kernel behavior at Phase 7 byte-compare.
Phase 5 review will flag as known fidelity gap.
Q2 num_dct_parts vs VAAPI num_of_partitions — confirmed off-by-
one: kernel = VAAPI - 1 (BBB has VAAPI=2, kernel=1).
Q3 DPB timestamp 0-sentinel — confirmed: keyframe writes all
three timestamps as 0; iter3 mirrors iter1 mpeg2.c pattern.
Q4 SHOW_FRAME default — set on every captured frame (BBB has no
alt-ref invisible). Force unconditional in libva backend.
Q5 lf.flags FILTER_TYPE_SIMPLE — not set; BBB normal loop filter.
Direct mapping from VAAPI filter_type=0.
Q6 First-frame DPB sentinel — confirmed Q3; no self-reference
fallback needed (different from iter1 mpeg2.c).
V4L2 binding cells this boot:
rkvdec : /dev/video3 + /dev/media1
hantro-vpu-dec: /dev/video5 + /dev/media2
Capture artefacts on fresnel /tmp/iter3_phase3/ preserved for
Phase 7 re-run:
vp8_strace.* (19 files, multi-thread)
decode_vp8.py (payload decoder)
vp8_sw_00{1,2}.jpg (criterion-4)
{h264,mpeg2,hevc}_hw_00{1,2}.jpg (criterion-5)
Refs:
phase0_findings_iter3.md (Phase 1 lock)
phase2_iter3_situation.md (Phase 2 contract surface)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
898544a29c |
iter3 Phase 2: situation analysis — VP8 backend gaps + contract surface
Source-read of every file the iter3 patch series will touch, plus the
kernel UAPI + VAAPI + downstream FFmpeg + kernel hantro reference
sources. Conducted on noether against fork tip 8d71e20 (iter2 Phase 6
commit B); fresnel.vpn was unreachable so Phase 3 baseline empirical
capture defers until laptop reachable.
Bug enumeration (10 sites the patch series must touch):
B1 config.c::RequestQueryConfigProfiles enumeration block missing
B2 config.c::RequestCreateConfig VP8 case label missing
B3 config.c::RequestQueryConfigEntrypoints VP8 case missing
B4 src/vp8.c new file ~160-220 LOC
B5 src/vp8.h new file ~35-45 LOC
B6 picture.c::codec_set_controls VP8 dispatch missing
B7 picture.c::codec_store_buffer 4 buffer-type cases +
VAProbabilityDataBufferType
outer case missing
B8 picture.c::RequestBeginPicture per-frame reset additions
B9 surface.h::object_surface::params union vp8 member missing
B10 meson.build vp8.c/vp8.h not in lists
Non-bugs (intentionally untouched):
- context.c (no DECODE_MODE/START_CODE menus for VP8)
- video.c (CAPTURE-side format list; VP8 is OUTPUT-side)
- v4l2.c (fourcc-agnostic helpers)
- buffer.c (buffer registry is type-agnostic)
- include/hevc-ctrls.h (already includes <linux/v4l2-controls.h>
which holds V4L2_CID_STATELESS_VP8_FRAME)
Contract surface cited verbatim:
- V4L2_CID_STATELESS_VP8_FRAME = V4L2_CID_CODEC_STATELESS_BASE+200
= 0x00a409c8 (matches Phase 0 V4L2 inventory)
- struct v4l2_ctrl_vp8_frame at <linux/v4l2-controls.h>:1929-1958
+ 5 sub-structs (segment, lf, quant, entropy, coder_state) at
1785-1888
- VAAPI VAPictureParameterBufferVP8 + VASliceParameterBufferVP8 +
VAProbabilityDataBufferVP8 + VAIQMatrixBufferVP8 at
references/libva/va/va_dec_vp8.h
- FFmpeg v4l2_request_vp8.c reference: single batched S_EXT_CTRLS
at end_frame, count=1, no init-time menus
- Kernel hantro_vp8.c::hantro_vp8_prob_update reads 9 fields from
hdr (skip/intra/last/gf probs, segment_probs, entropy.{y,uv,mv,
coeff}_probs)
VAAPI → V4L2 mapping table: 30 fields enumerated. Open questions for
Phase 3 baseline (6 items: first_part_header_bits derivation, num_
dct_parts off-by-one, DPB timestamp 0-sentinel handling, show_frame
default, lf.flags FILTER_TYPE_SIMPLE bit, first-frame DPB sentinel).
Patch-shape prediction: ~260-340 LOC across 6 modified + 2 new
files. Medium-sized iter — between iter1's 120 LOC (3 modified +
1 deleted) and iter2's 470 LOC (5 modified). The new file dominates.
Phase 3 baseline targets queued: cross-validator strace verbatim
S_EXT_CTRLS payload capture, VAAPI consumer trace, mpv-SW reference
JPEG capture for criterion 4 byte-compare anchor.
Phase 4 plan structure anticipated: 10-clause template per iter2.
Refs:
phase0_findings_iter3.md (Phase 1 lock)
phase8_iteration2_close.md (predecessor close)
src/mpeg2.c (iter1 single-codec template; iter3 will mirror shape)
src/h265.c (iter2 dispatcher pattern; iter3 takes structure cues)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
ea2413e957 |
iter3 Phase 0 + Phase 1 lock: VP8 on hantro-vpu-dec
Opens iter3 of the fresnel-fourier campaign immediately after iter2
close (
|
||
|
|
df787a6cc2 |
iter2 Phase 8 close: 3/5 codecs passing, lesson L1 extended (BOTH directions)
Iteration 2 closes with all 5 Phase 1 boolean-correctness criteria
green. Third codec passes — campaign scoreboard 2/5 → 3/5 (H.264
in T4, MPEG-2 in iter1, HEVC in iter2). Loop terminates per
feedback_dev_process.md Phase 8.
Notable: ZERO Phase 7 → Phase 4 loopbacks needed. Phase 5 review
caught all 3 would-be loopback triggers in advance (data_byte_offset
rename, dpb.rps→index-arrays semantics, pic_order_cnt_val rename).
This is the dev-process ideal: review catches bugs before
implementation lands; verification confirms contract.
What landed:
Code (libva-v4l2-request-fourier master 229d6d1 → 8d71e20):
cca539d iter2 Phase 6 commit A: config.c break for HEVCMain case
8d71e20 iter2 Phase 6 commit B: rewrite h265.c against new V4L2
stateless HEVC API (6 files, 463 ins, 236 del)
Both authored as Claude (noether) per feedback_gitea_as_claude_noether.md.
Campaign docs (fresnel-fourier):
|
||
|
|
05b4bd56ec |
iter2 Phase 7: verification — all 5 criteria GREEN, third codec PASS
Phase 7 verification of iter2 HEVC fix executed against fork tip
8d71e20 (libva-v4l2-request-fourier master = post-iter2-Commit-B).
Verbatim raw output captured to phase0_evidence/2026-05-08/
iter2_phase7/. All five Phase 1 criteria green; bonus byte-compare
confirms structural match against Baseline B with two minor field-
value divergences (informational SPS fields VAAPI doesn't expose;
non-blocking per Criterion 4 byte-identical pixel pass).
Phase 1 → Phase 7 scoreboard:
Criterion 1 (vainfo VAProfileHEVCMain enum): PASS
rkvdec bind: H.264 (5 profiles) + HEVCMain — same as Baseline.
Criterion 2 (vaCreateConfig SUCCESS for HEVCMain): PASS
Pre-iter2: VA_STATUS_ERROR_UNSUPPORTED_PROFILE (12)
Post-iter2: VA_STATUS_SUCCESS (verified verbatim libva trace)
Criterion 3 (ffmpeg-direct HEVC engages backend, exit 0): PASS
5 frames decoded clean, cap_pool_init: 24 slots ready,
no Failed-to-create lines, no S_EXT_CTRLS EINVAL.
Criterion 4 (DMA-BUF GL HEVC HW=SW byte-identical at +02s): PASS
HW frame 1: 47a5f3850df5d8c732767a227830c2272ff78402a7b6adeea329e29838808be5
SW frame 1: 47a5f3850df5d8c732767a227830c2272ff78402a7b6adeea329e29838808be5
HW frame 2: a467b3bc9d7b6374b6786ecfac46932d6c7bb932ab11d311edaa233d7863e656
SW frame 2: a467b3bc9d7b6374b6786ecfac46932d6c7bb932ab11d311edaa233d7863e656
Frames 1 vs 2 hash-differ (real motion).
Criterion 5 (iter1 MPEG-2 + T4 H.264 reference hashes): PASS
H.264 +30s HW1: f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9 (T4 ref MATCH)
H.264 +30s HW2: 7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8 (T4 ref MATCH)
MPEG-2 +02s HW1: 6e7873030dbf0403c67f35dd106ebef3c7909a0fd12433b82ad758e7fee9f092 (iter1 ref MATCH)
MPEG-2 +02s HW2: ccc7ce08810d4a96e9ba7a19f4f95bbf6cc861bda9337604b5c668ad52bef7de (iter1 ref MATCH)
Bonus byte-compare against Phase 3 Baseline B verbatim:
count=5, ctrl_class=V4L2_CTRL_CLASS_CODEC_STATELESS=0xf010000:
SPS id=0xa40a90 size=40 (matches Baseline B)
PPS id=0xa40a91 size=64 (matches)
SLICE_PARAMS id=0xa40a92 size=280 (1 slice × sizeof(slice_params))
SCALING_MATRIX id=0xa40a93 size=1000 (matches sizeof(scaling_matrix);
Phase 4 plan typo'\''d 1296 — actual
struct sums to 1000 = 96+384+384+
128+6+2)
DECODE_PARAMS id=0xa40a94 size=328 (matches)
All return = 0 (kernel accepts every batched call).
SPS field-value divergences vs Baseline B (FFmpeg-v4l2request):
sps_max_num_reorder_pics: post-fix=0 baseline=2 DIVERGE
sps_max_latency_increase_plus1: post-fix=0 baseline=4 DIVERGE
All other SPS fields match (pic_width=1280, pic_height=720,
bit_depth=0, flags=0x180=SAO|STRONG_INTRA_SMOOTHING).
PPS flags also diverge slightly (bit 12 ENTROPY_CODING_SYNC_ENABLED:
post-fix unset, baseline set). Other PPS fields match.
Cause: VAAPI'\''s VAPictureParameterBufferHEVC doesn'\''t expose
sps_max_num_reorder_pics, sps_max_latency_increase_plus1, or
always-truthful entropy_coding_sync. FFmpeg parses these from
bitstream directly. Operational impact NIL (Criterion 4 byte-
identical pixel pass — kernel decoded correctly with these fields
defaulted to 0). Phase 8 polish backlog candidate (low priority):
add SPS bitstream parsing to extract these fields when VAAPI
doesn'\''t supply them.
Phase 7 → Phase 8: clean transition, no loopback.
Notable Phase 7 observations for Phase 8 memory:
1. Phase 5 review value confirmed: 3 Critical findings (C1
data_byte_offset rename, C2 dpb.rps→index-arrays semantics,
C3 pic_order_cnt_val rename) caught at Phase 5 — prevented
Phase 6 compile failures + at least 1-2 Phase 7→Phase 4
loopback cycles. Per memory feedback_review_empirical_over_
theoretical.md: every Critical/Should-fix verified
empirically before responding. Lesson held.
2. One Phase 5 amendment was empirically wrong: S1 suggested
uniform_spacing_flag exists in VAAPI; gcc test-compile rejected.
Both PPS bits 19+20 left zero (VAAPI exposes neither).
Documented inline. Lesson: even reviewer-cited field mappings
warrant empirical verification.
3. Phase 4 plan typo: claimed sizeof(scaling_matrix) = 1296;
empirical size is 1000. Code uses sizeof() so produces correct
bytes. Plan body amendment-by-side-channel; not blocking.
4. VAAPI↔V4L2 field-fidelity gaps surfaced: 2 SPS fields +
possibly 1 PPS bit not exposed by VAAPI. Operational nil;
Phase 8 polish-backlog candidate.
5. mpv --hwdec=vaapi engages HEVC cleanly (no MPEG-2-style
filtering). Confirms Phase 5 Q3 — VAPictureParameterBufferType
sent per-frame for HEVC; latent B3 bug masked same as MPEG-2.
6. BBB HEVC fixture is 1 slice per frame (slice_params size=280
= 1 × sizeof). Multi-slice path in iter2 is coded but
untested by binding cell.
Campaign scoreboard: 2/5 → 3/5 codecs passing
(H.264 in T4, MPEG-2 in iter1, HEVC in iter2). iter2 advances
to Phase 8.
Refs:
../libva-v4l2-request-fourier@8d71e20 (the fork tip verified)
phase4_iter2_plan.md (10 contract clauses; SCALING_MATRIX size
typo noted)
phase5_iter2_review.md (3 Critical + 4 Should-fix amendments
all incorporated; S1 partially empirically
incorrect — VAAPI doesn'\''t expose
uniform_spacing_flag)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
9eae068f11 |
iter2 Phase 5: sonnet review — 3 critical UAPI errors caught, 7 amendments
Phase 5 review run via Plan subagent with model: sonnet per
feedback_dev_process.md Phase 5 discipline. 13 findings: 3 Critical
+ 4 Should-fix + 3 Question + 3 Nit. Reviewer's bottom-line: medium
confidence (vs iter1's medium-high) — lower because the plan had
3 concrete-and-wrong claims about kernel UAPI struct fields that
would have caused compile errors or silent semantic bugs in Phase 6.
Per memory feedback_review_empirical_over_theoretical.md: every
Critical and Should-fix finding was VERIFIED against fresnel's
kernel UAPI before responding. No source-read rebuttals attempted.
Critical resolutions:
C1 (data_byte_offset, not data_bit_offset):
Plan Clause 4 said new API "still requires bit_size + data_bit_
offset, this logic is preserved." Empirical: struct has
data_byte_offset (u32 byte count). FFmpeg uses straight byte
offset, no bit search. Plan amendment: drop bit-search at
h265.c:196-209; replace with byte-offset assignment.
ACCEPTED.
C2 (dpb.rps GONE, pic_order_cnt_val rename, poc_st_curr_*
arrays hold DPB indices):
Plan Clause 6 said "DPB extraction migrates verbatim." Empirical:
- dpb_entry has flags (only LONG_TERM_REFERENCE bit), no .rps
- pic_order_cnt_val (singular s32) replaces pic_order_cnt[0]
- poc_st_curr_before[16]/_after[16]/_lt_curr[16] are u8 DPB
INDICES, not POC values; populate via FFmpeg
get_ref_pic_index() pattern (search dpb[] by timestamp,
return index)
Plan amendment: replace "verbatim migration" claim with explicit
re-spec: classify VAAPI ReferenceFrames into ST_CURR_BEFORE/
AFTER/LT_CURR lists, assign DPB indices, populate arrays with
indices.
ACCEPTED.
C3 (union-aliasing reasoning wrong, claim still right):
Same anti-pattern as iter1 review C1. Plan said reset is benign
because RenderPicture per-buffer copies overwrite byte 17764.
Empirical: byte 17764 lands in num_slices region; non-HEVC
profiles never read that location. Reset is benign because
non-aliasing, NOT because of overwriting. Wording amended.
ACCEPTED.
Should-fix resolutions:
S1 (PPS flags 19+20 missing): empirical confirms
V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL<<19)
V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL<<20)
Plan amended to add both. ACCEPTED.
S2 (3 PPS scalars missing): empirical PPS struct dump confirms
pic_parameter_set_id, num_ref_idx_l0_default_active_minus1,
num_ref_idx_l1_default_active_minus1 all present in modern
struct. Plan amended to populate. ACCEPTED.
S3 (SCALING_MATRIX content divergence FFmpeg vs libva):
FFmpeg sends memset-zero when no scaling list in stream
(BBB has no scaling_list — SPS flags=SAO|STRONG_INTRA only).
Plan said "populate spec defaults when iqmatrix_set==false."
Phase 6 implementer choice; document in commit which path
taken. Phase 7 byte-compare validates. ACCEPTED as choice
rather than mandate.
S4 (FFmpeg function name wrong cite):
Plan cited ff_v4l2_request_query_control_default_value;
actual is ff_v4l2_request_query_control. Cosmetic fix.
ACCEPTED.
Question resolutions:
Q1 (object_heap allocator size handling): VERIFIED safe.
request.c:142-143 uses sizeof(struct object_surface). Adding
slices[64] auto-picks-up the larger size.
Q2 (slice_segment_addr field): VERIFIED present in struct.
Plan amended Clause 4: populate from VAAPI
slice->slice_segment_address. Single-slice BBB safe with
implicit zero; multi-slice would corrupt without this field.
Q3 (VAPictureParameterBufferType per-frame send for HEVC):
Deferred to Phase 7 LIBVA_TRACE capture. iter1+T4 patterns
suggest yes, worth grepping at verification time.
Nits N1+N2+N3: array size [16] not [8]; image-output
directory naming cosmetic; BeginPicture cleanup deferred.
Plan amendments consolidated:
1. Clause 4: data_byte_offset; drop bit-search; add
slice_segment_addr population (C1 + Q2)
2. Clause 6: explicit DPB classification + index-array logic;
pic_order_cnt_val rename; drop dpb.rps (C2)
3. Clause 3: 2 PPS flags + 3 scalars (S1, S2)
4. Clause 5: function name fix (S4); SCALING_MATRIX divergence
deferred to Phase 6 implementer (S3)
5. Clause 10: union-aliasing reasoning corrected (C3)
6. Clause 6: V4L2_HEVC_DPB_ENTRIES_NUM_MAX=16 macro reference (N1)
7. Phase 7 harness: rename png_* → image_* dirs (N2)
Plan re-locks with these amendments. Phase 6 proceeds.
Per global ~/.claude/CLAUDE.md rule: Phase 5 reviews never
skippable. iter2's review was the right path forward — caught
3 concrete UAPI errors (data_bit_offset → data_byte_offset rename;
dpb.rps field gone; pic_order_cnt struct shape) that would have
been Phase 6 compile failures or silent Phase 7 byte-compare
divergences requiring loopback. Outside-look value substantial.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
348736eb63 |
iter2 Phase 4: plan — 10 contract clauses, ~400-line h265.c rewrite
Phase 4 plan for iter2 HEVC 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.
10 contract clauses cited from authoritative sources:
Clause 1 — Per-frame batched VIDIOC_S_EXT_CTRLS, count=5
Authority: linux/v4l2-controls.h:2090-2300 (8 HEVC stateless CIDs)
Reference impl: FFmpeg libavcodec/v4l2_request_hevc.c:505-565
(v4l2_request_hevc_queue_decode)
Empirical anchor: Phase 3 Baseline B verbatim payload
Clause 2 — v4l2_ctrl_hevc_sps layout (40 bytes)
Authority: linux/v4l2-controls.h:2096+ (struct + 9 SPS_FLAG_* bits)
Field-by-field VAAPI source mapping table; existing
h265_fill_sps logic preserved, just routed to flags bitmask
Phase 3 Baseline B BBB SPS bytes: flags=SAO|STRONG_INTRA_SMOOTHING
Clause 3 — v4l2_ctrl_hevc_pps layout (64 bytes, 19 flags)
Authority: linux/v4l2-controls.h:2126-2150
Field source: VAPictureParameterBufferHEVC + slice (for
dependent_slice_segment_flag)
Clause 4 — v4l2_ctrl_hevc_slice_params (variable; dynamic-array)
Authority: kernel exposes 0xa40a92 elems=1 dims=[600] dynamic-array
Submission shape: size = sizeof(slice_params) * num_slices_in_frame
Reference impl: FFmpeg v4l2_request_hevc.c:540-547
BEHAVIORAL CHANGE: per-slice accumulation in codec_store_buffer
(replace overwrite with append-to-array)
DPB MOVES OUT of slice_params to DECODE_PARAMS (Clause 6)
Clause 5 — v4l2_ctrl_hevc_scaling_matrix (size M; conditional)
Conditional on kernel availability (probed via VIDIOC_QUERY_EXT_CTRL
at init), NOT on bitstream flag (Phase 3 baseline corrects Phase 2
assumption)
Spec defaults from ISO/IEC 23008-2 Table 4-1 when iqmatrix_set==false
PROTOCOL: transcribe defaults from Phase 3 Baseline B verbatim
SCALING_MATRIX bytes, NOT from spec recall (per
memory feedback_review_empirical_over_theoretical.md)
Clause 6 — v4l2_ctrl_hevc_decode_params layout (328 bytes)
NEW in modern API (didn't exist in staging-era)
Contains: DPB array (16 entries), POC, num_active_dpb_entries,
num_poc_st_curr_before/after, num_poc_lt_curr,
poc_st_curr_before[8], etc.
Source: existing h265_fill_slice_params lines 269-315 logic
preserved, routed to new struct
Clause 7 — Device-wide DECODE_MODE + START_CODE menus
Set once at init via v4l2_set_controls(...request_fd=-1, 2 ctrls)
rkvdec accepts: FRAME_BASED + ANNEX_B (only options per kernel menu
constraints, Phase 0 v4l2_inventory)
Default location: extend src/context.c:142-155 device-init block
Clause 8 — config.c HEVCMain case must break;
Authority: C semantics; iter1 Bug 1 pattern verbatim
Empirical anchor: Phase 3 Baseline D scratch confirmed
Clause 9 — picture.c::codec_set_controls HEVCMain dispatch
Authority: existing MPEG-2 dispatch pattern at picture.c:186-191
Replace explicit Fourier-local: HEVC stripped reject with
h265_set_controls call
Clause 10 — Per-slice accumulation in codec_store_buffer
HEVC slice_params dynamic-array source = per-RenderPicture appends
BeginPicture resets num_slices=0; codec_store_buffer appends each
VASliceParameterBufferType to slices[N] array
Diff scope (8 files):
src/config.c — 5-line break addition (Clause 8)
src/picture.c — HEVCMain dispatch (Clause 9) + per-slice
accumulation (Clause 10) + BeginPicture
num_slices reset, ~25 lines
src/surface.h — extend params.h265 with slices[64] +
num_slices, ~17 KB extra per surface union
src/h265.c — full rewrite ~400 lines (Clauses 2-7)
src/h265.h — re-enable
src/meson.build — uncomment h265.c + h265.h
src/context.c — extend device-init for HEVC DECODE_MODE +
START_CODE
include/hevc-ctrls.h — leave as-is (9-line shim, lower-risk path
per iter1 Phase 5 Nit 6 deferral)
Phase 6 implementation order (2 logical commits + optional fix-forward):
A: src/config.c HEVCMain break only (substrate fix in isolation;
Phase 3 Baseline D already verified collateral safe)
B: h265.c rewrite + picture.c dispatch + slice_params accumulation +
meson re-enable + surface.h extension + context.c device-init
C: optional fix-forward if Phase 7 surfaces a regression
Phase 7 verification harness (full Bash incantations in plan body):
Criterion 1: vainfo lists VAProfileHEVCMain on rkvdec
Criterion 2: vaCreateConfig(VAProfileHEVCMain) = SUCCESS via libva trace
Criterion 3: ffmpeg -hwaccel vaapi exit 0, no Failed-to-create
Criterion 4: mpv --hwdec=vaapi --vo=image at +02s; HW=SW byte-identical
(DMA-BUF GL cache-coherency-safe path per memory
feedback_rockchip_pixel_verify_path.md)
Criterion 5: iter1 MPEG-2 + T4 H.264 reference hashes still match
Bonus: byte-compare post-fix S_EXT_CTRLS payload vs Baseline B
Pre-identified Phase 7 → Phase 4 loopback triggers:
1. S_EXT_CTRLS EINVAL post-fix → check struct sizes (pahole),
reserved zeroing, SCALING_MATRIX size encoding
2. HW pixel hash mismatch → DPB ordering, slice_params bit_offset,
SPS/PPS flags bit positions, SCALING_MATRIX values
3. mpv --hwdec=vaapi filters HEVC out → fall-forward to ffmpeg
-vf hwdownload (less likely; vaapi engaged MPEG-2 in iter1)
4. iter1/T4 regression → verify diffs scoped right
5. Slice_params dynamic-array submission shape rejected → cross-
validator size encoding anchor
6. SCALING_MATRIX availability detection wrong → defensive
QUERY_EXT_CTRL probe in h265_init_device_controls
7. Latent bug B3 hits HEVC differently than MPEG-2 → byte 240 in
h265.picture; ffmpeg-vaapi sends VAPictureParameterBufferType
per frame so masking holds
Out-of-scope (LOCKED): VP9/VP8; HEVC Main 10 / Main Still Picture /
range ext / tile-wavefront; perf metrics; long-duration stress;
SLICE_BASED decode mode (rkvdec FRAME_BASED only); Phase 4 cross-
cutting backlog (B1 device-discovery, B3 BeginPicture profile-aware,
B4 context.c log suppression, B5 vbv_buffer_size, L3 vaDeriveImage
cache-stale); chromium-fourier 149 install; upstream engagement;
hevc-ctrls.h deletion (Phase 5 Nit 6 lower-risk path continues).
Predicted Phase 8 close: 4-6 commits on the fork (vs iter1's 4).
Iter2 ~3x larger codebase delta than iter1 (mpeg2.c rewrite was
~120 lines; h265.c rewrite is ~400 lines).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
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> |