[vlc-commits] hw: vaapi: remove vaapi global instance

Thomas Guillem git at videolan.org
Tue Jul 4 19:54:17 CEST 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Mon Jul  3 10:57:16 2017 +0200| [2d37a81d5146f90a565fc5d624fdde90458f9889] | committer: Thomas Guillem

hw: vaapi: remove vaapi global instance

We still need a *not global* vaapi instance: struct vlc_vaapi_instance. This
struct holds a VADisplay and a refcount. Every pictures of the vout pool hold
a reference to this struct in order to avoid that the VADisplay is terminated
while being used by pictures.

Filters now get the vaapi instance via filter_NewPicture(). Static filters like
the deinterlace one may not have access to a picture allocated by the vout.
This is fixed by next patches.

Refs #18445

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2d37a81d5146f90a565fc5d624fdde90458f9889
---

 modules/codec/Makefile.am                     |   6 +-
 modules/codec/avcodec/vaapi.c                 |  40 +++++-----
 modules/hw/vaapi/Makefile.am                  |  11 +--
 modules/hw/vaapi/chroma.c                     |  31 +++-----
 modules/hw/vaapi/filters.c                    |  18 +++--
 modules/hw/vaapi/instance.c                   |  93 ----------------------
 modules/hw/vaapi/vlc_vaapi.c                  | 108 +++++++++++++++++++++-----
 modules/hw/vaapi/vlc_vaapi.h                  |  41 ++++++----
 modules/video_output/Makefile.am              |   2 +-
 modules/video_output/opengl/converter_vaapi.c |  29 +++----
 10 files changed, 170 insertions(+), 209 deletions(-)

diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index c3bb6d207a..91c6e257cc 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -379,19 +379,19 @@ libvaapi_drm_plugin_la_SOURCES = \
 libvaapi_drm_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_DRM
 libvaapi_drm_plugin_la_CFLAGS = $(AM_CFLAGS) \
 	$(LIBVA_DRM_CFLAGS) $(AVCODEC_CFLAGS)
-libvaapi_drm_plugin_la_LIBADD = $(LIBVA_DRM_LIBS) libvlc_vaapi_instance.la
+libvaapi_drm_plugin_la_LIBADD = $(LIBVA_DRM_LIBS)
 libvaapi_x11_plugin_la_SOURCES = \
 	codec/avcodec/vaapi.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
 libvaapi_x11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_XLIB
 libvaapi_x11_plugin_la_CFLAGS = $(AM_CFLAGS) \
 	$(LIBVA_X11_CFLAGS) $(X_CFLAGS) $(AVCODEC_CFLAGS)
 libvaapi_x11_plugin_la_LIBADD = $(LIBVA_X11_LIBS) $(X_LIBS) $(X_PRE_LIBS) \
-	-lX11 libvlc_vaapi_instance.la
+	-lX11
 libvaapi_dr_plugin_la_SOURCES = \
 	codec/avcodec/vaapi.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
 libvaapi_dr_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_DR
 libvaapi_dr_plugin_la_CFLAGS = $(AM_CFLAGS) $(AVCODEC_CFLAGS)
-libvaapi_dr_plugin_la_LIBADD = $(LIBVA_LIBS) libvlc_vaapi_instance.la
+libvaapi_dr_plugin_la_LIBADD = $(LIBVA_LIBS)
 if HAVE_AVCODEC_VAAPI
 if HAVE_VAAPI_DRM
 codec_LTLIBRARIES += libvaapi_drm_plugin.la
diff --git a/modules/codec/avcodec/vaapi.c b/modules/codec/avcodec/vaapi.c
index 4f46802400..8c00f216c5 100644
--- a/modules/codec/avcodec/vaapi.c
+++ b/modules/codec/avcodec/vaapi.c
@@ -54,6 +54,7 @@
 
 struct vlc_va_sys_t
 {
+    struct vlc_vaapi_instance *va_inst;
 #ifdef VLC_VA_BACKEND_XLIB
     Display  *p_display_x11;
 #endif
@@ -147,14 +148,14 @@ static void DeleteDR(vlc_va_t *va, void *hwctx)
 
     vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id);
     vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
