# Per-codec test fixtures — fresnel 2026-05-07

Phase 0 deliverable #5. Fixtures for the five locked codecs (H.264 + HEVC + VP9 + MPEG-2 + VP8), all derived from the same Big Buck Bunny H.264 master, generated on fresnel with stock ffmpeg `n8.1-13`.

## Inventory

All fixtures live at `~/fourier-test/` on fresnel. Same path on ohm (carryover convention from libva-multiplanar). H.264 master mirrored on both hosts.

| Codec | File | Size | Profile/Level | Resolution | Pix fmt | Duration | Targets V4L2 device |
|---|---|---|---|---|---|---|---|
| H.264 | `bbb_1080p30_h264.mp4` (carryover) | 725 MB | High@4.0 | 1920×1080 | yuv420p | 596 s | rkvdec `/dev/video3` (`S264`) |
| HEVC  | `bbb_720p10s_hevc.mp4` | 620 KB | Main 8-bit | 1280×720 | yuv420p | 10 s | rkvdec `/dev/video3` (`S265`) |
| VP9   | `bbb_720p10s_vp9.webm` | 3.4 MB | Profile 0 (8-bit 4:2:0) | 1280×720 | yuv420p | 10 s | rkvdec `/dev/video3` (`VP9F`) |
| MPEG-2 | `bbb_720p10s_mpeg2.ts` | 5.3 MB | Main | 1280×720 | yuv420p | 10 s | hantro-vpu-dec `/dev/video5` (`MG2S`) |
| VP8   | `bbb_720p10s_vp8.webm` | 2.4 MB | Profile 0 | 1280×720 | yuv420p | 10 s | hantro-vpu-dec `/dev/video5` (`VP8F`) |

Codec scope alignment (per `phase0_findings.md` LOCK + 2026-05-07 evening corrections):

