Files
fresnel-fourier/phase5_iter5b_review.md
T
marfrit 7d1c44bd90 iter5b Phase 5: review — CRIT-1 mechanical pseudocode fix, 3 IMP amendments
Sonnet-architect found one Critical pseudocode error and three
Important amendments. All mechanical; no structural plan change.

CRIT-1: Phase 4 C2 pseudocode used non-existent
`struct object_heap_iterator`. Actual API at object_heap.h:67-68 uses
`int *iterator`. Author re-verified vs request.c:411-418 canonical
usage. Verbatim paste would have compile-failed.

IMP-1: gate comment at surface.c:178-195 should mention codec/profile
change alongside resolution change.

IMP-2: dead `object_config->pixelformat` field at config.h:46 — accept
option (a): wire up at CreateConfig, return directly from heap walk.
Saves one pixelformat_for_profile() call in surface.c path.

IMP-3: characterize hantro mechanism precisely — substitution to
default MPEG2_DECODER codec_mode, not rejection. Explains why MPEG-2
worked but VP8 didn't pre-fix.

10 contract clauses scorecard: 1 FAIL (C2), 2 CONDITIONAL (C3, C10),
7 PASS. Phase 6 cleared conditionally pending all 4 amendments.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 08:04:38 +00:00

214 lines
13 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 5b — Phase 5 (review)
Phase 5 architect review of `phase4_iter5b_plan.md` by sonnet-architect, 2026-05-12. Empirical-over-theoretical and trace-fix-mechanism-to-consumer disciplines applied. Source files read: `surface.c` (135380), `config.c` (1194), `context.c` (49227), `object_heap.h`, `object_heap.c` (150200), `request.h` (50107), `request.c` (354424), `config.h`, `meson.build`. Remote source read of `hantro_v4l2.c` on boltzmann's linux-rockchip v7.0 tree.
**Overall plan health**: Option α' choice over option β is defensible. 10 contract clauses are individually well-scoped. One Critical pseudocode error (compile failure if pasted verbatim). Three Important amendments improve accuracy without changing structure. Seven Non-Amendment findings confirm the plan is otherwise correct.
## Critical findings (BLOCKING Phase 6)
### CRIT-1 — Iterator type mismatch: pseudocode uses non-existent `struct object_heap_iterator`
**Plan's C2 pseudocode** declares:
```c
struct object_heap_iterator iter;
struct object_base *iter_obj;
iter_obj = object_heap_first(&driver_data->config_heap, &iter);
```
**Actual API** at `object_heap.h:6768`:
```c
struct object_base *object_heap_first(struct object_heap *heap, int *iterator);
struct object_base *object_heap_next(struct object_heap *heap, int *iterator);
```
The iterator parameter is `int *`, not a struct pointer. `struct object_heap_iterator` does not exist anywhere in the codebase. The C2 pseudocode will fail to compile.
**Reference usage** at `request.c:411418` (the canonical pattern):
```c
int iterator;
config_object = (struct object_config *)
object_heap_first(&driver_data->config_heap, &iterator);
while (config_object != NULL) {
...
config_object = (struct object_config *)
object_heap_next(&driver_data->config_heap, &iterator);
}
```
**Required amendment to C2**:
```c
static VAProfile find_sole_active_profile(struct request_data *driver_data)
{
VAProfile found = VAProfileNone;
int seen = 0;
int iter;
struct object_config *config_object;
config_object = (struct object_config *)
object_heap_first(&driver_data->config_heap, &iter);
while (config_object != NULL) {
if (seen == 0)
found = config_object->profile;
seen++;
config_object = (struct object_config *)
object_heap_next(&driver_data->config_heap, &iter);
}
if (seen == 1)
return found;
if (seen > 1)
request_log("CreateSurfaces2: %d active configs, profile-pick ambiguous; falling back to default OUTPUT format\n",
seen);
return VAProfileNone;
}
```
**Verdict**: Mechanical fix, but it would have been a Phase 6 compile failure that wasted a `meson compile` cycle. Phase 5 caught it. Phase 6 implementer pastes the corrected version above.
## Important findings (incorporate into plan before Phase 6)
### IMP-1 — Gate comment should mention codec/profile change alongside resolution change
The existing comment at `surface.c:178195` explains the teardown branch in terms of resolution change ("If we've previously allocated buffers at a different resolution"). C5 extends the gate predicate to fire on pixelformat change too, but the comment is now incomplete.
**Resolution**: Phase 6 amends the comment to say "If we've previously allocated buffers at a different resolution or codec, tear them down on BOTH queues before re-setting the OUTPUT format." Two-line change, mechanical.
### IMP-2 — Dead `object_config->pixelformat` field at config.h:46 creates a maintenance trap
`config.h:46` declares `unsigned int pixelformat;` in `struct object_config`. `grep -n "pixelformat" config.c` returns no assignment hits. The field has been dead scaffolding since some prior iteration.
The plan's C5 adds `last_output_pixelformat` to `struct request_data` instead. That's defensible — driver_data tracks "current V4L2 device state"; config tracks "what config wants." Distinct semantics.
**Recommended amendment**: Either (a) wire up the dead field at CreateConfig (`config_object->pixelformat = pixelformat_for_profile(profile)`) — costs zero LOC if done alongside C1, makes the field meaningful, and the heap walk can use `config_object->pixelformat` directly instead of calling `pixelformat_for_profile()` again; OR (b) add `/* DEAD — see request_data::last_output_pixelformat */` comment at config.h:46.
Option (a) is the cleaner fix. Recommended.
### IMP-3 — MPEG-2/VP8 hantro mechanism: substitution, not rejection
The plan's commit-message language ("kernel silently rejected the format/control mismatch") is imprecise. Empirical read of `hantro_v4l2.c` (boltzmann's v7.0 tree, `drivers/media/platform/verisilicon/hantro_v4l2.c::hantro_try_fmt`):
- `S_FMT(OUTPUT, H264_SLICE)` on hantro → `hantro_find_format` returns NULL (H264_SLICE not in `rk3399_vpu_dec_fmts`) → `hantro_try_fmt` substitutes the default = `MPEG2_SLICE``ctx->vpu_src_fmt->codec_mode = MPEG2_DECODER`.
- For MPEG-2 fixture: bitstream is MPEG-2 + controls dispatched to MPEG2 ops → decode succeeds (modulo timing).
- For VP8 fixture: bitstream is VP8 but `codec_mode = MPEG2_DECODER` → VP8 controls dispatched to MPEG2 ops → undefined behavior → all-zero output.
This is **more precise** than "format mismatch rejected" — the kernel doesn't reject, it silently substitutes a default codec_mode and dispatches into the wrong codec ops path. The fix (correct OUTPUT format per profile) makes hantro pick the right codec_mode.
**Recommended amendment**: update commit message body for the Phase 6 commit to use the precise framing. Update `phase0_iter5_loopback.md` taxonomy note in passing.
## Non-amendment findings (plan is correct)
### NC-1 — Helper completeness (concern 1): PASS
`pixelformat_for_profile()` in C1 covers every profile enumerated at `config.c:131194`:
| Profile (config.c enumerated) | C1 mapping |
|---|---|
| VAProfileMPEG2{Simple,Main} → MPEG2_SLICE | ✓ |
| VAProfileH264{Main,High,ConstrainedBaseline,MultiviewHigh,StereoHigh} → H264_SLICE | ✓ |
| VAProfileHEVCMain → HEVC_SLICE | ✓ |
| VAProfileVP8Version0_3 → VP8_FRAME | ✓ |
| VAProfileVP9Profile0 → VP9_FRAME | ✓ |
`default: return 0` correctly signals unknown.
### NC-2 — Heap iterator API (concern 2): SEE CRIT-1
API exists; type is wrong in pseudocode. Already covered above.
### NC-3 — `request_log` symbol available in surface.c: PASS
`utils.h` already included at `surface.c:46`. No new include needed.
### NC-4 — `VAProfileNone = -1` fallback: PASS
`va.h:495` defines it. `pixelformat_for_profile(VAProfileNone)` hits `default: return 0`. Caller's `if (pixelformat == 0)` branch correctly fires. Fallback to H264_SLICE preserves pre-iter5b behavior for the pathological case.
### NC-5 — `meson.build` update (C6): PASS
`meson.build:3053` (sources) and `:5578` (headers) both omit codec.c / codec.h. C6 correctly identifies both list edits.
### NC-6 — Option α' vs β choice (concern 7): DEFENSIBLE
The surface.c:164171 TODO comment specifically targets "consumers that legitimately stream multiple resolutions in sequence" — multi-resolution mid-stream, not iter5b's initial-CreateSurfaces case. Option α' addresses iter5b's bug without invoking the deferred-redesign flag.
### NC-7 — mpv probe-then-real flow (concern 5): SAFE
Pre-CreateConfig probe surfaces (128×128) hit VAProfileNone → fallback H264_SLICE → probe CAPTURE allocated. CreateConfig(HEVC) → real CreateSurfaces2 → find_sole_active_profile returns VAProfileHEVCMain → gate fires on both width/height AND pixelformat change → teardown destroys probe buffers → S_FMT(HEVC_SLICE) → correct allocation. Empirically: same teardown path as the mpv resolution-change case the existing code already exercises (surface.c:196223).
### NC-8 — Multi-config fallback safety (concern 8): SAFE
Gate fires on pixelformat change at the eventual CreateContext → re-S_FMT corrects the format before the consumer actually decodes. The brief window between probe and real CreateSurfaces uses H264_SLICE buffers that are torn down before any decode. No silent corruption path.
### NC-9 — Phase 7 hash stability (concern 10): SOUND
Phase 3 baseline verified `kdirect == sw` byte-identity. The hwdownload pipeline (`ffmpeg -f rawvideo -pix_fmt yuv420p`) is deterministic for stateless decode. Re-running the sweep on unchanged kernel + fixtures produces identical hashes. Target hashes `9340b832…` / `4f1565e8…` / `136ce5cb…` stable.
### NC-10 — Memory rule placement (concern 6): RECOMMENDATION
Best path: extend `feedback_unconditional_codec_state.md` with the pixel format instance as a second case (start codes + pixel formats are the same bug class), AND add a new `feedback_va_lifecycle_profile_threading.md` for the specific VA-API-CreateSurfaces-has-no-config_id observation. The lessons are sibling but distinct.
## Summary scorecard
| Clause | Status | Finding |
|---|---|---|
| C1 (codec.h/codec.c helper) | PASS | Complete profile coverage |
| C2 (find_sole_active_profile) | **FAIL** | CRIT-1: iterator type wrong; fix per amendment above |
| C3 (use helper at surface.c:173) | CONDITIONAL | Depends on C2 fix |
| C4 (#include "codec.h") | PASS | utils.h already provides request_log |
| C5 (driver_data field + gate extension) | PASS | Gate semantics correct; comment needs IMP-1 amendment |
| C6 (meson.build) | PASS | Both sources + headers lists need edit |
| C7 (Phase 7 verification matrix) | PASS | Hashes stable; methodology sound |
| C8 (build + install) | PASS | Backend-only; commands correct |
| C9 (control-payload anchor regression) | PASS | Optional but cheap |
| C10 (Phase 8 close) | CONDITIONAL | Depends on C2 fix; memory rule update per NC-10 |
**Phase 6 cleared, conditional on incorporating CRIT-1 fix + IMP-1 comment update + IMP-2 dead-field resolution + IMP-3 commit-message precision.** All amendments are mechanical; no structural plan changes.
## Author re-verification (post-review, 2026-05-12)
Per `feedback_review_empirical_over_theoretical.md` Direction 2:
### CRIT-1 — CONFIRMED
`object_heap.h:67-68` empirically shows iterator parameter is `int *`. `request.c:411-418` empirically shows the canonical usage pattern. My Phase 4 pseudocode invented `struct object_heap_iterator` — classic theoretical-code-without-empirical-grounding error. Phase 5 caught what Phase 4 would have wasted a `meson compile` cycle on.
### IMP-1 — CONFIRMED
Comment update is trivially correct.
### IMP-2 — CONFIRMED + ACCEPTING OPTION (a)
`grep -n "pixelformat" config.c` empirically returns no hits. The dead field needs either wiring up or commenting. Option (a) is cleaner — wire up at CreateConfig. Phase 6 incorporates: `config_object->pixelformat = pixelformat_for_profile(profile)` at CreateConfig, and `find_sole_active_profile` returns `config_object->pixelformat` directly (saves one `pixelformat_for_profile()` call in the surface.c path).
### IMP-3 — CONFIRMED
The reviewer's mechanism description (hantro substitutes default = MPEG2_SLICE, dispatches to MPEG2 codec_mode ops) is empirically correct per `hantro_v4l2.c::hantro_find_format` + `hantro_try_fmt` + `rk3399_vpu_dec_fmts` ordering. Phase 6 commit message uses the precise framing.
## Phase 5 review track-record acknowledgment
| ID | Finding | Author verification | Status |
|---|---|---|---|
| CRIT-1 | `struct object_heap_iterator` doesn't exist; type is `int` | Empirical: object_heap.h:67-68 + request.c:411-418 confirm | **CORRECT, BLOCKING** |
| IMP-1 | Gate comment should mention codec/profile change | Trivial; correct | **CORRECT** |
| IMP-2 | Dead `object_config->pixelformat` field at config.h:46 | Empirical grep confirms no assignment; accept option (a) | **CORRECT** |
| IMP-3 | Hantro substitutes (doesn't reject); dispatches wrong codec_mode | Reviewer cited hantro_v4l2.c flow; consistent with my Phase 0 loopback observation that MPEG-2 worked but VP8 didn't | **CORRECT** |
| NC-1..NC-10 | Plan correct on the 10 non-amendment fronts | Spot-checked; all confirmed | **CORRECT** |
All findings empirically correct. The reviewer caught a compile-failing pseudocode error before Phase 6 burned a build cycle on it. Estimated savings: 1 failed `meson compile` cycle (~30 seconds) + 1 mental-context-switch correction. Cheaper than iter5 Phase 5's CRIT-1 (which would have wasted a kernel build), but the same shape of catch.
## Phase 4 amendments to land before Phase 6
1. **C2 pseudocode**: replace iterator-type-and-loop with the corrected snippet above. Use `int iter;` and cast-on-return pattern from request.c:411-418.
2. **C5 comment**: amend the surface.c:178-195 explanatory block to say "If we've previously allocated buffers at a different resolution **or codec**, tear them down…"
3. **C1 wiring**: at `RequestCreateConfig` (config.c), add `config_object->pixelformat = pixelformat_for_profile(profile);` after the existing config_object allocation. This wires up the dead field at config.h:46.
4. **C2 simplification**: `find_sole_active_profile` returns `config_object->pixelformat` directly (FOURCC), not the VAProfile. Rename to `find_sole_active_pixelformat` for accuracy. Surface.c caller skips the second `pixelformat_for_profile()` call.
5. **Phase 6 commit message** (when the actual commit lands): use IMP-3's precise hantro-substitution framing instead of "format/control mismatch rejected."
6. **Memory rules**: extend `feedback_unconditional_codec_state.md` + add `feedback_va_lifecycle_profile_threading.md`.
LOC delta estimate unchanged at ~50 LOC. Amendments 14 simplify rather than expand.