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>
This commit is contained in:
@@ -0,0 +1,230 @@
|
|||||||
|
# Iteration 2 — Phase 5 (second-model review)
|
||||||
|
|
||||||
|
Sonnet-architect review of the iter2 plan, run 2026-05-08 via `Plan` subagent with `model: sonnet` per [`feedback_dev_process.md`](../../.claude/projects/-home-mfritsche-src/memory/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 has more concrete-and-wrong claims about kernel UAPI struct field names (C1, C2 in particular).
|
||||||
|
|
||||||
|
Per [`memory/feedback_review_empirical_over_theoretical.md`](../../.claude/projects/-home-mfritsche-src-fresnel-fourier/memory/feedback_review_empirical_over_theoretical.md): every finding the reviewer cited concretely was **verified empirically** against fresnel's kernel UAPI before responding. Reviewer was right on every verifiable claim. Lesson held.
|
||||||
|
|
||||||
|
The full review verbatim is preserved in the agent transcript; my response per finding follows.
|
||||||
|
|
||||||
|
## Critical findings — all 3 confirmed
|
||||||
|
|
||||||
|
### C1 — `data_byte_offset` not `data_bit_offset`; drop the bit-search logic
|
||||||
|
|
||||||
|
**Verdict**: ✅ accepted, plan is wrong. Empirical verification (`ssh fresnel 'awk "/^struct v4l2_ctrl_hevc_slice_params/,/^};/" /usr/include/linux/v4l2-controls.h'`):
|
||||||
|
|
||||||
|
```c
|
||||||
|
struct v4l2_ctrl_hevc_slice_params {
|
||||||
|
__u32 bit_size;
|
||||||
|
__u32 data_byte_offset; /* NOT data_bit_offset! */
|
||||||
|
__u32 num_entry_point_offsets;
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Plan Clause 4 said: "the new V4L2 API still requires per-slice `bit_size` and `data_bit_offset`. **This logic is preserved** — the new struct keeps these fields (they're per-slice metadata, not per-frame)."
|
||||||
|
|
||||||
|
**That claim is incorrect.** The new struct keeps `bit_size` but renames `data_bit_offset` to `data_byte_offset`. The current `src/h265.c:184-209` performs an 8-bit search to compute a bit-granularity offset (the slice-segment-header NALU start bit position), then stores it in `slice_params->data_bit_offset`. That field name doesn't compile against the new struct.
|
||||||
|
|
||||||
|
FFmpeg's reference at `libavcodec/v4l2_request_hevc.c:190` sets `.data_byte_offset = controls->pic.output->bytesused + sh->data_offset` — a plain byte offset, no bit search.
|
||||||
|
|
||||||
|
**Plan amendment to Clause 4**:
|
||||||
|
|
||||||
|
> Drop the bit-search logic at h265.c:196-209. Replace with byte-offset assignment:
|
||||||
|
>
|
||||||
|
> ```c
|
||||||
|
> slice_params->data_byte_offset = surface_object->slices_size + slice->slice_data_byte_offset;
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> (or `slice->slice_data_offset + slice->slice_data_byte_offset`, depending on libva semantics — Phase 6 source-read of how `slice_data_byte_offset` is computed by VAAPI consumers will clarify; FFmpeg's pattern is the authority).
|
||||||
|
>
|
||||||
|
> The bit-granularity start-bit search is no longer needed — kernel HEVC decoder finds the slice header start from the byte offset and standard NAL unit boundaries.
|
||||||
|
|
||||||
|
### C2 — `dpb[].rps` field GONE; `pic_order_cnt_val` rename; `poc_st_curr_*` arrays hold DPB indices
|
||||||
|
|
||||||
|
**Verdict**: ✅ accepted, plan is wrong on three sub-claims. Empirical verification:
|
||||||
|
|
||||||
|
```c
|
||||||
|
struct v4l2_hevc_dpb_entry {
|
||||||
|
__u64 timestamp;
|
||||||
|
__u8 flags; /* only V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE = 0x01 */
|
||||||
|
__u8 field_pic;
|
||||||
|
__u16 reserved;
|
||||||
|
__s32 pic_order_cnt_val; /* singular, NOT pic_order_cnt[0] */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE 0x01
|
||||||
|
/* No V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE/AFTER/LT_CURR */
|
||||||
|
```
|
||||||
|
|
||||||
|
The current `src/h265.c:292-304` writes:
|
||||||
|
|
||||||
|
```c
|
||||||
|
slice_params->dpb[i].rps = V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE; /* etc. */
|
||||||
|
...
|
||||||
|
slice_params->dpb[i].pic_order_cnt[0] = hevc_picture->pic_order_cnt;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Three sub-claims wrong**:
|
||||||
|
|
||||||
|
1. **`.rps` field is gone**. The new `v4l2_hevc_dpb_entry` has only `flags` (with `LONG_TERM_REFERENCE` as the sole defined bit). The per-entry classification ST_CURR_BEFORE / ST_CURR_AFTER / LT_CURR is now expressed via the `poc_st_curr_before[16]`, `poc_st_curr_after[16]`, `poc_lt_curr[16]` arrays in **DECODE_PARAMS**.
|
||||||
|
2. **`.pic_order_cnt[0]` is renamed `pic_order_cnt_val`**, singular `__s32`.
|
||||||
|
3. **The `poc_st_curr_*` arrays hold DPB INDICES (u8), not POC values**. FFmpeg's reference `v4l2_request_hevc.c:168-175` calls `get_ref_pic_index()` which searches `dpb[]` by timestamp and returns the index, then stores that index in `poc_st_curr_before[i]`.
|
||||||
|
|
||||||
|
So the logic must be:
|
||||||
|
|
||||||
|
(a) Classify each VAAPI `picture->ReferenceFrames[i]` as ST_CURR_BEFORE/AFTER/LT_CURR via `flags & VA_PICTURE_HEVC_RPS_*`.
|
||||||
|
(b) Set `dpb[j].flags = V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE` IFF the ref is a long-term ref.
|
||||||
|
(c) Set `dpb[j].pic_order_cnt_val = hevc_picture->pic_order_cnt`.
|
||||||
|
(d) For each ref, compute its DPB index `j`, append to the right array (`poc_st_curr_before[k++] = j`, etc.) based on classification.
|
||||||
|
|
||||||
|
Plan claim "DPB extraction logic migrates verbatim" is wrong. The migration is more nuanced — FFmpeg pattern via `get_ref_pic_index()` is the canonical implementation.
|
||||||
|
|
||||||
|
**Plan amendment to Clause 6**: replace "preserves existing extraction logic from current src/h265.c lines 269-315" with explicit re-spec:
|
||||||
|
|
||||||
|
> Reference frames are classified into three lists by their VA_PICTURE_HEVC flags: ST_CURR_BEFORE (forward refs in display order), ST_CURR_AFTER (backward refs), LT_CURR (long-term refs). For each VAAPI ReferenceFrame[i] that's valid (not VA_PICTURE_HEVC_INVALID, not VA_INVALID_SURFACE):
|
||||||
|
>
|
||||||
|
> 1. Lookup its surface_object via `SURFACE(driver_data, hevc_picture->picture_id)`.
|
||||||
|
> 2. Determine its DPB-array index `j` (the position it occupies in the kernel-side dpb[] array — assign sequentially).
|
||||||
|
> 3. Set `decode_params.dpb[j].timestamp = v4l2_timeval_to_ns(&surface->timestamp)`.
|
||||||
|
> 4. Set `decode_params.dpb[j].pic_order_cnt_val = hevc_picture->pic_order_cnt`.
|
||||||
|
> 5. Set `decode_params.dpb[j].flags = (hevc_picture->flags & VA_PICTURE_HEVC_RPS_LT_CURR) ? V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE : 0`.
|
||||||
|
> 6. Set `decode_params.dpb[j].field_pic = (hevc_picture->flags & VA_PICTURE_HEVC_FIELD_PIC) ? 1 : 0`.
|
||||||
|
> 7. Append `j` to `poc_st_curr_before[k]++` if VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE; `_after[k]++` if RPS_ST_CURR_AFTER; `_lt_curr[k]++` if RPS_LT_CURR.
|
||||||
|
>
|
||||||
|
> `decode_params.num_active_dpb_entries`, `num_poc_st_curr_before`, `num_poc_st_curr_after`, `num_poc_lt_curr` are then the counts.
|
||||||
|
|
||||||
|
This is a new piece of code, not a verbatim migration. Phase 6 implementer notes the rewrite scope.
|
||||||
|
|
||||||
|
### C3 — Union-aliasing reasoning wrong (again, like iter1 C1)
|
||||||
|
|
||||||
|
**Verdict**: ✅ accepted, my reasoning was wrong; the safety claim itself holds.
|
||||||
|
|
||||||
|
Plan said the unconditional `params.h265.num_slices = 0` reset at BeginPicture is "benign for non-HEVC since the union aliasing puts num_slices in a region overwritten by RenderPicture's per-buffer copies." The reviewer's verification (and my offsetof check during this phase) confirms `num_slices` lands at byte ~17764 of the union after the `slices[64]` insertion — well past any H.264 (max 240) or MPEG-2 (max 376) field. **Non-H.264/MPEG-2 paths never touch byte 17764**; the reset is benign because of non-aliasing, not because of overwriting.
|
||||||
|
|
||||||
|
Same anti-pattern as iter1 review C1: I wrote a hand-wavy union-aliasing argument that turned out to be wrong-mechanism but right-conclusion. Lesson reinforced (but already in [`feedback_review_empirical_over_theoretical.md`](../../.claude/projects/-home-mfritsche-src-fresnel-fourier/memory/feedback_review_empirical_over_theoretical.md) — both reviews now have an example of the same trap).
|
||||||
|
|
||||||
|
**Plan amendment to Clause 10**: replace the wording with "after `slices[64]` insertion, `num_slices` lands at byte ~17764, well past any H.264 (≤240) or MPEG-2 (≤376) field. The reset is benign for non-HEVC because no other profile reads union byte 17764, NOT because RenderPicture per-buffer copies overwrite that location."
|
||||||
|
|
||||||
|
## Should-fix findings — all 4 confirmed
|
||||||
|
|
||||||
|
### S1 — Two PPS flags missing from Clause 3 mapping
|
||||||
|
|
||||||
|
**Verdict**: ✅ accepted. Empirical verification:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL << 19)
|
||||||
|
#define V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL << 20)
|
||||||
|
```
|
||||||
|
|
||||||
|
Plan Clause 3 listed bits 0-18, missed 19+20. BBB likely doesn't trigger them (single-tile, default deblocking) but the mapping is incomplete.
|
||||||
|
|
||||||
|
**Plan amendment to Clause 3**: add to the PPS flags table:
|
||||||
|
|
||||||
|
| Flag bit | New name | VAAPI source |
|
||||||
|
|---|---|---|
|
||||||
|
| 19 | `_DEBLOCKING_FILTER_CONTROL_PRESENT` | `picture->slice_parsing_fields.bits.deblocking_filter_control_present_flag` (or implied — VAAPI may not expose directly; in that case set 1 if PPS was decoded with deblocking-filter overrides allowed) |
|
||||||
|
| 20 | `_UNIFORM_SPACING` | `picture->pic_fields.bits.uniform_spacing_flag` |
|
||||||
|
|
||||||
|
Phase 7 byte-compare on PPS bytes will catch silent zeroing.
|
||||||
|
|
||||||
|
### S2 — Three PPS scalar fields missing from source mapping
|
||||||
|
|
||||||
|
**Verdict**: ✅ accepted. PPS struct dump on fresnel:
|
||||||
|
|
||||||
|
```c
|
||||||
|
struct v4l2_ctrl_hevc_pps {
|
||||||
|
__u8 pic_parameter_set_id; /* iter1 plan missed */
|
||||||
|
__u8 num_extra_slice_header_bits;
|
||||||
|
__u8 num_ref_idx_l0_default_active_minus1; /* iter1 plan missed */
|
||||||
|
__u8 num_ref_idx_l1_default_active_minus1; /* iter1 plan missed */
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
The old staging-era `v4l2_ctrl_hevc_pps` didn't have these fields; new one does. Without explicit fill, the `memset(&pps, 0, ...)` will leave them zero — probably correct for BBB but not guaranteed.
|
||||||
|
|
||||||
|
**Plan amendment to Clause 3**: add to source mapping:
|
||||||
|
|
||||||
|
| New PPS field | Source |
|
||||||
|
|---|---|
|
||||||
|
| `pic_parameter_set_id` | 0 (single-PPS streams; VAAPI doesn't expose) |
|
||||||
|
| `num_ref_idx_l0_default_active_minus1` | `picture->num_ref_idx_l0_default_active_minus1` |
|
||||||
|
| `num_ref_idx_l1_default_active_minus1` | `picture->num_ref_idx_l1_default_active_minus1` |
|
||||||
|
|
||||||
|
### S3 — SCALING_MATRIX content divergence between FFmpeg and libva paths
|
||||||
|
|
||||||
|
**Verdict**: ✅ accepted as Phase 6 implementer's choice. FFmpeg at `v4l2_request_hevc.c:384-403` populates from the active scaling list pointer `sl`; if `sl == NULL` (BBB has no scaling list per SPS flags), FFmpeg's struct stays memset-zero. Plan's "populate spec defaults" branch would produce non-zero default matrices instead.
|
||||||
|
|
||||||
|
**Phase 7 byte-compare consequence**: if Phase 6 implements "spec defaults when iqmatrix_set==false," Baseline B compare will diverge on SCALING_MATRIX bytes. Two response paths:
|
||||||
|
|
||||||
|
(a) Implement matching FFmpeg: send zeros when no scaling list (preserves byte-equality vs cross-validator).
|
||||||
|
|
||||||
|
(b) Implement spec defaults (semantically purer; kernel may handle either).
|
||||||
|
|
||||||
|
**Plan amendment to Clause 5**: defer to Phase 6 implementer; flag in commit message which path was chosen and why. Phase 7 byte-compare will validate via decode-correctness of the result regardless of which path matches Baseline B exactly.
|
||||||
|
|
||||||
|
### S4 — Wrong FFmpeg function name cited
|
||||||
|
|
||||||
|
**Verdict**: ✅ accepted, cosmetic fix.
|
||||||
|
|
||||||
|
Plan Clause 5 cited `ff_v4l2_request_query_control_default_value`. The actual FFmpeg call at `v4l2_request_hevc.c:677` is `ff_v4l2_request_query_control(avctx, &scaling_matrix)`. Same intent (probe control existence), different function name.
|
||||||
|
|
||||||
|
**Plan amendment to Clause 5**: fix the citation. (No semantic change.)
|
||||||
|
|
||||||
|
## Question / clarification — all 3 verified
|
||||||
|
|
||||||
|
### Q1 — `object_heap` allocator handles new union size automatically
|
||||||
|
|
||||||
|
**Verdict**: ✅ verified. `src/request.c:142-143`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
object_heap_init(&driver_data->surface_heap,
|
||||||
|
sizeof(struct object_surface), SURFACE_ID_OFFSET);
|
||||||
|
```
|
||||||
|
|
||||||
|
`object_heap_init` is parameterized on `sizeof(struct object_surface)` — automatic pickup of the larger size after `slices[64]` insertion. No hardcoded constant to update.
|
||||||
|
|
||||||
|
### Q2 — `slice_segment_addr` field present in new API; must be populated
|
||||||
|
|
||||||
|
**Verdict**: ✅ verified. `slice_segment_addr` (u32) is in the new `v4l2_ctrl_hevc_slice_params` struct dump. Current `src/h265.c::h265_fill_slice_params` does NOT populate it. For multi-slice frames, omission would cause kernel decode error or wrong pixel output. For single-slice BBB, the implicit zero is correct (first slice is at address 0).
|
||||||
|
|
||||||
|
**Plan amendment to Clause 4**: add field to source mapping:
|
||||||
|
|
||||||
|
| `slice_params.slice_segment_addr` | `slice->slice_segment_address` (VAAPI exposes this directly) |
|
||||||
|
|
||||||
|
### Q3 — VAPictureParameterBufferType per-frame send for HEVC unverified
|
||||||
|
|
||||||
|
**Verdict**: deferred to Phase 7 LIBVA_TRACE capture. iter1+T4 patterns suggest yes, but worth grepping the trace for `va_TraceRenderPicture.*VAPictureParameterBufferType` per frame at Phase 7 verification.
|
||||||
|
|
||||||
|
## Nits — all 3 noted
|
||||||
|
|
||||||
|
### N1 — Array size description wrong
|
||||||
|
|
||||||
|
Plan Clause 6 said `poc_st_curr_before[8]` etc. Actual kernel UAPI uses `[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]` = `[16]`. Plan amendment: use the macro reference, value 16.
|
||||||
|
|
||||||
|
### N2 — Phase 7 harness directory naming inconsistent
|
||||||
|
|
||||||
|
`/tmp/iter2_phase7/png_hw/*.jpg` — the directory is named "png" but mpv writes JPEG. Cosmetic; plan amendment: rename `png_hw` → `image_hw` (or similar) in Phase 7 commands. Functionally no-op.
|
||||||
|
|
||||||
|
### N3 — BeginPicture unconditional reset cleanup deferred
|
||||||
|
|
||||||
|
Plan Clause 10 adds `params.h265.num_slices = 0` unconditional. Same pattern as the existing `params.h264.matrix_set = false`. Future cleanup: profile-aware reset (per Phase 4 cross-cutting backlog item B3 from iter1 close). No iter2 action.
|
||||||
|
|
||||||
|
## Plan amendments consolidated
|
||||||
|
|
||||||
|
After Phase 5, the iter2 plan stands as authored in [`phase4_iter2_plan.md`](phase4_iter2_plan.md), with the following amendments:
|
||||||
|
|
||||||
|
1. **Clause 4 (slice_params)**: drop bit-search; use `data_byte_offset` (NOT `data_bit_offset`); add `slice_segment_addr` field population from `slice->slice_segment_address` (C1 + Q2).
|
||||||
|
2. **Clause 6 (decode_params)**: replace "verbatim migration" with explicit DPB classification + index-array population logic; rename `pic_order_cnt[0]` → `pic_order_cnt_val`; drop `dpb[].rps` (use `dpb[].flags & LONG_TERM_REFERENCE` for long-term classification only); populate `poc_st_curr_before/after/lt_curr` arrays with DPB indices via FFmpeg `get_ref_pic_index()` pattern (C2).
|
||||||
|
3. **Clause 3 (PPS)**: add 2 missing flags (bits 19, 20) and 3 missing scalars (`pic_parameter_set_id`, `num_ref_idx_l0/l1_default_active_minus1`) (S1, S2).
|
||||||
|
4. **Clause 5 (SCALING_MATRIX)**: fix function name `ff_v4l2_request_query_control` (S4); flag the FFmpeg-vs-libva default-fill divergence as a Phase 6 implementer choice (S3).
|
||||||
|
5. **Clause 10 (per-slice accumulation)**: fix the union-aliasing reasoning wording — benign because non-HEVC profiles don't read byte 17764, NOT because RenderPicture overwrites it (C3).
|
||||||
|
6. **Clause 6 (array sizes)**: use `V4L2_HEVC_DPB_ENTRIES_NUM_MAX` (= 16) macro reference, not hardcoded `[8]` (N1).
|
||||||
|
7. **Phase 7 harness**: rename `png_*` directories → `image_*` for cosmetic clarity (N2).
|
||||||
|
8. **Q3 deferred**: Phase 7 LIBVA_TRACE capture confirms VAPictureParameterBufferType per-frame send for HEVC.
|
||||||
|
|
||||||
|
Plan re-locks with these amendments. Phase 6 proceeds.
|
||||||
|
|
||||||
|
## Phase 5 close
|
||||||
|
|
||||||
|
Per `feedback_dev_process.md` Phase 5: review handed over to sonnet-architect (Plan agent), 13 findings surfaced, 7 substantive amendments accepted. Critical findings C1 + C2 would have been compile errors (`data_bit_offset` undefined in struct) or silent semantic bugs (`dpb.rps` undefined; pic_order_cnt struct shape wrong). The reviewer's outside-look saved Phase 6/7 from at least 2 loopback cycles.
|
||||||
|
|
||||||
|
Per [`memory/feedback_review_empirical_over_theoretical.md`](../../.claude/projects/-home-mfritsche-src-fresnel-fourier/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. Lesson held this iteration. Phase 6 implementer can now proceed against an amended plan that compiles against the actual kernel UAPI on first try.
|
||||||
Reference in New Issue
Block a user