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>
This commit is contained in:
@@ -0,0 +1,367 @@
|
||||
# Iteration 1 — Phase 3 (baseline measurements)
|
||||
|
||||
Phase 3 baselines for the iter1 MPEG-2 boolean-correctness work, captured 2026-05-08 00:39 CEST after fresnel reboot. All four baseline runs and the verbatim output anchors are in [`phase0_evidence/2026-05-07/iter1_phase3/`](phase0_evidence/2026-05-07/iter1_phase3/).
|
||||
|
||||
Phase 3 discipline (per `feedback_dev_process.md`): raw data leads, derived numbers are anchored to the visible tool invocation that produced them. Every "this matches Phase 2 prediction" claim cites a verbatim line from the captured trace, not a paraphrase.
|
||||
|
||||
## Reset context
|
||||
|
||||
```
|
||||
$ ssh fresnel 'hostname; uname -r; uptime'
|
||||
fresnel
|
||||
6.19.9-99-eos-arm
|
||||
00:31:35 up 4 min, 2 users, load average: 1.01, 0.70, 0.34
|
||||
|
||||
$ loginctl list-sessions --no-pager | head
|
||||
SESSION UID USER SEAT LEADER CLASS TTY IDLE SINCE
|
||||
2 1000 mfritsche seat0 2244 user tty1 no -
|
||||
```
|
||||
|
||||
fresnel rebooted between Phase 2 and Phase 3 (uptime 4 min explains the `No route to host` Phase 2 noted). SDDM watchpoint condition not triggered: `journalctl -u sddm -b | grep -E "(qFatal|crash|Error|fatal|SIGABRT)"` returns empty for this boot. Plasma Wayland session active on tty1, mfritsche logged in.
|
||||
|
||||
## Baseline A — pre-patch failure mode
|
||||
|
||||
**Goal**: capture the exact path that produces `vaCreateConfig: 12 (UNSUPPORTED_PROFILE)` on master tip `65969da`, before any iter1 work touches the code.
|
||||
|
||||
**Invocation**:
|
||||
|
||||
```bash
|
||||
strace -ff -tt -y -e trace=ioctl,openat,close \
|
||||
-o /tmp/iter1_phase3/baseline_A_ffmpeg/ffmpeg.strace \
|
||||
env LIBVA_DRIVER_NAME=v4l2_request \
|
||||
LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video5 \
|
||||
LIBVA_V4L2_REQUEST_MEDIA_PATH=/dev/media2 \
|
||||
LIBVA_TRACE=/tmp/iter1_phase3/baseline_A_ffmpeg/libva.trace \
|
||||
ffmpeg -hide_banner -loglevel debug -hwaccel vaapi \
|
||||
-i ~/fourier-test/bbb_720p10s_mpeg2.ts -frames:v 2 -f null -
|
||||
```
|
||||
|
||||
**Verbatim libva trace** ([`baseline_A_ffmpeg/libva.trace.*`](phase0_evidence/2026-05-07/iter1_phase3/baseline_A_ffmpeg/)):
|
||||
|
||||
```
|
||||
[5276.234210][ctx none] VA-API vendor string: v4l2-request
|
||||
[5276.234352][ctx none] vaInitialize ret = VA_STATUS_SUCCESS, success (no error)
|
||||
[5276.264142][ctx none] vaQueryConfigProfiles ret = VA_STATUS_SUCCESS, success (no error)
|
||||
[5276.264347][ctx none] va_TraceCreateConfig
|
||||
[5276.264351][ctx none] profile = 1, VAProfileMPEG2Main
|
||||
[5276.264354][ctx none] entrypoint = 1, VAEntrypointVLD
|
||||
[5276.264357][ctx none] num_attribs = 0
|
||||
[5276.264606][ctx none] vaCreateConfig ret = VA_STATUS_ERROR_UNSUPPORTED_PROFILE, the requested VAProfile is not supported
|
||||
[5276.425879][ctx none] va_TraceTerminate
|
||||
[5276.426283][ctx none] vaTerminate ret = VA_STATUS_SUCCESS, success (no error)
|
||||
```
|
||||
|
||||
**Verbatim ffmpeg log** ([`baseline_A_ffmpeg/ffmpeg.stdout`](phase0_evidence/2026-05-07/iter1_phase3/baseline_A_ffmpeg/ffmpeg.stdout)):
|
||||
|
||||
```
|
||||
[VAAPI @ 0xaaaaef94e010] libva: User environment variable requested driver 'v4l2_request'
|
||||
[VAAPI @ 0xaaaaef94e010] libva: Trying to open /usr/lib/dri/v4l2_request_drv_video.so
|
||||
[VAAPI @ 0xaaaaef94e010] libva: Found init function __vaDriverInit_1_23
|
||||
[VAAPI @ 0xaaaaef94e010] Initialised VAAPI connection: version 1.23
|
||||
[VAAPI @ 0xaaaaef94e010] VAAPI driver: v4l2-request.
|
||||
[mpeg2video @ 0xaaaaef99ee10] Format vaapi chosen by get_format().
|
||||
[mpeg2video @ 0xaaaaef99ee10] Format vaapi requires hwaccel mpeg2_vaapi initialisation.
|
||||
[mpeg2video @ 0xaaaaef99ee10] Failed to create decode configuration: 12 (the requested VAProfile is not supported).
|
||||
[mpeg2video @ 0xaaaaef99ee10] Failed setup for format vaapi: hwaccel initialisation returned error.
|
||||
[mpeg2video @ 0xaaaaef99ee10] Format vaapi not usable, retrying get_format() without it.
|
||||
```
|
||||
|
||||
**Verbatim ioctl summary**:
|
||||
|
||||
```
|
||||
10 ioctl(6</dev/video5>, VIDIOC_ENUM_FMT
|
||||
4 ioctl(4</dev/dri/renderD128>, DRM_IOCTL_VERSION
|
||||
1 ioctl(6</dev/video5>, VIDIOC_QUERYCAP
|
||||
```
|
||||
|
||||
12 ftrace v4l2 lines (the ENUM_FMT probe events). Zero VIDIOC_S_FMT, zero REQBUFS, zero S_EXT_CTRLS, zero MEDIA_IOC_REQUEST_ALLOC. Decode never starts.
|
||||
|
||||
**Confirms Phase 2 Bug 1 directly**: `vaCreateConfig` returns `VA_STATUS_ERROR_UNSUPPORTED_PROFILE` for `VAProfileMPEG2Main` — the missing `break;` at `src/config.c:65-66` makes execution fall through to `default:` (line 67-68) which returns the error code we observe (`12`).
|
||||
|
||||
**mpv-as-driver does not reach this path**: a separate baseline run with `mpv --hwdec=vaapi-copy` instead of `ffmpeg -hwaccel vaapi` showed mpv silently fall back to SW decode without ever loading libva for MPEG-2 (no `[vaapi]` log lines, zero V4L2 ioctls, zero libva trace files). mpv's hwdec policy filters MPEG-2 out of vaapi-copy candidates before libva is touched. **Phase 1 success criterion #3 (mpv MPEG-2 engages backend) requires either an mpv config override or a different invocation path** — to be addressed in Phase 4 plan. ffmpeg-direct invocations exercise the full path.
|
||||
|
||||
## Baseline B — post Bug 1 patch failure mode
|
||||
|
||||
**Goal**: with the missing `break;` added as a Phase 3 scratch test, see what fails downstream. Predicted by Phase 2: `VIDIOC_S_EXT_CTRLS` returns `EINVAL` because the staging-era CID `V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS` (= `0x9909fa`) doesn't exist on this kernel.
|
||||
|
||||
**Patch applied** (scratch only, on throwaway branch `iter1-phase3-scratch`, reverted at end of Phase 3):
|
||||
|
||||
```diff
|
||||
@@ -63,6 +63,8 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
|
||||
break;
|
||||
case VAProfileMPEG2Simple:
|
||||
case VAProfileMPEG2Main:
|
||||
+ // Phase 3 scratch — would break here in real fix
|
||||
+ break;
|
||||
case VAProfileHEVCMain:
|
||||
default:
|
||||
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
||||
```
|
||||
|
||||
Rebuilt + installed (`ninja -C build && sudo ninja -C build install`).
|
||||
|
||||
**Verbatim libva trace** showing config-create now succeeds:
|
||||
|
||||
```
|
||||
[5329.689037][ctx none] vaQueryConfigProfiles ret = VA_STATUS_SUCCESS
|
||||
[5329.689228][ctx none] va_TraceCreateConfig
|
||||
[5329.689233][ctx none] profile = 1, VAProfileMPEG2Main
|
||||
[5329.689237][ctx none] entrypoint = 1, VAEntrypointVLD
|
||||
[5329.689239][ctx none] num_attribs = 0
|
||||
[5329.689471][ctx none] vaCreateConfig ret = VA_STATUS_SUCCESS, success (no error)
|
||||
[5329.689703][ctx none] vaQuerySurfaceAttributes ret = VA_STATUS_SUCCESS
|
||||
... (9 more vaQuerySurfaceAttributes calls; surface format negotiation works)
|
||||
```
|
||||
|
||||
**Verbatim failing ioctl** (extracted from `baseline_B_postbug1/ffmpeg.strace.*`, 6 occurrences across 5 frames):
|
||||
|
||||
```
|
||||
ioctl(6</dev/video5>, VIDIOC_S_EXT_CTRLS,
|
||||
{ctrl_class=0xf010000 /* V4L2_CTRL_CLASS_??? */,
|
||||
count=1,
|
||||
controls=[
|
||||
{id=V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
|
||||
size=56,
|
||||
string="h\1\17\0\0\0\0\0H\307Z\226\254i\255\30..."}
|
||||
]}
|
||||
=> {controls=[...], error_idx=1}
|
||||
) = -1 EINVAL (Invalid argument)
|
||||
```
|
||||
|
||||
- **CID** `V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS` = `V4L2_CID_MPEG_BASE+250` = `0x9909fa` — the fork's `include/mpeg2-ctrls.h:13` symbol. **The kernel doesn't recognize this CID** (mainline removed it; replaced by the split `V4L2_CID_STATELESS_MPEG2_{SEQUENCE,PICTURE,QUANTISATION}` at `0xa409dc/dd/de`).
|
||||
- **size=56** matches `sizeof(struct v4l2_ctrl_mpeg2_slice_params)` from the fork's local header (combined sequence + picture + slice fields).
|
||||
- **`error_idx=1`** = first (and only) control in the array failed validation.
|
||||
- 6 calls visible across the 5-frame attempt — one per frame, plus one buffer-pool bring-up artefact.
|
||||
|
||||
**Confirms Phase 2 Bug 2 directly**: the kernel rejects the staging-era CID. The fork's UAPI is stale; rewriting `mpeg2.c` against the new split API is non-optional.
|
||||
|
||||
**Auxiliary EINVAL — H.264 device-init runs unconditionally on hantro**:
|
||||
|
||||
```
|
||||
ioctl(6</dev/video5>, VIDIOC_S_EXT_CTRLS,
|
||||
{ctrl_class=0,
|
||||
count=2,
|
||||
controls=[
|
||||
{id=0xa40900 /* V4L2_CID_STATELESS_H264_DECODE_MODE */, size=0, value=1, value64=1},
|
||||
{id=0xa40901 /* V4L2_CID_STATELESS_H264_START_CODE */, size=0, value=1, value64=1}
|
||||
]}
|
||||
=> {error_idx=2}
|
||||
) = -1 EINVAL (Invalid argument)
|
||||
```
|
||||
|
||||
Source: `src/context.c:142-155` unconditionally sets the H.264 device-wide controls (`V4L2_CID_STATELESS_H264_DECODE_MODE = FRAME_BASED`, `V4L2_CID_STATELESS_H264_START_CODE = ANNEX_B`) on every CreateContext, regardless of profile. **This is intentional** per the existing comment at `src/context.c:138-141`:
|
||||
|
||||
> Errors here are not fatal: not every backing driver supports both controls (e.g. cedrus may default to SLICE_BASED without exposing DECODE_MODE).
|
||||
|
||||
The error is silently swallowed via `(void)v4l2_set_controls(...)` (line 153 — explicit cast discards the return). For MPEG-2 on hantro-vpu-dec the call's a no-op; the EINVAL is noise in the trace, not a bug. **Out of scope for iter1**; documented as auxiliary finding.
|
||||
|
||||
**Verbatim ioctl summary** (post-Bug-1 path engages full V4L2 lifecycle):
|
||||
|
||||
```
|
||||
40 ioctl(6</dev/video5>, VIDIOC_QUERYBUF
|
||||
22 ioctl(6</dev/video5>, VIDIOC_ENUM_FMT
|
||||
16 ioctl(7</dev/media2>, MEDIA_IOC_REQUEST_ALLOC
|
||||
10 ioctl(6</dev/video5>, VIDIOC_QBUF
|
||||
10 ioctl(6</dev/video5>, VIDIOC_G_FMT
|
||||
10 ioctl(6</dev/video5>, VIDIOC_DQBUF
|
||||
6 ioctl(6</dev/video5>, VIDIOC_S_EXT_CTRLS <-- 6 fail with EINVAL
|
||||
4 ioctl(4</dev/dri/renderD128>, DRM_IOCTL_VERSION
|
||||
2 ioctl(6</dev/video5>, VIDIOC_STREAMON
|
||||
2 ioctl(6</dev/video5>, VIDIOC_STREAMOFF
|
||||
2 ioctl(6</dev/video5>, VIDIOC_REQBUFS
|
||||
2 ioctl(6</dev/video5>, VIDIOC_CREATE_BUFS
|
||||
1 ioctl(9<anon_inode:request>, MEDIA_REQUEST_IOC_REINIT
|
||||
1 ioctl(9<anon_inode:request>, MEDIA_REQUEST_IOC_QUEUE
|
||||
1 ioctl(6</dev/video5>, VIDIOC_S_FMT
|
||||
1 ioctl(6</dev/video5>, VIDIOC_QUERYCAP
|
||||
```
|
||||
|
||||
The buffer-pool bring-up + per-frame plumbing (CREATE_BUFS, QUERYBUF, REQBUFS, STREAMON, REQUEST_ALLOC, QBUF, DQBUF, REQUEST_IOC_QUEUE) all succeeds. **Only the codec-specific control submission is broken**. This bounds the iter1 fix scope sharply.
|
||||
|
||||
## Baseline C — cross-validator verbatim contract anchor
|
||||
|
||||
**Goal**: extract the exact byte-level `VIDIOC_S_EXT_CTRLS` payload that the working independent V4L2 client (ffmpeg's `-hwaccel v4l2request`) submits per MPEG-2 frame. This is the contract Phase 4 implementation must match.
|
||||
|
||||
**Invocation** (verbose strace decoding compound `v4l2_ext_control` payloads):
|
||||
|
||||
```bash
|
||||
strace -ff -tt -y -v -e trace=ioctl \
|
||||
-o /tmp/iter1_phase3/baseline_C_xvalidator/ffmpeg.strace \
|
||||
ffmpeg -hide_banner -loglevel error -hwaccel v4l2request \
|
||||
-i ~/fourier-test/bbb_720p10s_mpeg2.ts -frames:v 2 -f null -
|
||||
```
|
||||
|
||||
**Verbatim per-frame submission** (5 frames captured, frame 1 shown verbatim):
|
||||
|
||||
```
|
||||
ioctl(5</dev/video5>, VIDIOC_S_EXT_CTRLS,
|
||||
{ctrl_class=0xf010000 /* V4L2_CTRL_CLASS_CODEC_STATELESS */,
|
||||
count=3,
|
||||
controls=[
|
||||
{id=0xa409dc /* V4L2_CID_STATELESS_MPEG2_SEQUENCE */,
|
||||
size=12,
|
||||
string="\0\5\320\2\0\30\25\0\0\0\1\1"},
|
||||
{id=0xa409dd /* V4L2_CID_STATELESS_MPEG2_PICTURE */,
|
||||
size=32,
|
||||
string="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\202\0\0\0\17\17\17\17\1\3\0\0\0\0\0\0"},
|
||||
{id=0xa409de /* V4L2_CID_STATELESS_MPEG2_QUANTISATION */,
|
||||
size=256,
|
||||
string="\10\20\20\23\20\23\26\26\26\26\26\26\32\30\32\33\33\33\32\32\32\32\33\33\33\35\35\35\"\"\"\35..."}
|
||||
]}) = 0
|
||||
```
|
||||
|
||||
**Field-by-field decode** (frame 1, BBB +30s seek into MPEG-2 fixture):
|
||||
|
||||
`SEQUENCE` (12 bytes, `struct v4l2_ctrl_mpeg2_sequence` per `linux/v4l2-controls.h:2009`):
|
||||
|
||||
| Bytes (LE) | Value | Field |
|
||||
|---|---|---|
|
||||
| `\0\5` | `0x0500` = 1280 | `horizontal_size` |
|
||||
| `\320\2` | `0x02d0` = 720 | `vertical_size` |
|
||||
| `\0\30\25\0` | `0x00151800` | `vbv_buffer_size` |
|
||||
| `\0\0` | `0x0000` | `profile_and_level_indication` |
|
||||
| `\1` | 1 | `chroma_format` (4:2:0) |
|
||||
| `\1` | `V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE` (0x01) | `flags` |
|
||||
|
||||
`PICTURE` (32 bytes, `struct v4l2_ctrl_mpeg2_picture` per `linux/v4l2-controls.h:2056`):
|
||||
|
||||
| Bytes (LE) | Value | Field |
|
||||
|---|---|---|
|
||||
| `\0\0\0\0\0\0\0\0` | 0 | `backward_ref_ts` (I-frame, no ref) |
|
||||
| `\0\0\0\0\0\0\0\0` | 0 | `forward_ref_ts` (I-frame, no ref) |
|
||||
| `\202\0\0\0` | `0x82` = `FRAME_PRED_DCT(0x02) \| PROGRESSIVE(0x80)` | `flags` |
|
||||
| `\17\17\17\17` | `f_code = {{15,15},{15,15}}` (default for I) | `f_code[2][2]` |
|
||||
| `\1` | 1 | `picture_coding_type` (I) |
|
||||
| `\3` | 3 | `picture_structure` (FRAME) |
|
||||
| `\0` | 0 | `intra_dc_precision` (8-bit) |
|
||||
| `\0\0\0\0\0` | 0 | `reserved[5]` |
|
||||
|
||||
Frame 2 (P-picture per the MPEG-2 GOP) shows different values, verbatim from the next strace line:
|
||||
|
||||
```
|
||||
PICTURE: "\0\0\0\0\0\0\0\0p\27\0\0\0\0\0\0\202\0\0\0\1\1\17\17\2\3\0\0\0\0\0\0"
|
||||
```
|
||||
|
||||
| Bytes (LE) | Value | Field |
|
||||
|---|---|---|
|
||||
| `\0\0\0\0\0\0\0\0` | 0 | `backward_ref_ts` (P, no backward) |
|
||||
| `p\27\0\0\0\0\0\0` | `0x1770` ns = 6000 (matches the I-frame's timestamp) | `forward_ref_ts` (refers to frame 1) |
|
||||
| `\202\0\0\0` | 0x82 | `flags` (same FRAME_PRED_DCT \| PROGRESSIVE) |
|
||||
| `\1\1\17\17` | `f_code = {{1,1},{15,15}}` (real motion vectors for P) | `f_code` |
|
||||
| `\2` | 2 | `picture_coding_type` (P) |
|
||||
| `\3` | 3 | `picture_structure` (FRAME) |
|
||||
| `\0` | 0 | `intra_dc_precision` |
|
||||
| `\0\0\0\0\0` | 0 | `reserved[5]` |
|
||||
|
||||
`QUANTISATION` (256 bytes = 4 × 64 bytes):
|
||||
|
||||
```
|
||||
intra_quantiser_matrix[64] = [8, 16, 16, 19, 16, 19, 22, 22, 22, 22, 22, 22, 26, 24, 26, 27, 27, 27, 26, 26, 26, 26, 27, 27, 27, 29, 29, 29, 34, 34, 34, 29, ...]
|
||||
```
|
||||
|
||||
This is the canonical MPEG-2 default intra matrix in zigzag scanning order — `8` is at zigzag-position 0 (DC coefficient), `16,16` at positions 1-2 (first AC pair). Confirms the kernel-doc claim that matrices arrive **in zigzag scanning order** (`linux/v4l2-controls.h:2076-2084`).
|
||||
|
||||
The remaining 192 bytes (non-intra, chroma_intra, chroma_non_intra) all start with `\20\20...` = 16,16,... — MPEG-2 default non-intra is a flat 16 matrix; chroma matrices duplicate luma when chroma_format=4:2:0.
|
||||
|
||||
**This is the iter1 contract anchor**: every Phase 4 implementation diff and Phase 7 verification must produce a `VIDIOC_S_EXT_CTRLS` call that's structurally indistinguishable from this — `count=3`, `ctrl_class=V4L2_CTRL_CLASS_CODEC_STATELESS=0xf010000`, the three CIDs in this order, with sizes 12 / 32 / 256 and the per-frame field values matching what VAAPI's `VAPictureParameterBufferMPEG2` and `VAIQMatrixBufferMPEG2` carry for the same fixture.
|
||||
|
||||
## Baseline D — H.264 regression check (Phase 1 success criterion #5)
|
||||
|
||||
**Goal**: prove Bug 1 fix in isolation doesn't break H.264. Re-runs T4's reference incantation against `bbb_1080p30_h264.mp4` with the scratch backend installed; expects byte-identical SHA-256 hashes against T4's reference values (`f623d5f7…` for frame 1, `7d7bc6f2…` for frame 2 at +30s seek).
|
||||
|
||||
**Verbatim hash output**:
|
||||
|
||||
```
|
||||
f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9 /tmp/iter1_phase3/baseline_D_h264_regr/png_seek_hw/00000001.jpg
|
||||
7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8 /tmp/iter1_phase3/baseline_D_h264_regr/png_seek_hw/00000002.jpg
|
||||
f623d5f7a41697f67dd227275c6f1b21ffc257f65626d32fde8229357f8764c9 /tmp/iter1_phase3/baseline_D_h264_regr/png_seek_sw/00000001.jpg
|
||||
7d7bc6f2146dda8b2d223bba622c4b9fbe9674181ff1e02afe286b620342e0a8 /tmp/iter1_phase3/baseline_D_h264_regr/png_seek_sw/00000002.jpg
|
||||
```
|
||||
|
||||
Pass: HW frame 1 == SW frame 1 == T4 reference; HW frame 2 == SW frame 2 == T4 reference. Bug 1 fix in isolation does not regress H.264.
|
||||
|
||||
## Scratch state cleanup
|
||||
|
||||
After Baseline D, the scratch patch was reverted to keep master clean for Phase 4 work:
|
||||
|
||||
```
|
||||
$ git checkout -- src/config.c
|
||||
$ ninja -C build && sudo ninja -C build install
|
||||
$ git branch -D iter1-phase3-scratch # branch was empty — patch was uncommitted
|
||||
```
|
||||
|
||||
**Sanity check** (master backend reinstalled, MPEG-2 should fail again):
|
||||
|
||||
```
|
||||
$ ffmpeg -hwaccel vaapi -i bbb_720p10s_mpeg2.ts -frames:v 2 -f null -
|
||||
[mpeg2video] Failed to create decode configuration: 12 (the requested VAProfile is not supported).
|
||||
[mpeg2video] Failed setup for format vaapi: hwaccel initialisation returned error.
|
||||
```
|
||||
|
||||
Back to Baseline A state — scratch state successfully cleaned.
|
||||
|
||||
## What Phase 3 confirms / refutes from Phase 2
|
||||
|
||||
| Phase 2 claim | Phase 3 evidence | Status |
|
||||
|---|---|---|
|
||||
| Bug 1: `RequestCreateConfig` rejects MPEG-2 via fall-through to `default:` returning `VA_STATUS_ERROR_UNSUPPORTED_PROFILE` | Baseline A libva trace shows `vaCreateConfig ret = VA_STATUS_ERROR_UNSUPPORTED_PROFILE` for `profile=VAProfileMPEG2Main` | ✅ confirmed |
|
||||
| Bug 1 fix is sufficient to advance past `vaCreateConfig` | Baseline B libva trace shows `vaCreateConfig ret = VA_STATUS_SUCCESS` post-patch | ✅ confirmed |
|
||||
| Bug 2: `mpeg2.c` uses staging-era CID `V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS` (`0x9909fa`) which mainline kernel removed | Baseline B strace shows `VIDIOC_S_EXT_CTRLS id=V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS size=56 = -1 EINVAL` | ✅ confirmed |
|
||||
| Bug 2: kernel exposes the new split API (`0xa409dc/dd/de`) | Baseline C strace shows ffmpeg-v4l2request submits these three CIDs successfully | ✅ confirmed |
|
||||
| Cross-validator submits 1 batched `VIDIOC_S_EXT_CTRLS, count=3` per frame | Baseline C verbatim payload shows exactly that | ✅ confirmed |
|
||||
| Quantisation matrices arrive in zigzag order | Baseline C QUANTISATION first 4 bytes `[8, 16, 16, 19]` matches MPEG-2 default intra matrix in zigzag | ✅ confirmed |
|
||||
| H.264 device-init in context.c is best-effort and silently swallows EINVAL on hantro | Baseline B strace shows the `0xa40900/0xa40901` EINVAL (silently); `src/context.c:153` has `(void)v4l2_set_controls(...)` cast | ✅ confirmed (auxiliary, not iter1 scope) |
|
||||
| Phase 1 criterion #5 (H.264 regression check) holds with scratch Bug 1 fix in isolation | Baseline D hashes match T4 reference exactly | ✅ confirmed |
|
||||
| mpv-as-driver engages the libva backend for MPEG-2 | Baseline A's mpv variant: zero V4L2 ioctls, zero libva trace, silent SW fallback | ❌ **refuted** — mpv silently bypasses vaapi for MPEG-2; Phase 1 criterion #3 needs adjustment |
|
||||
|
||||
## Phase 1 criterion #3 needs adjustment (Phase 3 → Phase 1 loopback)
|
||||
|
||||
Per `feedback_dev_process.md`'s Phase 3 → Phase 1 loopback edge:
|
||||
|
||||
> If baseline reveals the Phase 1 metric was tracking the wrong thing → loop back to Phase 1 with the corrected target.
|
||||
|
||||
The Phase 1 lock specified:
|
||||
|
||||
> 3. End-to-end decode engages the backend. `mpv --hwdec=vaapi-copy --frames=2 --vo=null --no-audio …` logs the `[vaapi] libva: Trying to open …` chain, the `Using hardware decoding (vaapi-copy)` confirmation, and exits 0 with no `Failed to create decode configuration` lines.
|
||||
|
||||
Phase 3 baseline shows mpv-vaapi-copy **never engages libva for MPEG-2** in the current configuration — neither pre-patch nor post-Bug-1-patch produces `[vaapi]` log lines or VA-API ioctls when invoked via mpv on the MPEG-2 fixture. The mpv hwdec policy (or ffmpeg-mpv glue layer) filters MPEG-2 out before libva is touched. So the Phase 1 criterion #3 wording can never be satisfied via the original incantation, regardless of whether iter1 fixes the libva backend.
|
||||
|
||||
**Adjusted Phase 1 criterion #3** (proposed; locks alongside Phase 4 plan):
|
||||
|
||||
> 3. End-to-end decode engages the backend. `ffmpeg -hwaccel vaapi -i bbb_720p10s_mpeg2.ts -frames:v 2 -f null - 2>&1` (with the v4l2_request env vars set) shows the `[VAAPI] libva: Trying to open /usr/lib/dri/v4l2_request_drv_video.so` chain, `vaCreateConfig ret = VA_STATUS_SUCCESS`, no `Failed to create decode configuration` lines, no `EINVAL` from `VIDIOC_S_EXT_CTRLS`, and exits 0 cleanly.
|
||||
|
||||
The `mpv` invocation moves from criterion to optional follow-up (potentially needs an `--vd` override or a fix to mpv's hwdec-codecs filter; a separate, smaller iteration after iter1 lands).
|
||||
|
||||
The other four Phase 1 criteria (vainfo enumeration regression, vaCreateConfig success, DMA-BUF GL pixel verify HW=SW, T4 H.264 regression) hold as locked — no adjustment needed.
|
||||
|
||||
## Phase 4 plan inputs
|
||||
|
||||
Phase 4 plan should specify:
|
||||
|
||||
1. **Diff scope** (per Phase 2 `phase2_iter1_situation.md`):
|
||||
- `src/config.c:55-69` — add `break;` for `VAProfileMPEG2Simple/Main` cases (3 lines).
|
||||
- `src/mpeg2.c` — full rewrite against the new split API.
|
||||
- `include/mpeg2-ctrls.h` — delete or empty (drop the staging-era header that masks the kernel's modern definitions).
|
||||
- `src/picture.c` — no changes (verified wired correctly in Phase 2).
|
||||
- `src/context.c` — no changes (the H.264 device-init EINVAL is auxiliary, by-design swallowed).
|
||||
|
||||
2. **Contract anchor** (per Phase 6 contract-before-code per `feedback_dev_process.md`):
|
||||
- Cite verbatim from `linux/v4l2-controls.h:1985-2105` — the three control struct definitions and flag constants.
|
||||
- Cite verbatim from FFmpeg `libavcodec/v4l2_request_mpeg2.c:130-155` — the batched submission shape (3 controls, `ctrl_class=V4L2_CTRL_CLASS_CODEC_STATELESS`).
|
||||
- Cite verbatim from kernel `drivers/media/platform/verisilicon/hantro_mpeg2.c::hantro_mpeg2_dec_copy_qtable` — the kernel-side zigzag-to-raster permutation (so the libva backend doesn't double-permute).
|
||||
- Cite Baseline C verbatim payload from this document (`SEQUENCE` 12 bytes, `PICTURE` 32 bytes, `QUANTISATION` 256 bytes per frame).
|
||||
|
||||
3. **Field mapping table** (per Phase 2 `phase2_iter1_situation.md` Bug 2 detail):
|
||||
- 6 structural changes from old to new API documented.
|
||||
- Source-data extraction in current `src/mpeg2.c` is sound; only destination-control-struct shape and CIDs change.
|
||||
|
||||
4. **Phase 7 verification harness**:
|
||||
- Re-run all 5 Phase 1 boolean checks (with criterion #3 adjusted as above).
|
||||
- Compare the post-fix `VIDIOC_S_EXT_CTRLS` payload byte-by-byte against Baseline C's verbatim payload — exact match expected for SEQUENCE field values; PICTURE will differ on `forward_ref_ts/backward_ref_ts` (different timestamp source) and `f_code` (real values not defaults); QUANTISATION should match exactly for the same fixture.
|
||||
|
||||
5. **Mpv-criterion-3 follow-up** (deferred):
|
||||
- File a follow-up task to investigate why mpv-vaapi-copy filters MPEG-2 out and how to override. Out of iter1 scope.
|
||||
|
||||
## Phase 3 → Phase 4 close
|
||||
|
||||
Phase 3 baselines all four green. Phase 2 Bug 1 + Bug 2 + Bug 3 confirmed empirically. Phase 1 criterion #3 needs a minor wording adjustment (mpv → ffmpeg-direct anchor) — proposed text above; locks with Phase 4 plan if approved. Phase 4 can proceed with the contract-anchored diff scope.
|
||||
Reference in New Issue
Block a user