From 860c8dcd505f0d90f89172d18d8b25984d718e08 Mon Sep 17 00:00:00 2001 From: pax Date: Mon, 13 Apr 2026 21:04:54 -0500 Subject: [PATCH] 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. --- booru_viewer/gui/media/video_player.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/booru_viewer/gui/media/video_player.py b/booru_viewer/gui/media/video_player.py index 9089514..cb874ae 100644 --- a/booru_viewer/gui/media/video_player.py +++ b/booru_viewer/gui/media/video_player.py @@ -431,6 +431,16 @@ class VideoPlayer(QWidget): """ m = self._ensure_mpv() 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._media_ready_fired = False self._pending_duration = None @@ -463,6 +473,15 @@ class VideoPlayer(QWidget): self._poll_timer.stop() if self._mpv: 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._duration_label.setText("0:00") self._seek_slider.setRange(0, 0)