[vlc-devel] [PATCH 11/16] avcodec: vdpau: put the video context data in its private storage

Steve Lhomme robux4 at ycbcr.xyz
Thu Oct 24 16:20:25 CEST 2019


video_context_private is now accessible from GetVDPAUContextPrivate().

The resources will be released when the video context is released by the last
picture or when the module is closed if there wasn't any picture in flight.
---
 modules/hw/vdpau/avcodec.c | 72 +++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 24 deletions(-)

diff --git a/modules/hw/vdpau/avcodec.c b/modules/hw/vdpau/avcodec.c
index 60677412121..e43700d9e45 100644
--- a/modules/hw/vdpau/avcodec.c
+++ b/modules/hw/vdpau/avcodec.c
@@ -48,7 +48,6 @@ struct video_context_private
 
 struct vlc_va_sys_t
 {
-    struct video_context_private vctx_priv;
     VdpDevice device;
     VdpChromaType type;
     void *hwaccel_context;
@@ -57,32 +56,40 @@ struct vlc_va_sys_t
     vlc_video_context *vctx;
 };
 
+static inline struct video_context_private *GetVDPAUContextPrivate(vlc_video_context *vctx)
+{
+    return (struct video_context_private *)
+        vlc_video_context_GetPrivate( vctx, VLC_VIDEO_CONTEXT_VDPAU );
+}
+
 static vlc_vdp_video_field_t *CreateSurface(vlc_va_t *va)
 {
     vlc_va_sys_t *sys = va->sys;
+    struct video_context_private *vctx_priv = GetVDPAUContextPrivate(sys->vctx);
     VdpVideoSurface surface;
     VdpStatus err;
 
-    err = vdp_video_surface_create(sys->vctx_priv.vdp, sys->device, sys->type,
+    err = vdp_video_surface_create(vctx_priv->vdp, sys->device, sys->type,
                                    sys->width, sys->height, &surface);
     if (err != VDP_STATUS_OK)
     {
         msg_Err(va, "%s creation failure: %s", "video surface",
-                vdp_get_error_string(sys->vctx_priv.vdp, err));
+                vdp_get_error_string(vctx_priv->vdp, err));
         return NULL;
     }
 
-    vlc_vdp_video_field_t *field = vlc_vdp_video_create(sys->vctx_priv.vdp, surface);
+    vlc_vdp_video_field_t *field = vlc_vdp_video_create(vctx_priv->vdp, surface);
     if (unlikely(field == NULL))
-        vdp_video_surface_destroy(sys->vctx_priv.vdp, surface);
+        vdp_video_surface_destroy(vctx_priv->vdp, surface);
     return field;
 }
 
 static vlc_vdp_video_field_t *GetSurface(vlc_va_sys_t *sys)
 {
     vlc_vdp_video_field_t *f;
+    struct video_context_private *vctx_priv = GetVDPAUContextPrivate(sys->vctx);
 
-    for (unsigned i = 0; (f = sys->vctx_priv.pool[i]) != NULL; i++)
+    for (unsigned i = 0; (f = vctx_priv->pool[i]) != NULL; i++)
     {
         uintptr_t expected = 1;
 
@@ -129,9 +136,6 @@ static void Close(vlc_va_t *va)
 {
     vlc_va_sys_t *sys = va->sys;
 
-    for (unsigned i = 0; sys->vctx_priv.pool[i] != NULL; i++)
-        vlc_vdp_video_destroy(sys->vctx_priv.pool[i]);
-    vdp_release_x11(sys->vctx_priv.vdp);
     vlc_video_context_Release(sys->vctx);
     if (sys->hwaccel_context)
         av_free(sys->hwaccel_context);
@@ -140,6 +144,18 @@ static void Close(vlc_va_t *va)
 
 static const struct vlc_va_operations ops = { Lock, Close, };
 
+static void DestroyVDPAUVideoContext(void *private)
+{
+    struct video_context_private *vctx_priv = private;
+    for (unsigned i = 0; vctx_priv->pool[i] != NULL; i++)
+        vlc_vdp_video_destroy(vctx_priv->pool[i]);
+    vdp_release_x11(vctx_priv->vdp);
+}
+
+const struct vlc_video_context_operations vdpau_vctx_ops = {
+    DestroyVDPAUVideoContext,
+};
+
 static int Open(vlc_va_t *va, AVCodecContext *avctx, const AVPixFmtDescriptor *desc,
                 enum PixelFormat pix_fmt,
                 const es_format_t *fmt, vlc_decoder_device *dec_device,
@@ -191,21 +207,32 @@ static int Open(vlc_va_t *va, AVCodecContext *avctx, const AVPixFmtDescriptor *d
             break;
     }
     const unsigned refs = codec_refs + 2 * avctx->thread_count + 5;
-    vlc_va_sys_t *sys = malloc(sizeof (*sys)
-                               + (refs + 1) * sizeof (sys->vctx_priv.pool[0]));
+    vlc_va_sys_t *sys = malloc(sizeof (*sys));
     if (unlikely(sys == NULL))
        return VLC_ENOMEM;
 
+    sys->vctx = vlc_video_context_Create( dec_device, VLC_VIDEO_CONTEXT_VDPAU,
+                                          sizeof(struct video_context_private) +
+                                           (refs + 1) * sizeof (vlc_vdp_video_field_t),
+                                          &vdpau_vctx_ops );
+    if (sys->vctx == NULL)
+    {
+        free(sys);
+        return VLC_ENOMEM;
+    }
+
+    struct video_context_private *vctx_priv = GetVDPAUContextPrivate(sys->vctx);
+
     sys->type = type;
     sys->width = width;
     sys->height = height;
     sys->hwaccel_context = NULL;
-    sys->vctx_priv.vdp = GetVDPAUOpaqueDevice(dec_device);
-    vdp_hold_x11(sys->vctx_priv.vdp, &sys->device);
+    vctx_priv->vdp = GetVDPAUOpaqueDevice(dec_device);
+    vdp_hold_x11(vctx_priv->vdp, &sys->device);
 
     unsigned flags = AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH;
 
-    err = vdp_get_proc_address(sys->vctx_priv.vdp, sys->device,
+    err = vdp_get_proc_address(vctx_priv->vdp, sys->device,
                                VDP_FUNC_ID_GET_PROC_ADDRESS, &func);
     if (err != VDP_STATUS_OK)
         goto error;
@@ -218,27 +245,23 @@ static int Open(vlc_va_t *va, AVCodecContext *avctx, const AVPixFmtDescriptor *d
     unsigned i = 0;
     while (i < refs)
     {
-        sys->vctx_priv.pool[i] = CreateSurface(va);
-        if (sys->vctx_priv.pool[i] == NULL)
+        vctx_priv->pool[i] = CreateSurface(va);
+        if (vctx_priv->pool[i] == NULL)
             break;
         i++;
     }
-    sys->vctx_priv.pool[i] = NULL;
+    vctx_priv->pool[i] = NULL;
 
     if (i < refs)
     {
         msg_Err(va, "not enough video RAM");
         while (i > 0)
-            vlc_vdp_video_destroy(sys->vctx_priv.pool[--i]);
+            vlc_vdp_video_destroy(vctx_priv->pool[--i]);
         goto error;
     }
 
-    sys->vctx = vlc_video_context_Create( dec_device, VLC_VIDEO_CONTEXT_VDPAU, 0, NULL );
-    if (sys->vctx == NULL)
-        goto error;
-
     const char *infos;
-    if (vdp_get_information_string(sys->vctx_priv.vdp, &infos) == VDP_STATUS_OK)
+    if (vdp_get_information_string(vctx_priv->vdp, &infos) == VDP_STATUS_OK)
         msg_Info(va, "Using %s", infos);
 
     *vtcx_out = sys->vctx;
@@ -246,9 +269,10 @@ static int Open(vlc_va_t *va, AVCodecContext *avctx, const AVPixFmtDescriptor *d
     return VLC_SUCCESS;
 
 error:
+    if (sys->vctx)
+        vlc_video_context_Release(sys->vctx);
     if (sys->hwaccel_context)
         av_free(sys->hwaccel_context);
-    vdp_release_x11(sys->vctx_priv.vdp);
     free(sys);
     return VLC_EGENERIC;
 }
-- 
2.17.1



More information about the vlc-devel mailing list