[vlc-devel] [PATCH 22/31] video context: make the video context structure private

Steve Lhomme robux4 at ycbcr.xyz
Fri Jul 5 16:20:01 CEST 2019


The video context will be passed to various modules up to the display where it
will be ultimately released when the last associated picture will be released.
We need a destructor to do this final release. And it needs to be refcounted.

Add a Create function to ensure we set a destructor if needed.

By default the video context holds a reference to the matching decoder device.
This reference is released with the video context.
---
 include/vlc_picture.h                         | 19 ++++++--
 modules/video_chroma/d3d11_fmt.h              | 24 ++++++++++
 modules/video_chroma/d3d9_fmt.h               | 23 ++++++++++
 modules/video_output/opengl/converter.h       |  4 +-
 modules/video_output/opengl/converter_vaapi.c | 24 ++++++++--
 modules/video_output/opengl/converter_vdpau.c | 25 ++++++++---
 modules/video_output/opengl/vout_helper.c     |  2 +-
 modules/video_output/win32/direct3d11.c       |  6 +--
 modules/video_output/win32/direct3d9.c        | 11 ++---
 src/audio_output/filters.c                    |  9 ++--
 src/input/decoder.c                           |  6 +--
 src/input/decoder_helpers.c                   | 45 +++++++++++++++++++
 src/libvlccore.sym                            |  4 ++
 13 files changed, 168 insertions(+), 34 deletions(-)

diff --git a/include/vlc_picture.h b/include/vlc_picture.h
index c314c9c207..d4b474c1e0 100644
--- a/include/vlc_picture.h
+++ b/include/vlc_picture.h
@@ -80,10 +80,21 @@ typedef struct picture_buffer_t
 } picture_buffer_t;
 
 typedef struct vlc_decoder_device vlc_decoder_device;
-typedef struct vlc_video_context
-{
-    vlc_decoder_device *device;
-} vlc_video_context;
+typedef struct vlc_video_context vlc_video_context;
+
+VLC_API vlc_video_context * vlc_video_context_Create(vlc_decoder_device *device,
+                                        void *opaque, void (*destroy)(void *));
+
+VLC_API vlc_video_context *vlc_video_context_Hold(vlc_video_context *);
+VLC_API void vlc_video_context_Release(vlc_video_context *);
+
+/**
+ * Get the decoder device used by the device context.
+ *
+ * This will increment the refcount of the decoder device.
+ */
+VLC_API vlc_decoder_device *vlc_video_context_GetDevice(vlc_video_context *);
+
 
 /**
  * Video picture
diff --git a/modules/video_chroma/d3d11_fmt.h b/modules/video_chroma/d3d11_fmt.h
index 7a57b4aa69..9d018b48fb 100644
--- a/modules/video_chroma/d3d11_fmt.h
+++ b/modules/video_chroma/d3d11_fmt.h
@@ -23,6 +23,8 @@
 #ifndef VLC_VIDEOCHROMA_D3D11_FMT_H_
 #define VLC_VIDEOCHROMA_D3D11_FMT_H_
 
+#include <vlc_codec.h>
+
 #include <d3d11.h>
 #include <d3dcompiler.h>
 
@@ -94,6 +96,28 @@ static inline bool is_d3d11_opaque(vlc_fourcc_t chroma)
            chroma == VLC_CODEC_D3D11_OPAQUE_BGRA;
 }
 
+static inline d3d11_decoder_device_t *GetD3D11OpaqueDevice(vlc_decoder_device *device)
+{
+    if (device == NULL || device->type != VLC_DECODER_DEVICE_D3D11VA)
+        return NULL;
+    return device->opaque;
+}
+
+static inline d3d11_decoder_device_t *GetD3D11OpaqueContext(vlc_video_context *vctx)
+{
+    vlc_decoder_device *device = vctx ? vlc_video_context_GetDevice(vctx) : NULL;
+    if (unlikely(device == NULL))
+        return NULL;
+    d3d11_decoder_device_t *res = NULL;
+    if (device->type == VLC_DECODER_DEVICE_D3D11VA)
+    {
+        assert(device->opaque != NULL);
+        res = GetD3D11OpaqueDevice(device);
+    }
+    vlc_decoder_device_Release(device);
+    return res;
+}
+
 void AcquireD3D11PictureSys(picture_sys_d3d11_t *p_sys);
 
 void ReleaseD3D11PictureSys(picture_sys_d3d11_t *p_sys);
diff --git a/modules/video_chroma/d3d9_fmt.h b/modules/video_chroma/d3d9_fmt.h
index 94fe506405..0ae18b1f65 100644
--- a/modules/video_chroma/d3d9_fmt.h
+++ b/modules/video_chroma/d3d9_fmt.h
@@ -24,6 +24,7 @@
 #define VLC_VIDEOCHROMA_D3D9_FMT_H_
 
 #include <vlc_picture.h>
+#include <vlc_codec.h>
 
 #define COBJMACROS
 #include <d3d9.h>
@@ -84,6 +85,28 @@ static inline bool is_d3d9_opaque(vlc_fourcc_t chroma)
     }
 }
 
+static inline d3d9_decoder_device_t *GetD3D9OpaqueDevice(vlc_decoder_device *device)
+{
+    if (device == NULL || device->type != VLC_DECODER_DEVICE_DXVA2)
+        return NULL;
+    return device->opaque;
+}
+
+static inline d3d9_decoder_device_t *GetD3D9OpaqueContext(vlc_video_context *vctx)
+{
+    vlc_decoder_device *device = vctx ? vlc_video_context_GetDevice(vctx) : NULL;
+    if (unlikely(device == NULL))
+        return NULL;
+    d3d9_decoder_device_t *res = NULL;
+    if (device->type == VLC_DECODER_DEVICE_DXVA2)
+    {
+        assert(device->opaque != NULL);
+        res = GetD3D9OpaqueDevice(device);
+    }
+    vlc_decoder_device_Release(device);
+    return res;
+}
+
 static inline void AcquireD3D9PictureSys(picture_sys_d3d9_t *p_sys)
 {
     IDirect3DSurface9_AddRef(p_sys->surface);
diff --git a/modules/video_output/opengl/converter.h b/modules/video_output/opengl/converter.h
index a84e6c6f4a..53e8f6d437 100644
--- a/modules/video_output/opengl/converter.h
+++ b/modules/video_output/opengl/converter.h
@@ -259,8 +259,8 @@ struct opengl_tex_converter_t
     /* Pointer to object gl, set by the caller */
     vlc_gl_t *gl;
 
