A hardware decoder cuts client decode power ~3.6× — and having the silicon isn't enough: stock software must be able to reach it
🟢 Repeatable · measured 2026-07-29 · v1
Pi 400, same board, same 1080p60 file — H.264 hw +0.35 W vs sw +1.25 W playing (3.6×); +0.64 vs +2.62 W saturated (4.1×). Pi 5 (block dropped): +1.57 W.
SCOPE: Client device layer only (Raspberry Pi 400 / Pi 5, headless pure decode; Google TV as playback context). Network, CDN, display excluded on the Pis.
OWL Finding: A hardware decoder cuts client decode power ~3.6× — and having the silicon isn't enough: stock software must be able to reach it
measured 2026-07-29
https://wattlab.greeningofstreaming.org/findings/hw-decoder-cuts-client-energy-4x
Greening of Streaming — wattlab.greeningofstreaming.org
Source measurement
Loading measurement decode/dec0de04…
Loading measurement decode/dec0de05…
Caveats
DRAFT pending lab review. Realtime rows are BBB 1080p60 only; single board pair; one rung.
Pi rows are headless pure decode (ffmpeg -f null, audio disabled) — no display path. A real player adds display/compositor energy on top.
Both Pis' HEVC hardware blocks exist but are unreachable from stock Bookworm userspace (stateless V4L2; GStreamer <1.24, no V4L2-request ffmpeg/mpv, VLC built without the hw paths) — so 'hw vs sw' could only be measured for H.264, on the Pi 400.
Cross-board Pi 400 vs Pi 5 software comparison is n=1 per board with uncontrolled DRAM/clock differences; the same-board hw-vs-sw pair is the clean single-variable read.
The result, in one sentence
On the same Raspberry Pi 400, decoding the same 1080p60 H.264 file, the hardware decode path (bcm2835-codec v4l2m2m) drew +0.35 W where software drew +1.25 W while playing at 1× — 3.6× less — and the Raspberry Pi 5, which shipped without that hardware block, pays +1.57 W in software for the same stream.
Why this matters
Encode energy is paid once per title; decode energy is paid per viewer, per hour. OWL's bench has measured the server side since day one — this is the first OWL-grade measurement (per-run idle baseline, ΔW, traffic-light confidence, raw samples persisted) of the client layer that REM's field fleet observes, using the local-mW plug principle LEM documents. A device generation that drops a decoder block, or an OS release that can't reach one, multiplies the per-viewer number by ~4 — invisible in any spec sheet, visible at the wall.
The second half of the headline is the sharper finding: on both Pi generations the HEVC hardware sits idle behind software that cannot drive it. Stock-OS users software-decode everything. Stranded silicon is an energy bug.
How it was measured
decode-bench harness (/srv/data/owl/decode-bench/): clips staged in tmpfs (no network, no SD I/O), ffmpeg -f null pure decode (every frame decoded, none displayed), Tapo P110 local mW API at 1.5 s, per-run baseline, OWL confidence.py per row. Two regimes per cell: realtime (-re, 150 s) and full-speed (-stream_loop -1, 120 s). All cited rows 🟢; key realtime rows replicated n=2–3. Full narrative + conjecture list: docs/pi_decode_energy_2026-07.md.
What this finding does not measure
Playback with a display attached (the mpv/KMS arm is future work) — these are decode-only watts.
Any codec other than H.264 for the hw-vs-sw pair (see caveats), any content other than BBB for realtime rows, any resolution other than 1080p.
Whether GStreamer 1.24 unstrands the HEVC blocks (expected, untested — the measured gap predicts roughly 2 W per stream on these boards).