- **rkvdec**: 8-bit Main HEVC (silicon doesn't do 10-bit reliably; rkvdec advertises Main 10 in its menu but RK3399 hardware support is unverified — 8-bit fixture stays in the "expected to work" lane).
- **rkvdec**: VP9 Profile 0 only (kernel menu shows `vp9_profile min=0 max=0 default=0` — no other profile is enumerable).
- **hantro-vpu-dec**: MPEG-2 Main (per kernel `hantro_mpeg2.c`).
- **hantro-vpu-dec**: VP8 (single profile, no menu).

## Generation provenance

All four non-H.264 fixtures generated on fresnel 2026-05-07 23:34–23:36 CEST from the H.264 master via stock ffmpeg software encoders:

```bash
INPUT=~/fourier-test/bbb_1080p30_h264.mp4

# HEVC Main 8-bit, 720p, 10s seek-30s, x265 ultrafast
ffmpeg -y -ss 30 -t 10 -i "$INPUT" \
  -vf scale=1280:720 -c:v libx265 -preset ultrafast -crf 28 \
  -profile:v main -pix_fmt yuv420p -tag:v hvc1 -an \
  ~/fourier-test/bbb_720p10s_hevc.mp4

# VP9 Profile 0, 720p, 10s, libvpx-vp9 speed 5 with row-mt
ffmpeg -y -ss 30 -t 10 -i "$INPUT" \
  -vf scale=1280:720 -c:v libvpx-vp9 -speed 5 -row-mt 1 \
  -profile:v 0 -pix_fmt yuv420p -an -b:v 2M \
  ~/fourier-test/bbb_720p10s_vp9.webm

# MPEG-2 Main, 720p, 10s, transport stream container
ffmpeg -y -ss 30 -t 10 -i "$INPUT" \
  -vf scale=1280:720 -c:v mpeg2video -profile:v 4 -level:v 8 \
  -b:v 4M -pix_fmt yuv420p -an \
  ~/fourier-test/bbb_720p10s_mpeg2.ts

# VP8, 720p, 10s, libvpx
ffmpeg -y -ss 30 -t 10 -i "$INPUT" \
  -vf scale=1280:720 -c:v libvpx -deadline good -cpu-used 4 \
  -pix_fmt yuv420p -an -b:v 2M \
  ~/fourier-test/bbb_720p10s_vp8.webm
```

Wall-clock encode times on fresnel RK3399:

| Codec | Wall | User CPU | Notes |
|---|---|---|---|
| HEVC | 13.4 s | 66.6 s | x265 ultrafast across 5 of 6 cores |
| VP9 | 93.4 s | 278.3 s | libvpx-vp9 -speed 5 -row-mt 1, 3-core utilization |
| MPEG-2 | 5.95 s | 24.5 s | mpeg2video, lightweight |
| VP8 | 26.4 s | 108.4 s | libvpx -cpu-used 4, 4-core utilization |

Reproducible: re-run the four `ffmpeg` invocations above; outputs should hash-match modulo encoder-version non-determinism (libx265/libvpx don't always produce bit-exact identical encodes across runs even with identical flags).

## Why 720p / 10s

- **720p** matches the second-most-common consumer playback resolution (mpv, Firefox YouTube embed, Chromium WebRTC) without exhausting the 1080p H.264 master's encoded resolution (downscale, never upscale). Keeps encode time ≪ 2 minutes per codec on RK3399 SW encoders.
- **10s** = 240 frames at 24 fps. Long enough to see DPB activity, B-frame ordering (where applicable), reference-frame pumping, and any transient bug like iter4's frame-11 EINVAL on libva-multiplanar. Short enough for a contract trace's grep'ability.
- **8-bit yuv420p** matches the kernel's silicon support reality for all five codecs on RK3399.

## Encoder choice rationale

- **libx265 ultrafast preset** for HEVC: trades file size for encode wall-time. We don't care about quality (decode-side test, not encode-side); we care about a valid, parseable HEVC bitstream that exercises the rkvdec HEVC path.
- **libvpx-vp9 speed 5** for VP9: balanced — speed 6+ hurts conformance, speed 4 doubles the encode time.
- **mpeg2video profile 4 level 8 (Main, ML)**: the most generic compatibility target. RK3399 hantro accepts Simple and Main; Main covers both and is what's commonly streamed.
- **libvpx (vp8)**: stock libvpx, no speed tuning needed — VP8 is fast enough.

Phase 1+ may add additional fixtures: longer durations (60s+ for run-stability), higher resolutions (1080p HEVC for rkvdec stress), or additional source content (e.g., a low-motion test pattern, a high-motion sports clip). Keeping Phase 0 at the smallest set that exercises each codec's request-API contract on its assigned V4L2 node.

## Verification

Each fixture probed via `ffprobe -v error -show_entries stream=codec_name,profile,pix_fmt,width,height,r_frame_rate,duration`:

| File | codec_name | profile | pix_fmt | width×height | fps | duration |
|---|---|---|---|---|---|---|
| `bbb_720p10s_hevc.mp4` | hevc | Main | yuv420p | 1280×720 | 24/1 | 10.000000 |
| `bbb_720p10s_vp9.webm` | vp9 | Profile 0 | yuv420p | 1280×720 | 24/1 | N/A (live-stream container) |
| `bbb_720p10s_mpeg2.ts` | mpeg2video | Main | yuv420p | 1280×720 | 24/1 | 10.000000 |
| `bbb_720p10s_vp8.webm` | vp8 | 0 | yuv420p | 1280×720 | 24/1 | N/A (live-stream container) |

Profile/pix_fmt match the campaign codec scope. Phase 1 binding cells per codec can use these directly.

## Open future-fixture items (not Phase 0 gating)

- **Test patterns** for synthetic decode-correctness checks (constant-color frames, gradient ramps, single-pixel motion). Useful for bit-exact verification beyond JPEG-of-real-content. Not generated yet; Phase 1 work item.
- **Long-duration variants** (60s, 5min) for run-stability / leak detection. iter7's slot-leak fix is in iter8 master so this should be clean, but a long-run trace would prove it on RK3399.
- **Stress fixtures**: 1080p HEVC, 1080p VP9, complex motion. Defer until basic boolean-correctness lands per codec.
- **chromium-fourier 149 reference clips** if the cross-validator engages a different fixture format (e.g., MSE/EME-encrypted clip for DRM-path validation). Not in Phase 0 scope.

## Storage / mirroring

- `~/fourier-test/` on fresnel is the working location.
- Mirror to `data:/moviedata/fourier-test/` for fleet-wide availability — pending; data is currently offline (no route to host as of 2026-05-07 22:34). Wake via the his cheatsheet (Fritz!DECT plug or WoL) when the next iteration needs cross-host fixtures.
- `~/fourier-test/` on ohm holds the H.264 master; ohm doesn't yet have the new per-codec clips. Decision deferred — fresnel-fourier is the campaign that needs them; ohm is the libva-multiplanar testbed (already H.264-only-locked at iter5+).

The fixtures are gitignored as binary content (`*.mp4`, `*.webm`, `*.ts` are treated as raw data; not in `phase*_evidence/` extension allow-list). They live on fresnel; this document is the canonical inventory.
