70ddbd6c4b69a569d27500ca2bf66eb62093feaa
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |