Files
fresnel-fourier/phase8_iteration31_close.md
T
marfrit c1f9738368 iter31 α-29 close: HEVC Bug 5 remainder FIXED — 3/3 PASS
Fix: slice_params.short_term_ref_pic_set_size = picture->st_rps_bits
(was 0, mis-routed via α-26 into decode_params with same field name).

Final 5-codec state:
- H.264 10F: PASS (byte-equal SW)
- HEVC 10F: PASS (byte-equal SW)  ← THIS ITER
- VP9 10F: PASS (byte-equal SW)
- MPEG-2 / VP8: untestable through libva single-device probe
  (pre-existing limitation, orthogonal to Bug 4/5)

Backend fork tip: 23eb1bd. Kernel: 7.0-10 (diagnostic printks still in,
production cleanup outstanding).
2026-05-14 15:30:48 +00:00

62 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Iteration 29/30/31 — Phase 8 (close): HEVC frame 2+ FIXED
Closes 2026-05-14, second campaign-day session after iter27/28 partial close. Three sub-iterations: iter29 probe (refuted 40-byte inflation theory), iter30 timestamp-magnitude sweep (refuted timestamp hypothesis), **iter31 α-29 (FIX)**.
### Final result: 3/3 PASS (anchors that go through libva single-device probe)
| Codec | 10F result | Status |
|---|---|---|
| H.264 | byte-equal to SW (10 frames) | **PASS** (Bug 4 already fixed iter25 α-25) |
| HEVC | byte-equal to SW (10 frames) | **PASS** (Bug 5 NOW FIXED iter31 α-29) |
| VP9 | byte-equal to SW (10 frames) | **PASS** (unchanged) |
| MPEG-2| untestable through libva | pre-existing single-device probe limitation |
| VP8 | untestable through libva | same |
### Root cause: wrong V4L2 field
α-26 had set `decode_params->short_term_ref_pic_set_size = picture->st_rps_bits` based on the FIELD NAME. But `picture->st_rps_bits` from VAAPI is documented as the bit-count of `short_term_ref_pic_set()` in the **slice segment header** (per `/usr/include/va/va_dec_hevc.h:177-185`). The V4L2 SLICE-PARAMS field of the same name is what rkvdec reads. The V4L2 DECODE-PARAMS field with this name (where α-26 wrote it) refers to the SPS-side bit count, which rkvdec does not use.
`rkvdec_hevc.c::assemble_sw_rps` (lines 386-389) reads `sl_params->short_term_ref_pic_set_size`:
```c
if (!(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC)) {
if (sl_params->short_term_ref_pic_set_size)
st_bit_offset = sl_params->short_term_ref_pic_set_size;
else if (sps->num_short_term_ref_pic_sets > 1)
st_bit_offset = fls(sps->num_short_term_ref_pic_sets - 1);
}
```
For BBB's `num_short_term_ref_pic_sets == 1`, the fallback (`fls(0) = 0`) is wrong — the HW reads slice-header bits from offset 0, treats the st_ref_pic_set() bytes as long-term-RPS / slice-header continuation, and the entropy decoder spins onto garbage state for every non-IDR slice. IDR is gated out by `V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC` → frame 1 unaffected → consistent with prior iter25 "frame 1 PASS, frame 2+ FAIL" observation.
### Fix: α-29
```c
// src/h265.c::h265_fill_slice_params, line 476:
- slice_params->short_term_ref_pic_set_size = 0; /* VAAPI doesn't expose */
+ slice_params->short_term_ref_pic_set_size = picture->st_rps_bits;
```
Backend commit `23eb1bd`. Build, deploy, re-test → 10/10 PASS for HEVC.
### Investigation path
- **iter29** added env-gated dump of last 80 bytes of HEVC slice_data. Trailing 80 bytes look like real entropy — refuted the "40-byte ffmpeg-vaapi inflation" hypothesis from iter27/28 close.
- **iter30** added `LIBVA_TS_SCALE` env-gated timestamp multiplier. Tested scales 1/1000/1000000. All produced identical (wrong) frame-2 output. Refuted timestamp-magnitude hypothesis.
- **iter31** extended kernel iter27 printk to dump `dpb[2..3]` (offsets 96..128) and `sl[32..64]`. Direct libva-vs-kdirect comparison for POC=1 (display frame 2, decode #4) revealed all slice_params[0..64] bytes match EXCEPT `num_entry_point_offsets` (known unused by rkvdec). Re-reading rkvdec's assemble_sw_rps located the `sl_params->short_term_ref_pic_set_size` read site, then traced backward to ffmpeg-v4l2request's `sh->short_term_ref_pic_set_size` source. VAAPI's `picture->st_rps_bits` is the semantic equivalent.
### Substrate state at iter31 close
- Backend fork tip `23eb1bd` (α-25 through α-29 + iter29 dump + iter30 ts-scale env probes; α-29 is the load-bearing fix; others are env-gated and inactive by default).
- Kernel `7.0-10` with iter17 + iter20 + iter21 + iter22 + iter23 + iter27 + iter31 printks (production kernel would revert all these — outstanding cleanup item).
- 5-codec status: 3 PASS, 2 untestable. MPEG-2/VP8 reachability requires libva multi-device-probe rework (separate iter — orthogonal to Bug 4/5).
### Campaign milestone
Bug 4 fix landed iter25 α-25. Bug 5 frame 1 fix landed same iter25 α-25. Bug 5 remainder (frames 2+) localized over iter26-28 (correctly: rkvdec reads field X, libva sends 0), mis-fixed in α-26 (right value, wrong field), refuted in iter29-30 (rule-outs), correctly fixed in α-29 (right value to right field). Total: 1 day for full pixel correctness across the three rkvdec-routed codecs.
### Memory entries to update
- `feedback_rkvdec_image_fmt_pre_seed.md` — note the remainder-fix landed (no longer "deferred").
- `feedback_libva_byte_correct_kernel_bug.md` — fully overturned now (Bug 5 is fully a libva-side fix, not kernel-side).
- New: `feedback_va_st_rps_bits_is_slice_field.md` — VAAPI's picture->st_rps_bits goes into slice_params not decode_params (the field NAME is identical, semantics differ).