evidence · 7.8 KiB

README.md

Committed at docs/evidence/video-acceleration/README.md. This is what grounds the requirements that cite it.

Open raw source

Video decoding and rendering follow-up

Physical board, 2026-09-22 America/Chicago (2026-09-23 UTC), running the persistent Wi-Fi image. These are temporary probe packages from nix/video-probe.nix, not an installed default video app. Audio is disabled throughout. Big Buck Bunny © 2008 Blender Foundation, CC BY 3.0.

Hardware decoder

The live capability query identifies /dev/video0 as MVX/Linlon, V4L2 memory-to-memory, with H.264 compressed input and raw YUV output. Listing other formats is not proof that those codecs work. The small query binary was first built against a different cross-libc path; invoking it with the board’s installed compatible loader resolved that host-build mismatch.

The rebuilt FFmpeg enables withV4l2M2m = true and h264_v4l2m2m explicitly. The decoder flag is -c:v h264_v4l2m2m; mpv selects it with --vd=h264_v4l2m2m. --hwdec=no in the trial disables mpv’s separate automatic hwaccel negotiation; it does not override this explicit V4L2 decoder selection. Logs confirm the selected decoder opens /dev/video0 using driver mvx.

Packages:

The driver already includes vendor codec microcode in the kernel. See the source and firmware audit; this is not a blob-free path or evidence of GPU rendering.

Decode-only comparison

A local fragmented-MP4 sample concatenated the initialization segment and segments 12–15 of bbb_30fps_640x360_1000k from https://dash.akamaized.net/akamai/bbb_30fps/. It contains the same public BBB representation used for the network trial. Local input removes network time; null output removes scaling and display. Each invocation stopped at 300 output frames, with -debug_ts -benchmark, no input seek, and no duration-based stop. These are single bounded observations, not statistical benchmark estimates.

DecoderOutput framesWall timeUser + system CPU timeReported rate
Software H.2643003.873 s3.626 s77 fps
MVX H.2643001.259 s0.469 s239 fps

Both completed successfully with zero reported decode errors. Those rates measure decode to a null sink, not on-screen frame rate.

MVX’s timestamps are not yet trustworthy: the captured sequence starts with repeated zeros, whereas software starts 0,1,2,3,4 at time base 1/30. The excerpt contains 292 parseable timestamps and is not a complete frame-index map. The hardware run reports 9.33 s for 300 frames, versus 10.00 s in software. This limits seeking, variable-frame-rate playback, and audio synchronization. No speculative driver patch or general timestamp repair was applied.

For the known 30-fps, silent BBB experiment only, mpv can generate timing with --correct-pts=no --container-fps-override=30. That is a scoped workaround, not acceptance of MVX timestamps for arbitrary media.

Streaming and window size

The original public remote MPD is https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd. All following runs request the same 30 seconds, starting at 45 seconds, with --cache=yes --demuxer-readahead-secs=30 --vo=wlshm --profile=sw-fast. A Sway rule makes the k230-video-probe window floating and borderless at the specified size. --geometry alone does not constrain a tiled Sway window.

TrialSource / outputDecoderDecoder / VO drops
Software, video-sized window480×270 / 480×270native H.2640 / 0
MVX, fixed 30-fps timing640×360 / 568×320MVX0 / 134
Same, internal vsync disabled640×360 / 568×320MVX0 / 138
MVX, point scaling, internal vsync auto640×360 / 568×320MVX0 / 0

The 270p result improves on the earlier 106-drop tiled-window observation. Window size and explicit cache settings changed together, so this is a usable configuration comparison, not an isolated attribution of all improvement to one flag. Network buffers stayed ahead in the original-URL trials.

An intermediate experiment used a filtered MPD stored locally. Both native and MVX runs kept only about one second of cache and advanced in bursts. Their zero-drop counters are excluded from acceptance; they do not establish smooth playback. A first seek/duration-limited FFmpeg DASH trial was also discarded as a throughput benchmark in favor of the fixed-frame local comparison above.

The software baseline uses an unscaled YUV-to-BGRA converter. The 360p output still uses CPU scaling (bilinear in the first trials, point in the successful configuration); neither the VPU nor the KPU accelerates this Wayland SHM rendering path. Counters describe player behavior, not a measured panel scanout cadence. Physical/native captures and a presentation-timing acceptance remain separate evidence layers in the video proposal.

The decisive 360p setting was --sws-scaler=point, placed after --profile=sw-fast so that the profile does not overwrite it with bilinear. The first attempt put it before the profile and still logged bilinear; that attempt is not a point-scaler result. The corrected log explicitly records nearest-neighbor/point scaling. This trades interpolation quality for speed.

tools/play-bbb-probe.sh preserves two bounded recipes: software for unscaled 270p with native timing, and mvx for 360p with point scaling and the known-CFR timing override. Run it as the shell user with the built mpv path and its Wayland/Sway environment. It runs the public 30-second test, with audio off.

Compositor versus 2.5D GPU

Sway currently forces the CPU Pixman renderer. That is not evidence that the chip lacks graphics acceleration: the live GPU preflight records CONFIG_GPU_VGLITE=y and a root-only /dev/vg_lite device. DRM exposes card0 but no render node. The VG-Lite 2.5D engine is a different integration path from a Mesa/OpenGL renderer; it is not used by the current shell or these wlshm playback tests. The separate offscreen RGBX blit/scale test passed; the GPU integration audit records the initial RGBA color mismatch and the remaining display-buffer work. This is separate from the proven VPU decode result above.

Captured repeat

The same 360p/point/CFR configuration was repeated while taking a compositor screenshot and a host-camera recording. This captured run reported 0 decoder and 2 video-output drops, versus 0/0 in the earlier run. The screenshot adds work on the board; this record does not isolate whether that caused the two drops. Both outcomes are retained.

Native screenshot, four-second physical clip and camera still show the actual decoded movie. The camera crop excludes the surrounding body/desk scene; provenance records its coordinates, timing, source hash and autofocus setting. It is an oblique hand-held camera view, not a panel frame-rate measurement. The source recording remains private on the host; only selected derivatives are published.

The captured repeat stopped advancing at the requested final frame but did not finish process teardown promptly. The coordinator terminated that identified mpv process; cleanup confirms no player remains and shell, seatd, and Wi-Fi stay active. The diagnostic wrapper therefore has a 90-second wall clock limit with a three-second termination grace period. This is a guard for the bounded probe, not a claim that integrated EOF/error recovery is solved. The earlier point-scaler run did return EOF normally.