-    vlc_vaapi_ReleaseInstance(sys->hw_ctx.display);
+    vlc_vaapi_ReleaseInstance(sys->va_inst);
     free(sys);
 }
 
 static int CreateDR(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
                     const es_format_t *fmt, picture_sys_t *p_sys)
 {
-    if (pix_fmt != AV_PIX_FMT_VAAPI_VLD)
+    if (pix_fmt != AV_PIX_FMT_VAAPI_VLD || p_sys == NULL)
         return VLC_EGENERIC;
 
     (void) fmt;
@@ -164,9 +165,9 @@ static int CreateDR(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
     vlc_va_sys_t *sys = NULL;
 
     /* The picture must be allocated by the vout */
-    VADisplay *va_dpy = vlc_vaapi_GetInstance();
-    if (va_dpy == NULL)
-        return VLC_EGENERIC;
+    VADisplay va_dpy;
+    struct vlc_vaapi_instance *va_inst =
+        vlc_vaapi_PicSysHoldInstance(p_sys, &va_dpy);
 
     VASurfaceID *render_targets;
     unsigned num_render_targets =
@@ -188,6 +189,7 @@ static int CreateDR(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
     memset(sys, 0, sizeof (*sys));
 
     /* */
+    sys->va_inst = va_inst;
     sys->hw_ctx.display = va_dpy;
     sys->hw_ctx.config_id = VA_INVALID_ID;
     sys->hw_ctx.context_id = VA_INVALID_ID;
@@ -221,7 +223,7 @@ error:
             vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
         free(sys);
     }
-    vlc_vaapi_ReleaseInstance(va_dpy);
+    vlc_vaapi_ReleaseInstance(va_inst);
     return ret;
 }
 
@@ -254,7 +256,7 @@ static void Delete(vlc_va_t *va, void **hwctx)
     picture_pool_Release(sys->pool);
     vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id);
     vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
-    vlc_vaapi_ReleaseInstance(sys->hw_ctx.display);
+    vlc_vaapi_ReleaseInstance(sys->va_inst);
 #ifdef VLC_VA_BACKEND_XLIB
     XCloseDisplay(sys->p_display_x11);
 #endif
@@ -267,7 +269,7 @@ static void Delete(vlc_va_t *va, void **hwctx)
 static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
                   const es_format_t *fmt, picture_sys_t *p_sys)
 {
-    if (pix_fmt != AV_PIX_FMT_VAAPI_VLD)
+    if (pix_fmt != AV_PIX_FMT_VAAPI_VLD || p_sys)
         return VLC_EGENERIC;
 
     (void) fmt;
@@ -299,6 +301,7 @@ static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
     sys->hw_ctx.config_id = VA_INVALID_ID;
     sys->hw_ctx.context_id = VA_INVALID_ID;
     sys->pool = NULL;
+    sys->va_inst = NULL;
 
     /* Create a VA display */
 #ifdef VLC_VA_BACKEND_XLIB
@@ -337,18 +340,9 @@ static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
         goto error;
     }
 
-    if (vlc_vaapi_Initialize(o, sys->hw_ctx.display))
-    {
-        sys->hw_ctx.display = NULL;
+    sys->va_inst = vlc_vaapi_InitializeInstance(o, sys->hw_ctx.display);
+    if (!sys->va_inst)
         goto error;
-    }
-
-    if (vlc_vaapi_SetInstance(sys->hw_ctx.display))
-    {
-        msg_Err(va, "VAAPI instance already in use");
-        sys->hw_ctx.display = NULL;
-        goto error;
-    }
 
     sys->hw_ctx.config_id =
         vlc_vaapi_CreateConfigChecked(o, sys->hw_ctx.display, i_profile,
@@ -364,7 +358,7 @@ static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
         .i_visible_height = ctx->coded_height
     };
     VASurfaceID *surfaces;
