11 KiB
Pre-Compact Handoff — Session 2026-05-14 (FINAL post iter34)
Use this doc to resume the fresnel-fourier campaign after Claude context compaction. Campaign is at full close state: 5/5 codecs PASS.
TL;DR (read first)
| Bug | Status | Fix |
|---|---|---|
| Bug 4 (H.264 keyframe-partial) | FIXED iter25 α-25 | rkvdec image_fmt pre-seed via synthetic SPS at CreateContext |
| Bug 5 (HEVC libva all-zero CAPTURE) | FIXED iter25 + iter31 | α-25 (image_fmt) + α-29 (slice_params.short_term_ref_pic_set_size from VAAPI st_rps_bits) |
| VP8 wrong output through libva | FIXED iter33 α-30 | prepend VP8 uncompressed frame header (10 kf / 3 inter) to OUTPUT |
| MPEG-2 HW differs from SW | NOT A BUG | hantro IDCT precision (≤1 LSB / ~67 px); libva==kdirect bit-exact |
| Kernel diagnostic printks | CLEANED iter32 + iter34 | 7.0-14 ship |
| Codec | libva 10F sha | kdirect 10F sha | SW 10F sha | L==K | L==SW |
|---|---|---|---|---|---|
| H.264 | dd4f5f2d552c07bc | same | same | ✓ | ✓ |
| HEVC | 108f925bb6cbb6c9 | same | same | ✓ | ✓ |
| VP9 | cf35908ae0f9ab60 | same | same | ✓ | ✓ |
| VP8 | d3231e5b6c0ee10b | same | same | ✓ | ✓ |
| MPEG-2 | 95c5905890c937d4 | same | 933b744134e47ba4 | ✓ | ~ |
5/5 PASS the libva-vs-kdirect bit-exact contract.
Substrate state (where things live)
| Component | Location | Tip |
|---|---|---|
| Campaign repo (this) | /home/mfritsche/src/fresnel-fourier/ |
70ddbd6 on gitea master |
| Libva backend fork (noether) | /home/mfritsche/src/libva-multiplanar/libva-v4l2-request-fourier/ |
7e0848d on gitea master |
| Libva backend (fresnel deploy) | /home/mfritsche/src/libva-v4l2-request-fourier/ |
sync to gitea master, ninja -C build |
| Kernel source (boltzmann) | ~/src/kernel-agent-bootstrap/build/marfrit-packages/arch/linux-fresnel-fourier/ |
pkgrel=14 clean (no diagnostic printks) |
| Kernel running on fresnel | linux-fresnel-fourier 7.0-14 |
clean shipping kernel |
| Test fixtures (fresnel) | /home/mfritsche/fourier-test/bbb_*.{mp4,ts,webm} |
5 codecs at 720p10s or 1080p30 |
| Anchors (fresnel) | /tmp/final/{L,K,S}_<codec>.yuv |
10-frame YUV per codec per backend |
| Memory | ~/.claude/projects/-home-mfritsche-src-fresnel-fourier/memory/ |
see entries below |
Identity for gitea pushes
All git.reauktion.de interactions use claude-noether identity (per memory feedback_gitea_as_claude_noether.md). Backend remote URL: ssh://gitea@git.reauktion.de.claude-noether/marfrit/libva-v4l2-request-fourier.git.
Device map on 7.0-14 (REVERSED from 7.0-13)
/dev/video* and /dev/media* numbers SHIFT between kernel boots based on probe order. On 7.0-14 (current):
| Driver | /dev/videoN | /dev/mediaN |
|---|---|---|
| rockchip-rga | video0 | n/a |
| rk3399-vpu-enc | video1 | (shared) |
| rk3399-vpu-dec (hantro) | video2 | media0 |
| rkvdec | video3 | media1 |
Always re-probe via v4l2-ctl --info + media-ctl -p before hardcoding paths.
Backend commits delivered (chronological, this campaign day)
7e0848d iter33 α-30: prepend VP8 uncompressed frame header to OUTPUT buffer ← VP8 fix
bf3e3d8 iter33: extend VP8 DIAG to dump VAAPI probability struct directly (env-gated diag)
4b3c21b iter33 DIAG: env-gated dump of v4l2_ctrl_vp8_frame contents (env-gated diag)
23eb1bd iter31 α-29: slice_params.short_term_ref_pic_set_size = picture->st_rps_bits ← HEVC fix
68dbbdd iter30 DIAG: LIBVA_TS_SCALE env-gated timestamp multiplier (env-gated diag)
0eca3ff iter29 DIAG: env-gated dump of HEVC slice_data trailing 80 bytes (env-gated diag)
6646b16 Revert iter28b DIAG: trim=40 universal-trim broke IDR frame 1
cd286d9 iter28 α-28: bit_size = (slice_data_size - data_byte_offset) * 8 for HEVC
754be1d iter27 diag: env-gated VAAPI slice fields dump
719d813 iter27 α-27: populate slice_params.num_entry_point_offsets (no-op)
66ef848 iter26 α-26: decode_params.short_term_ref_pic_set_size from VAAPI (mis-routed cosmetic)
d062fec iter25 α-25 fix: FRAME_MBS_ONLY flag for H264 dummy SPS
db0b7f9 iter25 α-25: inject synthetic SPS before cap_pool_init to seed image_fmt ← H264+HEVC frame 1 fix
The load-bearing commits are db0b7f9 + d062fec (α-25), 23eb1bd (α-29), 7e0848d (α-30). The DIAG commits are env-gated and inactive by default.
Campaign repo commits delivered (today's arc)
70ddbd6 iter34 close: kernel 7.0-14 CLEAN ship — 5/5 codecs PASS
cd2d077 iter33: MPEG-2 closed (libva==kdirect bit-exact) — 5/5 codecs PASS
51eee19 iter33 α-30 close: VP8 FIXED — 4/5 codecs PASS
acacf3d iter32 close: kernel substrate cleanup landed → 7.0-11 SHIPPING
85cc178 Update campaign session doc: full-day arc closes at 3/3 PASS
fde8a25 Update handoff doc: HEVC Bug 5 fully fixed (3/3 PASS)
c1f9738 iter31 α-29 close: HEVC Bug 5 remainder FIXED — 3/3 PASS
422ecaf Add pre-compact handoff doc for session resumption
…earlier in day:
c15fc6c, 8b17bf7, 02c4192, bf67900 (iter20-28 chain)
How to verify the current state
Run on fresnel (post-7.0-14 boot, devices: rkvdec /dev/video3+/dev/media1, hantro /dev/video2+/dev/media0):
for codec in h264:bbb_1080p30_h264.mp4:rk hevc:bbb_720p10s_hevc.mp4:rk vp9:bbb_720p10s_vp9.webm:rk vp8:bbb_720p10s_vp8.webm:ha mpeg2:bbb_720p10s_mpeg2.ts:ha; do
name="${codec%%:*}"; rest="${codec#*:}"; fixture="${rest%:*}"; dev="${rest##*:}"
if [ "$dev" = "rk" ]; then V=/dev/video3; M=/dev/media1
else V=/dev/video2; M=/dev/media0; fi
env LIBVA_DRIVER_NAME=v4l2_request \
LIBVA_DRIVERS_PATH=/home/mfritsche/src/libva-v4l2-request-fourier/build/src \
LIBVA_V4L2_REQUEST_VIDEO_PATH=$V LIBVA_V4L2_REQUEST_MEDIA_PATH=$M \
ffmpeg -hide_banner -loglevel error -y \
-hwaccel vaapi -hwaccel_output_format vaapi \
-i "/home/mfritsche/fourier-test/$fixture" \
-vf "hwdownload,format=nv12" -frames:v 10 \
-f rawvideo -pix_fmt nv12 "/tmp/L_${name}.yuv"
ffmpeg -hide_banner -loglevel error -y -hwaccel v4l2request -hwaccel_output_format drm_prime \
-i "/home/mfritsche/fourier-test/$fixture" -vf "hwdownload,format=nv12" \
-frames:v 10 -f rawvideo -pix_fmt nv12 "/tmp/K_${name}.yuv"
L=$(sha256sum "/tmp/L_${name}.yuv" | cut -c1-16)
K=$(sha256sum "/tmp/K_${name}.yuv" | cut -c1-16)
[ "$L" = "$K" ] && echo "$name: PASS" || echo "$name: FAIL"
done
Expect: 5× PASS.
Root cause summary
Bug 4 + Bug 5 frame 1 (iter25 α-25): rkvdec_s_ctrl returns -EBUSY when first SPS triggers image_fmt reset on busy CAPTURE queue. libva pre-allocated 24 CAPTURE buffers at CreateContext (iter5b-β) before per-frame S_EXT_CTRLS. Fix: inject synthetic SPS at CreateContext, pre-cap_pool_init, while CAPTURE is empty.
Bug 5 frame 2+ (iter31 α-29): libva backend set slice_params->short_term_ref_pic_set_size = 0 (stale "VAAPI doesn't expose" comment). rkvdec's assemble_sw_rps (rkvdec-hevc.c:386-389) reads this; when zero with num_short_term_ref_pic_sets <= 1, falls back to 0 → entropy decoder consumes slice-header bits as long-term-RPS → garbage for every non-IDR slice. IDR is gated by !IDR_PIC so frame 1 was unaffected. Fix: slice_params->short_term_ref_pic_set_size = picture->st_rps_bits (VAAPI's field IS the slice-header bit count, per va_dec_hevc.h doc). α-26 had mis-routed this value into decode_params (same field name, different V4L2 semantics).
VP8 (iter33 α-30): ffmpeg-vaapi strips the VP8 uncompressed frame header (3 bytes interframe / 10 bytes keyframe) before submitting via VAAPI. ffmpeg-v4l2request keeps it. Hantro hard-codes first_part_offset = V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) ? 10 : 3 and uses it for both mb_offset_bits and dct_part_offset. Without the prepended header in libva's OUTPUT, hantro's offset arithmetic lands inside the compressed bitstream and the entropy decoder produces garbage. Fix: in codec_store_buffer, prepend header_size zero bytes to OUTPUT for VP8 profile (hantro skips these bytes for actual parsing, uses ctrl-struct values).
Open items (low priority, no blockers)
-
Backend env-gated diagnostics cleanup —
LIBVA_HEVC_DUMP_SLICE_TAIL(iter29),LIBVA_TS_SCALE(iter30),LIBVA_VP8_DUMP_FRAME(iter33) are env-gated and inactive by default. Leave for future regression debugging or clean up. Low priority. -
α-26 cosmetic revert —
decode_params->short_term_ref_pic_set_size = picture->st_rps_bitswas mis-routed (rkvdec doesn't use that field). Could revert to 0. Cosmetic; no behavior change. -
Libva multi-device probe — currently
find_codec_devicepicks ONE device per session, requiringLIBVA_V4L2_REQUEST_VIDEO_PATHoverride to access both rkvdec (H264/HEVC/VP9) and hantro (VP8/MPEG-2) within one workflow. Architectural change insrc/request.c::find_codec_device(~200-400 LOC). Design judgment from user welcome.
Memory entries (full set, this campaign)
feedback_rkvdec_image_fmt_pre_seed.md— α-25 (Bug 4 + Bug 5 frame 1)feedback_va_st_rps_bits_is_slice_field.md— α-29 (Bug 5 frame 2+)feedback_vaapi_strips_vp8_uncompressed_header.md— α-30 (VP8)feedback_libva_byte_correct_kernel_bug.md— FULLY OVERTURNED (both Bug 4 + Bug 5 are libva-side fixes)reference_fresnel_kernel_substrate.md— 7.0-14 clean, device-enumeration caveat noted- MEMORY.md index updated
Key commands quickreference
# Sync backend on fresnel + rebuild
ssh fresnel 'cd ~/src/libva-v4l2-request-fourier && git fetch && git reset --hard origin/master && ninja -C build'
# Identify which video device is rkvdec vs hantro after a fresh boot
ssh fresnel 'for v in /dev/video*; do v4l2-ctl -d $v --info 2>/dev/null | grep -E "^Card type" | head -1 | awk -v dev=$v "{print dev,\$0}"; done'
# 5-codec smoke (above script)
# Run libva HEVC (rkvdec is currently /dev/video3 on 7.0-14)
ssh fresnel 'env LIBVA_DRIVER_NAME=v4l2_request \
LIBVA_DRIVERS_PATH=/home/mfritsche/src/libva-v4l2-request-fourier/build/src \
LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video3 LIBVA_V4L2_REQUEST_MEDIA_PATH=/dev/media1 \
ffmpeg -hide_banner -loglevel error -y -hwaccel vaapi -hwaccel_output_format vaapi \
-i /home/mfritsche/fourier-test/bbb_720p10s_hevc.mp4 \
-vf "hwdownload,format=nv12" -frames:v 10 -f rawvideo -pix_fmt nv12 /tmp/x.yuv'
# kdirect reference (works for any codec; hwaccel auto-routes)
ssh fresnel 'ffmpeg -hide_banner -loglevel error -y -hwaccel v4l2request -hwaccel_output_format drm_prime \
-i /home/mfritsche/fourier-test/bbb_720p10s_hevc.mp4 \
-vf "hwdownload,format=nv12" -frames:v 10 -f rawvideo -pix_fmt nv12 /tmp/y.yuv'
# Reboot fresnel (sddm autologin reseats mfritsche)
ssh fresnel 'sudo systemctl reboot'; sleep 60
Safe vs needs-confirmation actions
Safe (no confirmation needed):
- Read/grep on noether, boltzmann, fresnel
- Push to gitea (claude-noether identity)
- Reboot fresnel (sddm autologin restores session)
- Build kernel on boltzmann via
makepkg -ef --skipinteg --noconfirm - Deploy kernel via
scp+sudo pacman -U - Run ffmpeg/cmp tests on fresnel
Needs confirmation:
- Significant rebuild (~25-30 min CPU on boltzmann, e.g. ffmpeg full rebuild or fresh kernel build)
- Architectural changes to libva multi-device probe (item 3 above) — affects backend design