[vlc-commits] [Git][videolan/vlc][master] 2 commits: avcodec: va: re-use previous vctx when possible

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat Nov 8 10:44:04 UTC 2025



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
5827e946 by Thomas Guillem at 2025-11-08T11:30:17+01:00
avcodec: va: re-use previous vctx when possible

Add cfg->vctx_prev, only valid from ffmpeg_RecreateVa() (for VAAPI).
This will be used to use the previous context when a format change is
triggered by a flush.

- - - - -
b1596c8d by Thomas Guillem at 2025-11-08T11:30:17+01:00
avcodec: vaapi: try to keep previous vctx

Keep the previous vctx if present and if it is using the same
format/size.

This will allow to avoid recreating a vout because of a vctx change (on
flush).

Fixes #29434

- - - - -


3 changed files:

- modules/codec/avcodec/va.h
- modules/codec/avcodec/vaapi.c
- modules/codec/avcodec/video.c


Changes:

=====================================
modules/codec/avcodec/va.h
=====================================
@@ -59,6 +59,15 @@ struct vlc_va_cfg
      */
     video_format_t *video_fmt_out;
 
+    /**
+    * Pointer to the previous video context
+    *
+    * Only valid if use_hwframes is true and when recreating the va module.
+    * This context can be re-used (held, and set to vctx_out) if the internal
+    * format/size matches the new cfg.
+    */
+    vlc_video_context *vctx_prev;
+
     /**
      * Pointer to the used video context
      *


=====================================
modules/codec/avcodec/vaapi.c
=====================================
@@ -246,6 +246,38 @@ error:
     return VLC_EGENERIC;
 }
 
+static int AVHWFramesContextCompare(const AVHWFramesContext *c1,
+                                    const AVHWFramesContext *c2)
+{
+    return c1->width == c2->width && c1->height == c2->height &&
+           c1->format == c2->format && c1->sw_format == c2->sw_format &&
+           c1->initial_pool_size == c2->initial_pool_size ? 0 : 1;
+}
+
+static vlc_video_context *
+ReuseVideoContext(vlc_video_context *vctx, AVBufferRef *hwframes_ref_new)
+{
+    if (vctx == NULL)
+        return NULL;
+
+    struct vaapi_vctx *vaapi_vctx =
+    vlc_video_context_GetPrivate(vctx, VLC_VIDEO_CONTEXT_VAAPI);
+
+    AVHWFramesContext *hwframes_ctx_prev =
+        (AVHWFramesContext*)vaapi_vctx->hwframes_ref->data;
+
+    AVHWFramesContext *hwframes_ctx_new =
+        (AVHWFramesContext*)hwframes_ref_new->data;
+
+    if (AVHWFramesContextCompare(hwframes_ctx_prev, hwframes_ctx_new) != 0)
+        return NULL;
+
+    vctx = vlc_video_context_Hold(vctx);
+    av_buffer_unref(&vaapi_vctx->hwframes_ref);
+    vaapi_vctx->hwframes_ref = hwframes_ref_new;
+    return vctx;
+}
+
 static int Create(vlc_va_t *va, struct vlc_va_cfg *cfg)
 {
     AVCodecContext *ctx = cfg->avctx;
@@ -360,23 +392,27 @@ static int Create(vlc_va_t *va, struct vlc_va_cfg *cfg)
         return VLC_EGENERIC;
     }
 
-    vlc_video_context *vctx =
-        vlc_video_context_Create(dec_device, VLC_VIDEO_CONTEXT_VAAPI,
-                                 sizeof(struct vaapi_vctx), &vaapi_ctx_ops);
+    vlc_video_context *vctx = ReuseVideoContext(cfg->vctx_prev, hwframes_ref);
     if (vctx == NULL)
     {
-        av_buffer_unref(&hwframes_ref);
-        av_buffer_unref(&ctx->hw_frames_ctx);
-        return VLC_EGENERIC;
-    }
+        vctx = 
+            vlc_video_context_Create(dec_device, VLC_VIDEO_CONTEXT_VAAPI,
+                                    sizeof(struct vaapi_vctx), &vaapi_ctx_ops);
+        if (vctx == NULL)
+        {
+            av_buffer_unref(&hwframes_ref);
+            av_buffer_unref(&ctx->hw_frames_ctx);
+            return VLC_EGENERIC;
+        }
 
-    struct vaapi_vctx *vaapi_vctx =
-        vlc_video_context_GetPrivate(vctx, VLC_VIDEO_CONTEXT_VAAPI);
+        struct vaapi_vctx *vaapi_vctx =
+            vlc_video_context_GetPrivate(vctx, VLC_VIDEO_CONTEXT_VAAPI);
 
-    vaapi_vctx->va_dpy = va_dpy;
-    vaapi_vctx->hwframes_ref = hwframes_ref;
-    vlc_sem_init(&vaapi_vctx->pool_sem, hwframes_ctx->initial_pool_size);
-    vaapi_vctx->dynamic_pool = hwframes_ctx->initial_pool_size < 1;
+        vaapi_vctx->va_dpy = va_dpy;
+        vaapi_vctx->hwframes_ref = hwframes_ref;
+        vlc_sem_init(&vaapi_vctx->pool_sem, hwframes_ctx->initial_pool_size);
+        vaapi_vctx->dynamic_pool = hwframes_ctx->initial_pool_size < 1;
+    }
 
     msg_Info(va, "Using %s", vaQueryVendorString(va_dpy));
 


=====================================
modules/codec/avcodec/video.c
=====================================
@@ -750,7 +750,8 @@ static void ffmpeg_CloseVa(decoder_t *p_dec, AVCodecContext *context)
 static int ffmpeg_OpenVa(decoder_t *p_dec, AVCodecContext *p_context,
                          enum AVPixelFormat hwfmt,
                          const AVPixFmtDescriptor *src_desc,
-                         vlc_decoder_device *dec_device)
+                         vlc_decoder_device *dec_device,
+                         vlc_video_context *vctx)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
@@ -762,6 +763,7 @@ static int ffmpeg_OpenVa(decoder_t *p_dec, AVCodecContext *p_context,
         .fmt_in = p_dec->fmt_in,
         .dec_device = dec_device,
         .video_fmt_out = &p_dec->fmt_out.video,
+        .vctx_prev = vctx,
         .vctx_out = NULL,
         .use_hwframes = false,
         .extra_pictures = 0,
@@ -792,8 +794,10 @@ static int ffmpeg_RecreateVa(decoder_t *p_dec, AVCodecContext *p_context,
                              enum AVPixelFormat swfmt)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    assert(p_sys->use_hwframes);
     assert(p_sys->vctx_out != NULL);
 
+    vlc_video_context *vctx = vlc_video_context_Hold(p_sys->vctx_out);
     vlc_decoder_device *dec_device =
         vlc_video_context_HoldDevice(p_sys->vctx_out);
 
@@ -802,9 +806,10 @@ static int ffmpeg_RecreateVa(decoder_t *p_dec, AVCodecContext *p_context,
     const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(swfmt);
 
     int ret = ffmpeg_OpenVa(p_dec, p_context, p_sys->pix_fmt,
-                            src_desc, dec_device);
+                            src_desc, dec_device, vctx);
     if (dec_device != NULL)
         vlc_decoder_device_Release(dec_device);
+    vlc_video_context_Release(vctx);
     return ret;
 }
 
@@ -921,7 +926,8 @@ int InitVideoHwDec( vlc_object_t *obj )
         if (ret != VLC_SUCCESS)
             continue;
 
-        ret = ffmpeg_OpenVa(p_dec, p_context, hwfmts[i], src_desc, dec_device);
+        ret = ffmpeg_OpenVa(p_dec, p_context, hwfmts[i], src_desc, dec_device,
+                            NULL);
         if (dec_device != NULL)
             vlc_decoder_device_Release(dec_device);
 
@@ -2140,7 +2146,7 @@ no_reuse:
         if (ret != VLC_SUCCESS)
             continue;
 
-        ret = ffmpeg_OpenVa(p_dec, p_context, hwfmt, src_desc, dec_device);
+        ret = ffmpeg_OpenVa(p_dec, p_context, hwfmt, src_desc, dec_device, NULL);
         if (dec_device != NULL)
             vlc_decoder_device_Release(dec_device);
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/29b0a17233ea014cb5576541adbe8ad48cdc5ca7...b1596c8d18854c1f693388e9f2dff0a46792ef98

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/29b0a17233ea014cb5576541adbe8ad48cdc5ca7...b1596c8d18854c1f693388e9f2dff0a46792ef98
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list