-    sys->pool = vlc_vaapi_PoolNew(o, sys->hw_ctx.display, count,
+    sys->pool = vlc_vaapi_PoolNew(o, sys->va_inst, sys->hw_ctx.display, count,
                                   &surfaces, &vfmt, VA_RT_FORMAT_YUV420, 0);
 
     if (!sys->pool)
@@ -391,8 +385,10 @@ error:
         picture_pool_Release(sys->pool);
     if (sys->hw_ctx.config_id != VA_INVALID_ID)
         vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
-    if (sys->hw_ctx.display != NULL)
-        vlc_vaapi_ReleaseInstance(sys->hw_ctx.display);
+    if (sys->va_inst != NULL)
+        vlc_vaapi_ReleaseInstance(sys->va_inst);
+    else if (sys->hw_ctx.display != NULL)
+        vaTerminate(sys->hw_ctx.display);
 #ifdef VLC_VA_BACKEND_XLIB
     if( sys->p_display_x11 != NULL)
         XCloseDisplay(sys->p_display_x11);
diff --git a/modules/hw/vaapi/Makefile.am b/modules/hw/vaapi/Makefile.am
index d0e595e7c6..563bad2844 100644
--- a/modules/hw/vaapi/Makefile.am
+++ b/modules/hw/vaapi/Makefile.am
@@ -1,23 +1,16 @@
 vaapidir = $(pluginsdir)/vaapi
 
-libvlc_vaapi_instance_la_SOURCES = hw/vaapi/instance.c hw/vaapi/vlc_vaapi.h
-libvlc_vaapi_instance_la_CFLAGS = $(LIBVA_CFLAGS)
-libvlc_vaapi_instance_la_LIBADD = $(LIBVA_LIBS) $(LIBPTHREAD)
-libvlc_vaapi_instance_la_LDFLAGS = -no-undefined	\
-				   -version-info 0:0:0
-
 libvaapi_chroma_plugin_la_SOURCES = hw/vaapi/chroma.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h	\
 				    video_chroma/copy.c video_chroma/copy.h
 libvaapi_chroma_plugin_la_CFLAGS = $(AM_CFLAGS) $(LIBVA_CFLAGS)
-libvaapi_chroma_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS) libvlc_vaapi_instance.la
+libvaapi_chroma_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS)
 
 libvaapi_filters_plugin_la_SOURCES = hw/vaapi/filters.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
 libvaapi_filters_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
 libvaapi_filters_plugin_la_CFLAGS = $(AM_CFLAGS) $(LIBVA_CFLAGS)
-libvaapi_filters_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS) libvlc_vaapi_instance.la
+libvaapi_filters_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS)
 
 if HAVE_VAAPI
-pkglib_LTLIBRARIES += libvlc_vaapi_instance.la
 vaapi_LTLIBRARIES = libvaapi_chroma_plugin.la	\
 		    libvaapi_filters_plugin.la
 endif