-    /* Pointer to decoder device, set by the caller (can be NULL) */
-    vlc_decoder_device *dec_device;
+    /* Pointer to decoder video context, set by the caller (can be NULL) */
+    vlc_video_context *vctx;
 
     /* libplacebo context, created by the caller (optional) */
     struct pl_context *pl_ctx;
diff --git a/modules/video_output/opengl/converter_vaapi.c b/modules/video_output/opengl/converter_vaapi.c
index 455ab51bbc..21b822ae36 100644
--- a/modules/video_output/opengl/converter_vaapi.c
+++ b/modules/video_output/opengl/converter_vaapi.c
@@ -222,10 +222,12 @@ tc_vaegl_get_pool(const opengl_tex_converter_t *tc, unsigned requested_count)
     vlc_object_t *o = VLC_OBJECT(tc->gl);
     struct priv *priv = tc->priv;
 
+    vlc_decoder_device *dec_device = vlc_video_context_GetDevice(tc->vctx);
     picture_pool_t *pool =
-        vlc_vaapi_PoolNew(VLC_OBJECT(tc->gl), tc->dec_device, priv->vadpy,
+        vlc_vaapi_PoolNew(VLC_OBJECT(tc->gl), dec_device, priv->vadpy,
                           requested_count, &priv->va_surface_ids, &tc->fmt,
                           true);
+    vlc_decoder_device_Release(dec_device);
     if (!pool)
         return NULL;
 
@@ -328,20 +330,31 @@ Open(vlc_object_t *obj)
 {
     opengl_tex_converter_t *tc = (void *) obj;
 
-    if (tc->dec_device == NULL
-     || tc->dec_device->type != VLC_DECODER_DEVICE_VAAPI
+    if (tc->vctx == NULL)
+        return VLC_EGENERIC;
+    vlc_decoder_device *dec_device = vlc_video_context_GetDevice(tc->vctx);
+    if (dec_device->type != VLC_DECODER_DEVICE_VAAPI
      || !vlc_vaapi_IsChromaOpaque(tc->fmt.i_chroma)
      || tc->gl->ext != VLC_GL_EXT_EGL
      || tc->gl->egl.createImageKHR == NULL
      || tc->gl->egl.destroyImageKHR == NULL)
+    {
+        vlc_decoder_device_Release(dec_device);
         return VLC_EGENERIC;
+    }
 
     if (!vlc_gl_StrHasToken(tc->glexts, "GL_OES_EGL_image"))
+    {
+        vlc_decoder_device_Release(dec_device);
         return VLC_EGENERIC;
+    }
 
     const char *eglexts = tc->gl->egl.queryString(tc->gl, EGL_EXTENSIONS);
     if (eglexts == NULL || !vlc_gl_StrHasToken(eglexts, "EGL_EXT_image_dma_buf_import"))
+    {
+        vlc_decoder_device_Release(dec_device);
         return VLC_EGENERIC;
+    }
 
     struct priv *priv = tc->priv = calloc(1, sizeof(struct priv));
     if (unlikely(tc->priv == NULL))
@@ -372,7 +385,7 @@ Open(vlc_object_t *obj)
     if (priv->glEGLImageTargetTexture2DOES == NULL)
         goto error;
 
-    priv->vadpy = tc->dec_device->opaque;
+    priv->vadpy = dec_device->opaque;
     assert(priv->vadpy != NULL);
 
     if (tc_va_check_interop_blacklist(tc, priv->vadpy))
@@ -386,8 +399,11 @@ Open(vlc_object_t *obj)
     tc->pf_update  = tc_vaegl_update;
     tc->pf_get_pool = tc_vaegl_get_pool;
 
+    vlc_decoder_device_Release(dec_device);
+
     return VLC_SUCCESS;
 error:
+    vlc_decoder_device_Release(dec_device);
     free(priv);
     return VLC_EGENERIC;
 }
diff --git a/modules/video_output/opengl/converter_vdpau.c b/modules/video_output/opengl/converter_vdpau.c
index b76878a05d..17e59c71d4 100644
--- a/modules/video_output/opengl/converter_vdpau.c
+++ b/modules/video_output/opengl/converter_vdpau.c
@@ -62,9 +62,13 @@ static picture_pool_t *
 tc_vdpau_gl_get_pool(opengl_tex_converter_t const *tc,
                      unsigned int requested_count)
 {
-    return vlc_vdp_output_pool_create(tc->dec_device->opaque,
+    vlc_decoder_device *dec_device = vlc_video_context_GetDevice(tc->vctx);
+    picture_pool_t *pool;
+    pool = vlc_vdp_output_pool_create(dec_device->opaque,
                                       VDP_RGBA_FORMAT_B8G8R8A8,
                                       &tc->fmt, requested_count);
+    vlc_decoder_device_Release(dec_device);
+    return pool;
 }
 
 static int
@@ -112,26 +116,33 @@ Close(vlc_object_t *obj)
 {
     opengl_tex_converter_t *tc = (void *)obj;
     _glVDPAUFiniNV(); assert(tc->vt->GetError() == GL_NO_ERROR);
-    vdp_release_x11(tc->dec_device->opaque);
+    vlc_decoder_device *dec_device = vlc_video_context_GetDevice(tc->vctx);
+    vdp_release_x11(dec_device->opaque);
+    vlc_decoder_device_Release(dec_device);
 }
 
 static int
 Open(vlc_object_t *obj)
 {
     opengl_tex_converter_t *tc = (void *) obj;
-    if (tc->dec_device == NULL
-     || tc->dec_device->type != VLC_DECODER_DEVICE_VDPAU
+    if (tc->vctx == NULL)
+        return VLC_EGENERIC;
+    vlc_decoder_device *dec_device = vlc_video_context_GetDevice(tc->vctx);
+    if (dec_device->type != VLC_DECODER_DEVICE_VDPAU
      || (tc->fmt.i_chroma != VLC_CODEC_VDPAU_VIDEO_420
       && tc->fmt.i_chroma != VLC_CODEC_VDPAU_VIDEO_422
       && tc->fmt.i_chroma != VLC_CODEC_VDPAU_VIDEO_444)
      || !vlc_gl_StrHasToken(tc->glexts, "GL_NV_vdpau_interop")
      || tc->gl->surface->type != VOUT_WINDOW_TYPE_XID)
+    {
+        vlc_decoder_device_Release(dec_device);
         return VLC_EGENERIC;
+    }
 
     tc->fmt.i_chroma = VLC_CODEC_VDPAU_OUTPUT;
 
     VdpDevice device;
-    vdp_t *vdp = tc->dec_device->opaque;
+    vdp_t *vdp = dec_device->opaque;
     vdp_hold_x11(vdp, &device);
 
     void *vdp_gpa;
@@ -139,6 +150,7 @@ Open(vlc_object_t *obj)
                              VDP_FUNC_ID_GET_PROC_ADDRESS, &vdp_gpa)
         != VDP_STATUS_OK)
     {
+        vlc_decoder_device_Release(dec_device);
         vdp_release_x11(vdp);
         return VLC_EGENERIC;
     }
@@ -147,6 +159,7 @@ Open(vlc_object_t *obj)
     _##fct = vlc_gl_GetProcAddress(tc->gl, #fct); \
     if (!_##fct) \
     { \
+        vlc_decoder_device_Release(dec_device); \
         vdp_release_x11(vdp); \
         return VLC_EGENERIC; \
     }
@@ -163,6 +176,8 @@ Open(vlc_object_t *obj)
 
     INTEROP_CALL(glVDPAUInitNV, (void *)(uintptr_t)device, vdp_gpa);
 
+    vlc_decoder_device_Release(dec_device);
+
     tc->fshader = opengl_fragment_shader_init(tc, GL_TEXTURE_2D,
                                               VLC_CODEC_RGB32,
                                               COLOR_SPACE_UNDEF);
diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c
index b37b653257..8e692eae5a 100644
--- a/modules/video_output/opengl/vout_helper.c
+++ b/modules/video_output/opengl/vout_helper.c
@@ -588,7 +588,7 @@ opengl_init_program(vout_display_opengl_t *vgl, vlc_video_context *context,
         if (desc->plane_count == 0)
         {
             /* Opaque chroma: load a module to handle it */
-            tc->dec_device = context ? context->device : NULL;
+            tc->vctx = context;
             tc->p_module = module_need_var(tc, "glconv", "glconv");
         }
 
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 3434d37457..b1ba6bc72e 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -329,10 +329,8 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
     sys->startEndRenderingCb = var_InheritAddress( vd, "vout-cb-make-current" );
     sys->selectPlaneCb       = var_InheritAddress( vd, "vout-cb-select-plane" );
 
-    d3d11_decoder_device_t *d3d11_decoder = NULL;
-    if ( context && context->device->type == VLC_DECODER_DEVICE_D3D11VA )
-        d3d11_decoder = context->device->opaque;
-    if ( d3d11_decoder == NULL || d3d11_decoder->device == NULL )
+    d3d11_decoder_device_t *d3d11_decoder = GetD3D11OpaqueContext(context);
+    if ( d3d11_decoder == NULL )
     {
         msg_Err(vd, "Missing D3D device");
         goto error;
diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index 7fafcb7a07..a3745e1da7 100644
--- a/modules/video_output/win32/direct3d9.c
+++ b/modules/video_output/win32/direct3d9.c
@@ -41,7 +41,6 @@
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
-#include <vlc_codec.h>
 #include <vlc_vout_display.h>
 
 #include <vlc/libvlc.h>
@@ -1664,10 +1663,8 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
         sys->startEndRenderingCb = NULL;
     }
 
-    d3d9_decoder_device_t *d3d9_decoder = NULL;
-    if ( context && context->device->type == VLC_DECODER_DEVICE_DXVA2 )
-        d3d9_decoder = context->device->opaque;
-    if ( d3d9_decoder == NULL || d3d9_decoder->device == NULL )
+    d3d9_decoder_device_t *d3d9_decoder = GetD3D9OpaqueContext(context);
+    if ( d3d9_decoder == NULL )
     {
         msg_Err(vd, "Missing D3D device");
         goto error;
@@ -1926,9 +1923,9 @@ GLConvOpen(vlc_object_t *obj)
 
     HRESULT hr;
     int adapter = -1;
-    if (tc->dec_device->type == VLC_DECODER_DEVICE_DXVA2)
+    d3d9_decoder_device_t *d3d9_decoder = GetD3D9OpaqueContext( tc->vctx );
+    if ( d3d9_decoder != NULL )
     {
-        d3d9_decoder_device_t *d3d9_decoder = tc->dec_device->opaque;
         D3D9_CloneExternal(&priv->hd3d, d3d9_decoder->device);
         adapter = d3d9_decoder->adapter;
     }
diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c
index 44cb1ca371..ffd2e97694 100644
--- a/src/audio_output/filters.c
+++ b/src/audio_output/filters.c
@@ -399,14 +399,15 @@ vout_thread_t *aout_filter_GetVout(filter_t *filter, const video_format_t *fmt)
     vlc_decoder_device *dec_dev = NULL;
     if (vout_RequestDevice(&cfg, &dec_dev) == 0)
     {
-        vlc_video_context vctx;
-        vctx.device = dec_dev;
-        if (vout_RequestDisplay(&cfg, &vctx, NULL) == 0)
+        vlc_video_context *vctx = vlc_video_context_Create(dec_dev, NULL, NULL);
+        if (vout_RequestDisplay(&cfg, vctx, NULL) == 0)
         {
-            /* FIXME unused for now */
             vlc_decoder_device_Release(dec_dev);
+            /* don't keep it for now */
+            vlc_video_context_Release(vctx);
             return vout;
         }
+        vlc_video_context_Release(vctx);
     }
 
     vlc_decoder_device_Release(dec_dev);
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 43fa380da4..ee7e63fb47 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -617,9 +617,9 @@ static int vout_update_format( decoder_t *p_dec )
         .dpb_size = dpb_size + p_dec->i_extra_picture_buffers + 1,
         .mouse_event = MouseEvent, .mouse_opaque = p_dec,
     };
-    vlc_video_context vctx;
-    vctx.device = p_dec->init_device;
-    int res = input_resource_GetDisplay( p_owner->p_resource, &vctx, &cfg);
+    vlc_video_context *vctx = vlc_video_context_Create( p_dec->init_device, NULL, NULL );
+    int res = input_resource_GetDisplay( p_owner->p_resource, vctx, &cfg);
+    vlc_video_context_Release(vctx);
 
     vlc_mutex_lock( &p_owner->lock );
     p_owner->fmt.video.i_chroma = p_dec->fmt_out.i_codec;
diff --git a/src/input/decoder_helpers.c b/src/input/decoder_helpers.c
index b8257e62a6..c37e9f50df 100644
--- a/src/input/decoder_helpers.c
+++ b/src/input/decoder_helpers.c
@@ -31,6 +31,7 @@
 #include <vlc_atomic.h>
 #include <vlc_meta.h>
 #include <vlc_modules.h>
+#include <vlc_picture.h>
 #include "libvlc.h"
 
 void decoder_Init( decoder_t *p_dec, const es_format_t *restrict p_fmt )
@@ -181,3 +182,47 @@ vlc_decoder_device_Release(vlc_decoder_device *device)
         vlc_object_delete(device);
     }
 }
+
+/* video context */
+
+struct vlc_video_context
+{
+    vlc_atomic_rc_t    rc;
+    vlc_decoder_device *device;
+    void *opaque;
+    void (*destroy)(void *);
+};
+
+vlc_video_context * vlc_video_context_Create(vlc_decoder_device *device,
+                                          void *opaque, void (*destroy)(void *))
+{
+    vlc_video_context *vctx = malloc(sizeof(*vctx));
+    if (unlikely(vctx == NULL))
+        return NULL;
+    vlc_atomic_rc_init( &vctx->rc );
+    vctx->device = vlc_decoder_device_Hold( device );
+    vctx->opaque = opaque;
+    vctx->destroy = destroy;
+    return vctx;
+}
+
+vlc_video_context *vlc_video_context_Hold(vlc_video_context *vctx)
+{
+    vlc_atomic_rc_inc( &vctx->rc );
+    return vctx;
+}
+
+void vlc_video_context_Release(vlc_video_context *vctx)
+{
+    if ( vlc_atomic_rc_dec( &vctx->rc ) )
+    {
+        vlc_decoder_device_Release( vctx->device );
+        if ( vctx->destroy )
+            vctx->destroy( vctx->opaque );
+    }
+}
+
+vlc_decoder_device* vlc_video_context_GetDevice(vlc_video_context *vctx)
+{
+    return vlc_decoder_device_Hold( vctx->device );
+}
\ No newline at end of file
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 4fbd6f7d4f..bae8efe401 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -940,3 +940,7 @@ vlc_media_tree_Unlock
 vlc_media_tree_Find
 vlc_media_tree_Preparse
 vlc_viewpoint_to_4x4
+vlc_video_context_Create
+vlc_video_context_Hold
+vlc_video_context_Release
+vlc_video_context_GetDevice
-- 
2.17.1



More information about the vlc-devel mailing list