fix(viewer): switch x86 mpv VO to gpu+wayland for stable playback

dmabuf-wayland segfaults reliably under the viewer's launch pattern
(background subprocess, no controlling tty) on mpv 0.40.0 +
wlroots-0.18 + libplacebo. The crash happens between hwdec
initialization and file open — visible in --log-file output, the log
truncates right after the last hwdec driver probe ("vulkan: This is
not a libplacebo vulkan gpu api context") and never reaches the
demuxer stage. Earlier validation succeeded only because mpv was
invoked interactively from a tty; the viewer's subprocess.Popen path
hits the bug every time.

Switch to --vo=gpu --gpu-context=wayland — the generic GL-over-Wayland
path mpv supports on every x86 GPU with Mesa or vendor GL drivers.
With --hwdec=auto-safe, VAAPI-capable hardware (Intel iHD/i965, AMD
radeonsi, ...) still decodes in hardware and hands frames to the GL
context as DMA-BUFs via mpv's dmabuf-interop-gl; software decode keeps
working via the same VO for codecs without HW support. The trade-off
is one extra GL upload step versus dmabuf-wayland's direct scanout,
which is fine on iGPU and the only path that's actually stable.

Verified on x86 Debian 13 with cage 0.2 + mpv 0.40.0:
- H.264 1080p60 (Big Buck Bunny sunflower) plays end-to-end, log
  reports "Using hardware decoding (vaapi)", iHD driver loads, CPU
  settles at ~25% (software decode would peg multiple cores).
- HEVC 1080p30 plays end-to-end, hevc_qsv / VAAPI engaged.
- Zero dropped frames over 30s.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Viktor Petersson
2026-05-12 11:17:04 +00:00
parent 6c348f1163
commit 63f31c6fac
2 changed files with 15 additions and 10 deletions

View File

@@ -69,16 +69,20 @@ class MPVMediaPlayer(MediaPlayer):
# x86 runs under `cage` (a wlroots kiosk compositor — see
# bin/start_viewer.sh); cage holds DRM master, so --vo=drm is
# denied. Route mpv through dmabuf-wayland so decoded frames go
# straight to the compositor as DMA-BUFs (wp_linux_dmabuf_v1)
# for direct scanout, sidestepping the GL upload/swap path that
# stalls under wlroots. Paired with --hwdec=auto-safe below,
# VAAPI-capable iGPUs decode straight into NV12 DMA-BUFs for
# zero-copy playback; software decode still works via the same
# VO. Pi boards (pi4-64/pi5) keep --vo=drm — they own the
# framebuffer directly with no compositor in front.
# denied. Route mpv through the GL VO over a Wayland EGL
# context, which is the generic path mpv supports on every x86
# GPU with Mesa or vendor GL drivers. Paired with
# --hwdec=auto-safe, VAAPI-capable iGPUs (Intel iHD/i965, AMD
# radeonsi, …) decode in hardware and hand frames to the GL
# context as DMA-BUFs via dmabuf-interop-gl; software decode
# still works via the same VO for codecs without HW support.
# --vo=dmabuf-wayland would skip the GL upload entirely but
# segfaults under cage in the viewer's background-spawn path
# (mpv 0.40.0 + wlroots-0.18 + libplacebo dies between hwdec
# init and file open). Pi boards (pi4-64/pi5) keep --vo=drm —
# they own the framebuffer directly with no compositor.
if device_type == 'x86':
vo_args = ['--vo=dmabuf-wayland']
vo_args = ['--vo=gpu', '--gpu-context=wayland']
else:
vo_args = ['--vo=drm']

View File

@@ -115,7 +115,8 @@ def test_play_uses_wayland_vo_on_x86(
mpv.player.play()
args, _ = mock_popen.call_args
assert '--vo=dmabuf-wayland' in args[0]
assert '--vo=gpu' in args[0]
assert '--gpu-context=wayland' in args[0]
assert '--vo=drm' not in args[0]