diff --git a/modules/hw/vaapi/chroma.c b/modules/hw/vaapi/chroma.c
index 278ecf9e17..a202f3f8aa 100644
--- a/modules/hw/vaapi/chroma.c
+++ b/modules/hw/vaapi/chroma.c
@@ -39,6 +39,7 @@
 
 struct filter_sys_t
 {
+    struct vlc_vaapi_instance *va_inst;
     VADisplay           dpy;
     picture_pool_t *    dest_pics;
     VASurfaceID *       va_surface_ids;
@@ -126,20 +127,10 @@ static picture_t *
 DownloadSurface(filter_t *filter, picture_t *src_pic)
 {
     filter_sys_t *const filter_sys = filter->p_sys;
-    VADisplay           va_dpy;
+    VADisplay           va_dpy = vlc_vaapi_PicGetDisplay(src_pic);
     VAImage             src_img;
     void *              src_buf;
 
-    if (filter_sys->dpy == NULL)
-    {
-        /* Get the instance here since the instance may be not created by the
-         * decoder from Open() */
-        va_dpy = filter_sys->dpy = vlc_vaapi_GetInstance();
-        assert(filter_sys->dpy);
-    }
-    else
-        va_dpy = filter->p_sys->dpy;
-
     picture_t *dest = filter_NewPicture(filter);
     if (!dest)
     {
@@ -310,24 +301,26 @@ static int Open(vlc_object_t *obj)
     filter_sys->derive_failed = false;
     filter_sys->image_fallback_failed = false;
     filter_sys->image_fallback.image_id = VA_INVALID_ID;
+    filter_sys->va_inst = vlc_vaapi_FilterHoldInstance(filter,
+                                                       &filter_sys->dpy);
 
     if (is_upload)
     {
-        filter_sys->dpy = vlc_vaapi_GetInstance();
-        if (filter_sys->dpy == NULL)
+        /* Only upload can't work without a VAAPI instance */
+        if (filter_sys->va_inst == NULL)
         {
             free(filter_sys);
             return VLC_EGENERIC;
         }
 
         filter_sys->dest_pics =
-            vlc_vaapi_PoolNew(obj, filter_sys->dpy, DEST_PICS_POOL_SZ,
-                              &filter_sys->va_surface_ids,
+            vlc_vaapi_PoolNew(obj, filter_sys->va_inst, filter_sys->dpy,
+                              DEST_PICS_POOL_SZ, &filter_sys->va_surface_ids,
                               &filter->fmt_out.video, VA_RT_FORMAT_YUV420,
                               VA_FOURCC_NV12);
         if (!filter_sys->dest_pics)
         {
-            vlc_vaapi_ReleaseInstance(filter_sys->dpy);
+            vlc_vaapi_ReleaseInstance(filter_sys->va_inst);
             free(filter_sys);
             return VLC_EGENERIC;
         }
@@ -344,7 +337,7 @@ static int Open(vlc_object_t *obj)
         if (is_upload)
         {
             picture_pool_Release(filter_sys->dest_pics);
-            vlc_vaapi_ReleaseInstance(filter_sys->dpy);
+            vlc_vaapi_ReleaseInstance(filter_sys->va_inst);
         }
         free(filter_sys);
         return VLC_EGENERIC;
@@ -365,8 +358,8 @@ Close(vlc_object_t *obj)
                                filter_sys->image_fallback.image_id);
     if (filter_sys->dest_pics)
         picture_pool_Release(filter_sys->dest_pics);
-    if (filter_sys->dpy != NULL)
-        vlc_vaapi_ReleaseInstance(filter_sys->dpy);
+    if (filter_sys->va_inst != NULL)
+        vlc_vaapi_ReleaseInstance(filter_sys->va_inst);
     CopyCleanCache(&filter_sys->cache);
 
     free(filter_sys);
diff --git a/modules/hw/vaapi/filters.c b/modules/hw/vaapi/filters.c
index 0af9c0548b..f68c28a3e5 100644
--- a/modules/hw/vaapi/filters.c
+++ b/modules/hw/vaapi/filters.c
@@ -38,6 +38,7 @@
 
 struct  va_filter_desc
 {
+    struct vlc_vaapi_instance *inst;
     VADisplay           dpy;
     VAConfigID          conf;
     VAContextID         ctx;
@@ -298,14 +299,15 @@ Open(filter_t * filter,
     filter_sys->va.conf = VA_INVALID_ID;
     filter_sys->va.ctx = VA_INVALID_ID;
     filter_sys->va.buf = VA_INVALID_ID;
-    filter_sys->va.dpy = vlc_vaapi_GetInstance();
-    if (!filter_sys->va.dpy)
+    filter_sys->va.inst =
+        vlc_vaapi_FilterHoldInstance(filter, &filter_sys->va.dpy);
+    if (!filter_sys->va.inst)
         goto error;
 
     filter_sys->dest_pics =
-        vlc_vaapi_PoolNew(VLC_OBJECT(filter), filter_sys->va.dpy,
-                          DEST_PICS_POOL_SZ, &filter_sys->va.surface_ids,
-                          &filter->fmt_out.video,
+        vlc_vaapi_PoolNew(VLC_OBJECT(filter), filter_sys->va.inst,
+                          filter_sys->va.dpy, DEST_PICS_POOL_SZ,
+                          &filter_sys->va.surface_ids, &filter->fmt_out.video,
                           VA_RT_FORMAT_YUV420, VA_FOURCC_NV12);
     if (!filter_sys->dest_pics)
         goto error;
@@ -376,8 +378,8 @@ error:
     if (filter_sys->va.conf != VA_INVALID_ID)
         vlc_vaapi_DestroyConfig(VLC_OBJECT(filter),
                                 filter_sys->va.dpy, filter_sys->va.conf);
-    if (filter_sys->va.dpy)
-        vlc_vaapi_ReleaseInstance(filter_sys->va.dpy);
+    if (filter_sys->va.inst)
+        vlc_vaapi_ReleaseInstance(filter_sys->va.inst);
     free(filter_sys);
     return VLC_EGENERIC;
 }
@@ -389,7 +391,7 @@ Close(vlc_object_t * obj, filter_sys_t * filter_sys)
     vlc_vaapi_DestroyBuffer(obj, filter_sys->va.dpy, filter_sys->va.buf);
     vlc_vaapi_DestroyContext(obj, filter_sys->va.dpy, filter_sys->va.ctx);
     vlc_vaapi_DestroyConfig(obj, filter_sys->va.dpy, filter_sys->va.conf);
-    vlc_vaapi_ReleaseInstance(filter_sys->va.dpy);
+    vlc_vaapi_ReleaseInstance(filter_sys->va.inst);
     free(filter_sys);
 }
 
diff --git a/modules/hw/vaapi/instance.c b/modules/hw/vaapi/instance.c
deleted file mode 100644
index 3f70fe7ebc..0000000000
--- a/modules/hw/vaapi/instance.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*****************************************************************************
- * instance.c: VAAPI instance management for VLC
- *****************************************************************************
- * Copyright (C) 2017 VLC authors, VideoLAN and VideoLabs
- *
- * Author: Victorien Le Couviour--Tuffet <victorien.lecouviour.tuffet at gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <assert.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <vlc_common.h>
-#include "vlc_vaapi.h"
-
-#pragma GCC visibility push(default)
-
-static struct
-{
-    pthread_mutex_t     lock;
-    VADisplay           dpy;
-    unsigned            refcount;
-} va_instance = { PTHREAD_MUTEX_INITIALIZER, NULL, 0 };
-
-/* Set the VA instance and sets the reference counter to 1. */
-int
-vlc_vaapi_SetInstance(VADisplay dpy)
-{
-    pthread_mutex_lock(&va_instance.lock);
-    if (va_instance.refcount != 0)
-    {
-        vaTerminate(dpy);
-        pthread_mutex_unlock(&va_instance.lock);
-        return VLC_EGENERIC;
-    }
-    va_instance.refcount = 1;
-    va_instance.dpy = dpy;
-    pthread_mutex_unlock(&va_instance.lock);
-    return VLC_SUCCESS;
-}
-
-/* Retrieve the VA instance and increases the reference counter by 1. */
-VADisplay
-vlc_vaapi_GetInstance(void)
-{
-    VADisplay dpy;
-    pthread_mutex_lock(&va_instance.lock);
-    if (!va_instance.dpy)
-        dpy = NULL;
-    else
-    {
-        dpy = va_instance.dpy;
-        ++va_instance.refcount;
-    }
-    pthread_mutex_unlock(&va_instance.lock);
-    return dpy;
-}
-
-/* Decreases the reference counter by 1 and frees the instance if that counter
-   reaches 0. */
-void
-vlc_vaapi_ReleaseInstance(VADisplay *dpy)
-{
-    assert(va_instance.dpy == dpy && va_instance.refcount > 0);
-    (void) dpy;
-
-    pthread_mutex_lock(&va_instance.lock);
-    if (--va_instance.refcount == 0)
-    {
-        vaTerminate(va_instance.dpy);
-        va_instance.dpy = NULL;
-    }
-    pthread_mutex_unlock(&va_instance.lock);
-}
-
-#pragma GCC visibility pop
diff --git a/modules/hw/vaapi/vlc_vaapi.c b/modules/hw/vaapi/vlc_vaapi.c
index 04514eb852..7b9d9c0da2 100644
--- a/modules/hw/vaapi/vlc_vaapi.c
+++ b/modules/hw/vaapi/vlc_vaapi.c
@@ -38,6 +38,7 @@
 #include <vlc_common.h>
 #include <vlc_atomic.h>
 #include <vlc_fourcc.h>
+#include <vlc_filter.h>
 #include <vlc_picture_pool.h>
 
 /* This macro is designed to wrap any VA call, and in case of failure,
@@ -54,19 +55,47 @@
         }                                               \
     } while (0)
 
-/*****************
- * VAAPI display *
- *****************/
+/**************************
+ * VA instance management *
+ **************************/
 
-int
-vlc_vaapi_Initialize(vlc_object_t *o, VADisplay dpy)
+struct vlc_vaapi_instance {
+    VADisplay dpy;
+    atomic_uint pic_refcount;
+};
+
+struct vlc_vaapi_instance *
+vlc_vaapi_InitializeInstance(vlc_object_t *o, VADisplay dpy)
 {
     int major = 0, minor = 0;
     VA_CALL(o, vaInitialize, dpy, &major, &minor);
-    return VLC_SUCCESS;
+    struct vlc_vaapi_instance *inst = malloc(sizeof(*inst));
+
+    if (unlikely(inst == NULL))
+        return NULL;
+    inst->dpy = dpy;
+    atomic_init(&inst->pic_refcount, 1);
+
+    return inst;
 error:
-    vaTerminate(dpy);
-    return VLC_EGENERIC;
+    return NULL;
+}
+
+VADisplay
+vlc_vaapi_HoldInstance(struct vlc_vaapi_instance *inst)
+{
+    atomic_fetch_add(&inst->pic_refcount, 1);
+    return inst->dpy;
+}
+
+void
+vlc_vaapi_ReleaseInstance(struct vlc_vaapi_instance *inst)
+{
+    if (atomic_fetch_sub(&inst->pic_refcount, 1) == 1)
+    {
+        vaTerminate(inst->dpy);
+        free(inst);
+    }
 }
 
 /**************************
@@ -412,8 +441,9 @@ struct vaapi_pic_ctx
 
 struct pic_sys_vaapi_instance
 {
-    atomic_int refcount;
-    VADisplay dpy;
+    atomic_int pic_refcount;
+    VADisplay va_dpy;
+    struct vlc_vaapi_instance *va_inst;
     unsigned num_render_targets;
     VASurfaceID render_targets[];
 };
@@ -430,11 +460,11 @@ pool_pic_destroy_cb(picture_t *pic)
     picture_sys_t *p_sys = pic->p_sys;
     struct pic_sys_vaapi_instance *instance = p_sys->instance;
 
-    if (atomic_fetch_sub(&instance->refcount, 1) == 1)
+    if (atomic_fetch_sub(&instance->pic_refcount, 1) == 1)
     {
-        vaDestroySurfaces(instance->dpy, instance->render_targets,
+        vaDestroySurfaces(instance->va_dpy, instance->render_targets,
                           instance->num_render_targets);
-        vlc_vaapi_ReleaseInstance(instance->dpy);
+        vlc_vaapi_ReleaseInstance(instance->va_inst);
         free(instance);
     }
     free(pic->p_sys);
@@ -471,8 +501,8 @@ pic_sys_ctx_destroy_cb(struct picture_context_t *opaque)
 }
 
 picture_pool_t *
-vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay dpy, unsigned count,
-                  VASurfaceID **render_targets,
+vlc_vaapi_PoolNew(vlc_object_t *o, struct vlc_vaapi_instance *va_inst,
+                  VADisplay dpy, unsigned count, VASurfaceID **render_targets,
                   const video_format_t *restrict fmt,
                   unsigned va_rt_format, int va_force_fourcc)
 {
@@ -481,7 +511,7 @@ vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay dpy, unsigned count,
     if (!instance)
         return NULL;
     instance->num_render_targets = count;
-    atomic_init(&instance->refcount, 0);
+    atomic_init(&instance->pic_refcount, 0);
 
     VASurfaceAttrib *attribs = NULL;
     unsigned num_attribs = 0;
@@ -536,9 +566,9 @@ vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay dpy, unsigned count,
     if (!pool)
         goto error_pic;
 
-    atomic_store(&instance->refcount, count);
-    instance->dpy = vlc_vaapi_GetInstance(); /* Hold a reference on VADisplay */
-    assert(instance->dpy == dpy);
+    atomic_store(&instance->pic_refcount, count);
+    instance->va_dpy = vlc_vaapi_HoldInstance(va_inst);
+    instance->va_inst = va_inst;
 
     *render_targets = instance->render_targets;
     return pool;
@@ -547,7 +577,7 @@ error_pic:
     while (count > 0)
         picture_Release(pics[--count]);
 
-    VA_CALL(o, vaDestroySurfaces, instance->dpy, instance->render_targets,
+    VA_CALL(o, vaDestroySurfaces, instance->va_dpy, instance->render_targets,
             instance->num_render_targets);
 
 error:
@@ -564,9 +594,37 @@ vlc_vaapi_PicSysGetRenderTargets(picture_sys_t *sys,
     return sys->instance->num_render_targets;
 }
 
+struct vlc_vaapi_instance *
+vlc_vaapi_PicSysHoldInstance(picture_sys_t *sys, VADisplay *dpy)
+{
+    assert(sys->instance != NULL);
+    *dpy = vlc_vaapi_HoldInstance(sys->instance->va_inst);
+    return sys->instance->va_inst;
+}
+
+struct vlc_vaapi_instance *
+vlc_vaapi_FilterHoldInstance(filter_t *filter, VADisplay *dpy)
+{
+    picture_t *pic = filter_NewPicture(filter);
+    if (!pic)
+        return NULL;
+
+    struct vlc_vaapi_instance *va_inst =
+        pic->format.i_chroma == VLC_CODEC_VAAPI_420 && pic->p_sys ?
+        vlc_vaapi_PicSysHoldInstance(pic->p_sys, dpy) : NULL;
+    picture_Release(pic);
+
+    return va_inst;
+}
+
+#define ASSERT_VAAPI_CHROMA(pic) do { \
+    assert(pic->format.i_chroma == VLC_CODEC_VAAPI_420); \
+} while(0)
+
 void
 vlc_vaapi_PicAttachContext(picture_t *pic)
 {
+    ASSERT_VAAPI_CHROMA(pic);
     assert(pic->p_sys != NULL);
     assert(pic->context == NULL);
 
@@ -577,7 +635,17 @@ vlc_vaapi_PicAttachContext(picture_t *pic)
 VASurfaceID
 vlc_vaapi_PicGetSurface(picture_t *pic)
 {
+    ASSERT_VAAPI_CHROMA(pic);
     assert(pic->context);
 
     return ((struct vaapi_pic_ctx *)pic->context)->surface;
 }
+
+VADisplay
+vlc_vaapi_PicGetDisplay(picture_t *pic)
+{
+    ASSERT_VAAPI_CHROMA(pic);
+    assert(pic->context);
+
+    return ((struct vaapi_pic_ctx *)pic->context)->picref->p_sys->instance->va_dpy;
+}
diff --git a/modules/hw/vaapi/vlc_vaapi.h b/modules/hw/vaapi/vlc_vaapi.h
index 51dbc69a6c..fc2cfff6a8 100644
--- a/modules/hw/vaapi/vlc_vaapi.h
+++ b/modules/hw/vaapi/vlc_vaapi.h
@@ -35,25 +35,20 @@
  * VA instance management *
  **************************/
 
-/* Allocates the VA instance and sets the reference counter to 1. */
-int
-vlc_vaapi_SetInstance(VADisplay dpy);
+struct vlc_vaapi_instance;
+
+/* Initializes the VADisplay and sets the reference counter to 1. */
+struct vlc_vaapi_instance *
+vlc_vaapi_InitializeInstance(vlc_object_t *o, VADisplay dpy);
 
-/* Retrieve the VA instance and increases the reference counter by 1. */
+/* Increments the VAAPI instance refcount */
 VADisplay
-vlc_vaapi_GetInstance(void);
+vlc_vaapi_HoldInstance(struct vlc_vaapi_instance *inst);
 
-/* Decreases the reference counter by 1 and frees the instance if that counter
-   reaches 0. */
+/* Decrements the VAAPI instance refcount, and call vaTerminate if that counter
+ * reaches 0 */
 void
-vlc_vaapi_ReleaseInstance(VADisplay *);
-
-/*****************
- * VAAPI display *
- *****************/
-
-int
-vlc_vaapi_Initialize(vlc_object_t *o, VADisplay va_dpy);
+vlc_vaapi_ReleaseInstance(struct vlc_vaapi_instance *inst);
 
 /**************************
  * VAAPI create & destroy *
@@ -177,8 +172,8 @@ vlc_vaapi_CreateConfigChecked(vlc_object_t *o, VADisplay dpy,
 /* Create a pool backed by VASurfaceID. render_targets will destroyed once
  * the pool and every pictures are released. */
 picture_pool_t *
-vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay va_dpy,
-                  unsigned count, VASurfaceID **render_targets,
+vlc_vaapi_PoolNew(vlc_object_t *o, struct vlc_vaapi_instance *vainst,
+                  VADisplay dpy, unsigned count, VASurfaceID **render_targets,
                   const video_format_t *restrict fmt,
                   unsigned va_rt_format, int va_force_fourcc);
 
@@ -188,6 +183,14 @@ unsigned
 vlc_vaapi_PicSysGetRenderTargets(picture_sys_t *sys,
                                  VASurfaceID **render_targets);
 
+/* Get and hold the VADisplay instance attached to the picture sys */
+struct vlc_vaapi_instance *
+vlc_vaapi_PicSysHoldInstance(picture_sys_t *sys, VADisplay *dpy);
+
+/* Get and hold the VADisplay instance from a filter */
+struct vlc_vaapi_instance *
+vlc_vaapi_FilterHoldInstance(filter_t *filter, VADisplay *dpy);
+
 /* Attachs the VASurface to the picture context, the picture must be allocated
  * by a vaapi pool (see vlc_vaapi_PoolNew()) */
 void
@@ -197,4 +200,8 @@ vlc_vaapi_PicAttachContext(picture_t *pic);
 VASurfaceID
 vlc_vaapi_PicGetSurface(picture_t *pic);
 
+/* Get the VADisplay attached to the pic (valid while the pic is alive) */
+VADisplay
+vlc_vaapi_PicGetDisplay(picture_t *pic);
+
 #endif /* VLC_VAAPI_H */
diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index 8c89e0bedd..e7cf70ab66 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -24,7 +24,7 @@ OPENGL_COMMONCFLAGS += -DVLCGL_CONV_CVPX
 endif
 if HAVE_EGL
 if HAVE_VAAPI
-OPENGL_COMMONLIBS += $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) libvlc_vaapi_instance.la
+OPENGL_COMMONLIBS += $(LIBVA_LIBS) $(LIBVA_EGL_LIBS)
 OPENGL_COMMONSOURCES += video_output/opengl/converter_vaapi.c \
 	hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
 OPENGL_COMMONCFLAGS += -DVLCGL_CONV_VA
diff --git a/modules/video_output/opengl/converter_vaapi.c b/modules/video_output/opengl/converter_vaapi.c
index 03987a8e34..1775cd0cb1 100644
--- a/modules/video_output/opengl/converter_vaapi.c
+++ b/modules/video_output/opengl/converter_vaapi.c
@@ -47,6 +47,7 @@
 
 struct priv
 {
+    struct vlc_vaapi_instance *vainst;
     VADisplay vadpy;
     VASurfaceID *va_surface_ids;
     PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
@@ -225,9 +226,9 @@ tc_vaegl_get_pool(const opengl_tex_converter_t *tc, unsigned requested_count)
     struct priv *priv = tc->priv;
 
     picture_pool_t *pool =
-        vlc_vaapi_PoolNew(VLC_OBJECT(tc->gl), priv->vadpy, requested_count,
-                          &priv->va_surface_ids, &tc->fmt, VA_RT_FORMAT_YUV420,
-                          VA_FOURCC_NV12);
+        vlc_vaapi_PoolNew(VLC_OBJECT(tc->gl), priv->vainst, priv->vadpy,
+                          requested_count, &priv->va_surface_ids, &tc->fmt,
+                          VA_RT_FORMAT_YUV420, VA_FOURCC_NV12);
     if (!pool)
         return NULL;
 
@@ -252,12 +253,13 @@ tc_vaegl_release(const opengl_tex_converter_t *tc)
     if (priv->last.pic != NULL)
         vaegl_release_last_pic(tc, priv);
 
-    vlc_vaapi_ReleaseInstance(priv->vadpy);
+    vlc_vaapi_ReleaseInstance(priv->vainst);
 
 #ifdef HAVE_VA_X11
     if (priv->x11dpy != NULL)
         XCloseDisplay(priv->x11dpy);
 #endif
+
     free(tc->priv);
 }
 
@@ -324,31 +326,24 @@ tc_vaegl_init(opengl_tex_converter_t *tc, VADisplay *vadpy)
     tc->pf_release = tc_vaegl_release;
     tc->pf_get_pool = tc_vaegl_get_pool;
 
-    if (vlc_vaapi_Initialize(VLC_OBJECT(tc->gl), priv->vadpy))
+    priv->vainst = vlc_vaapi_InitializeInstance(VLC_OBJECT(tc->gl), priv->vadpy);
+    if (priv->vainst == NULL)
         goto error;
 
     if (tc_va_check_interop_blacklist(tc, priv->vadpy))
         goto error;
 
-    if (vlc_vaapi_SetInstance(priv->vadpy))
-    {
-        msg_Err(tc->gl, "VAAPI instance already in use");
-        vadpy = NULL;
-        goto error;
-    }
-
     tc->fshader = opengl_fragment_shader_init(tc, GL_TEXTURE_2D, VLC_CODEC_NV12,
                                               tc->fmt.space);
     if (tc->fshader == 0)
-    {
-        vlc_vaapi_ReleaseInstance(priv->vadpy);
-        vadpy = NULL;
         goto error;
-    }
+
     return VLC_SUCCESS;
 
 error:
-    if (vadpy != NULL)
+    if (priv->vainst)
+        vlc_vaapi_ReleaseInstance(priv->vainst);
+    else
         vaTerminate(vadpy);
     free(tc->priv);
     return ret;



More information about the vlc-commits mailing list