video_player: drop hwdec surface pool on stop

On NVIDIA the NVDEC surface pool is the bulk of mpv's idle VRAM
footprint, and keep_open=yes plus the live GL render context pin
it for the widget lifetime. stop() now sets hwdec='no' to release
the pool while idle; play_file() re-arms hwdec='auto' before the
next loadfile so GPU decode is restored on playback.

behavior change from v0.2.6: video VRAM now releases when switching
from a video post to an image post in the same preview pane, instead
of staying pinned for the widget lifetime.
This commit is contained in:
pax 2026-04-13 21:04:54 -05:00
parent 0d75b8a3c8
commit 860c8dcd50

View File

@ -431,6 +431,16 @@ class VideoPlayer(QWidget):
""" """
m = self._ensure_mpv() m = self._ensure_mpv()
self._gl_widget.ensure_gl_init() self._gl_widget.ensure_gl_init()
# Re-arm hardware decoder before each load. stop() sets
# hwdec=no to release the NVDEC/VAAPI surface pool (the bulk
# of mpv's idle VRAM footprint on NVIDIA), so we flip it back
# to auto here so the next loadfile picks up hwdec again.
# mpv re-inits the decoder context on the next frame — swamped
# by the network fetch for uncached videos.
try:
m['hwdec'] = 'auto'
except Exception:
pass
self._current_file = path self._current_file = path
self._media_ready_fired = False self._media_ready_fired = False
self._pending_duration = None self._pending_duration = None
@ -463,6 +473,15 @@ class VideoPlayer(QWidget):
self._poll_timer.stop() self._poll_timer.stop()
if self._mpv: if self._mpv:
self._mpv.command('stop') self._mpv.command('stop')
# Drop the hardware decoder surface pool to release VRAM
# while idle. On NVIDIA the NVDEC pool is the bulk of mpv's
# idle footprint and keep_open=yes + the live GL render
# context would otherwise pin it for the widget lifetime.
# play_file re-arms hwdec='auto' before the next loadfile.
try:
self._mpv['hwdec'] = 'no'
except Exception:
pass
self._time_label.setText("0:00") self._time_label.setText("0:00")
self._duration_label.setText("0:00") self._duration_label.setText("0:00")
self._seek_slider.setRange(0, 0) self._seek_slider.setRange(0, 0)