[vlc-commits] [Git][videolan/vlc][master] 21 commits: vdpau: name and document the device context

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Thu Jan 13 10:27:25 UTC 2022



Hugo Beauzée-Luyssen pushed to branch master at VideoLAN / VLC


Commits:
743929f4 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: name and document the device context

- - - - -
86e2881d by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau/chroma: keep the device context directly

- - - - -
724a978b by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: allocate picture contexts from video context

- - - - -
cd341e3c by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: hold video context when creating a field

- - - - -
04a580f1 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: move surface pool back to VA

Surfaces logically reference their device (i.e. the video context).
So long as they are stored in the video context, a cycle of
cross-references leads to an enormous memory leak.

- - - - -
81c602df by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: remove dead code

- - - - -
4fa9fbc3 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: really reference the context from fields

Video surfaces in the VA pool do not really need to reference the video
context of their own as they cannot outlive the VA, which already
references the video context.

But referencing the context anyway is cleaner and allows for further
simplifications.

- - - - -
7c27f01b by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: hold the video context while cloning a picture context

- - - - -
29f94a71 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: remove dead code

- - - - -
7c097bec by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: frames need not hold the instance

Frames (video surfaces) are always held by one of more fields. Fields
already hold the video context, which holds the decoder device, which
holds the instance.

So frames can rely on any one of their referencing fields to hold the
video context.

- - - - -
7ba2e950 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: remove redundant instance from frame structure

- - - - -
739d7a46 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: pass video context to allocate output surfaces

- - - - -
4b464e8d by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: output surfaces hold context rather than instance

- - - - -
5c8b1436 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: remove dead code

- - - - -
98632a96 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: remove in-process instance sharing

Originally, both the decoder and the video output would instantiate
VDPAU devices on their own. The process-global list was necessary to
force paired decoder and output to use the same VDPAU instance: they
were matched by server name and screen number.

Now that all components in a given pipeline obtain the VDPAU instance
from a shared decoder device, this trick is no longer necessary.

Incidentally, VDPAU instances would also harmlessly but nevertheless
unnecessarily be shared between independent pipelines within the same
process using the same X11 screen. We can ignore this.

- - - - -
aebb6314 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: remove the instance reference count

This was necessary for sharing and for vlc_hold_x11(), but they were
both removed.

Note that the list is still used to match a display to an instance, so
it cannot be removed quite yet.

- - - - -
fae5234d by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: add working decoder device module (fixes #26385)

This associates the correct X11 screen and does not depend on GL for no
particular reasons.

- - - - -
0a82e325 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
opengl: remove VDPAU decoder device

- - - - -
46130b4f by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: remove dead code

- - - - -
4913808e by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: don't initialise Xlib twice

By the time we got to this piece of code, this had already been taken
care of by the decoder device.

- - - - -
647bafc3 by Rémi Denis-Courmont at 2022-01-13T10:02:51+00:00
vdpau: identify the driver only once

- - - - -


9 changed files:

- modules/hw/vdpau/Makefile.am
- modules/hw/vdpau/avcodec.c
- modules/hw/vdpau/chroma.c
- + modules/hw/vdpau/device.c
- modules/hw/vdpau/display.c
- − modules/hw/vdpau/instance.c
- modules/hw/vdpau/picture.c
- modules/hw/vdpau/vlc_vdpau.h
- modules/video_output/opengl/interop_vdpau.c


Changes:

=====================================
modules/hw/vdpau/Makefile.am
=====================================
@@ -1,6 +1,6 @@
 vdpaudir = $(pluginsdir)/vdpau
 
-libvlc_vdpau_la_SOURCES = hw/vdpau/vlc_vdpau.c hw/vdpau/vlc_vdpau.h hw/vdpau/instance.c
+libvlc_vdpau_la_SOURCES = hw/vdpau/vlc_vdpau.c hw/vdpau/vlc_vdpau.h
 libvlc_vdpau_la_CFLAGS = $(VDPAU_CFLAGS)
 libvlc_vdpau_la_LIBADD = $(X_LIBS) $(X_PRE_LIBS) -lX11 $(LIBDL)
 libvlc_vdpau_la_LDFLAGS = \
@@ -8,11 +8,15 @@ libvlc_vdpau_la_LDFLAGS = \
 	-export-symbols-regex ^vdp_ \
 	-version-info 0:0:0
 
+libvdpau_instance_plugin_la_SOURCES = hw/vdpau/device.c
+libvdpau_instance_plugin_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) $(VDPAU_CFLAGS)
+libvdpau_instance_plugin_la_LIBADD = libvlc_vdpau.la \
+	$(X_LIBS) $(X_PRE_LIBS) -lX11
+
 libvdpau_avcodec_plugin_la_SOURCES = hw/vdpau/avcodec.c hw/vdpau/picture.c
 libvdpau_avcodec_plugin_la_CFLAGS = $(AM_CFLAGS) \
-	$(X_CFLAGS) $(AVCODEC_CFLAGS) $(VDPAU_CFLAGS)
-libvdpau_avcodec_plugin_la_LIBADD = libvlc_vdpau.la \
-	$(X_LIBS) $(X_PRE_LIBS) -lX11 $(AVCODEC_LIBS)
+	$(AVCODEC_CFLAGS) $(VDPAU_CFLAGS)
+libvdpau_avcodec_plugin_la_LIBADD = libvlc_vdpau.la $(AVCODEC_LIBS)
 
 libvdpau_deinterlace_plugin_la_SOURCES = hw/vdpau/deinterlace.c hw/vdpau/picture.c
 libvdpau_deinterlace_plugin_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS)
@@ -38,7 +42,8 @@ libvdpau_display_plugin_la_LIBADD = libvlc_vdpau.la libvlc_xcb_events.la \
 
 if HAVE_VDPAU
 pkglib_LTLIBRARIES += libvlc_vdpau.la
-vdpau_LTLIBRARIES = libvdpau_deinterlace_plugin.la libvdpau_adjust_plugin.la \
+vdpau_LTLIBRARIES = libvdpau_instance_plugin.la \
+	libvdpau_deinterlace_plugin.la libvdpau_adjust_plugin.la \
 	libvdpau_sharpen_plugin.la libvdpau_chroma_plugin.la
 if HAVE_XCB
 vdpau_LTLIBRARIES += libvdpau_display_plugin.la


=====================================
modules/hw/vdpau/avcodec.c
=====================================
@@ -36,7 +36,6 @@
 #include <vlc_fourcc.h>
 #include <vlc_picture.h>
 #include <vlc_codec.h>
-#include <vlc_xlib.h>
 #include "vlc_vdpau.h"
 #include "../../codec/avcodec/va.h"
 
@@ -47,14 +46,9 @@ typedef struct
     uint32_t width;
     uint32_t height;
     vlc_video_context *vctx;
+    vlc_vdp_video_field_t *pool[];
 } vlc_va_sys_t;
 
-static inline vlc_vdp_video_field_t **GetVDPAUContextPrivate(vlc_video_context *vctx)
-{
-    return (vlc_vdp_video_field_t **)
-        vlc_video_context_GetPrivate( vctx, VLC_VIDEO_CONTEXT_VDPAU );
-}
-
 static vlc_vdp_video_field_t *CreateSurface(vlc_va_t *va, vdpau_decoder_device_t *vdpau_decoder)
 {
     vlc_va_sys_t *sys = va->sys;
@@ -70,7 +64,7 @@ static vlc_vdp_video_field_t *CreateSurface(vlc_va_t *va, vdpau_decoder_device_t
         return NULL;
     }
 
-    vlc_vdp_video_field_t *field = vlc_vdp_video_create(vdpau_decoder->vdp, surface);
+    vlc_vdp_video_field_t *field = vlc_vdp_video_create(sys->vctx, surface);
     if (unlikely(field == NULL))
         vdp_video_surface_destroy(vdpau_decoder->vdp, surface);
     return field;
@@ -79,9 +73,8 @@ static vlc_vdp_video_field_t *CreateSurface(vlc_va_t *va, vdpau_decoder_device_t
 static vlc_vdp_video_field_t *GetSurface(vlc_va_sys_t *sys)
 {
     vlc_vdp_video_field_t *f;
-    vlc_vdp_video_field_t **pool = GetVDPAUContextPrivate(sys->vctx);
 
-    for (unsigned i = 0; (f = pool[i]) != NULL; i++)
+    for (unsigned i = 0; (f = sys->pool[i]) != NULL; i++)
     {
         uintptr_t expected = 1;
 
@@ -118,9 +111,6 @@ static int Lock(vlc_va_t *va, picture_t *pic, AVCodecContext *ctx, AVFrame *fram
     if (field == NULL)
         return VLC_ENOMEM;
 
-    field->context.copy = VideoSurfaceCloneWithContext;
-    field->context.vctx = vlc_video_context_Hold(sys->vctx);
-
     pic->context = &field->context;
     frame->data[3] = (void *)(uintptr_t)field->frame->surface;
     return VLC_SUCCESS;
@@ -130,6 +120,9 @@ static void Close(vlc_va_t *va)
 {
     vlc_va_sys_t *sys = va->sys;
 
+    for (size_t i = 0; sys->pool[i] != NULL; i++)
+        vlc_vdp_video_destroy(sys->pool[i]);
+
     vlc_video_context_Release(sys->vctx);
     if (sys->hwaccel_context)
         av_free(sys->hwaccel_context);
@@ -138,15 +131,8 @@ static void Close(vlc_va_t *va)
 
 static const struct vlc_va_operations ops = { Lock, Close, };
 
-static void DestroyVDPAUVideoContext(void *private)
-{
-    vlc_vdp_video_field_t **pool = private;
-    for (unsigned i = 0; pool[i] != NULL; i++)
-        vlc_vdp_video_destroy(pool[i]);
-}
-
 const struct vlc_video_context_operations vdpau_vctx_ops = {
-    DestroyVDPAUVideoContext,
+    NULL,
 };
 
 static int Open(vlc_va_t *va, AVCodecContext *avctx, enum AVPixelFormat hwfmt, const AVPixFmtDescriptor *desc,
@@ -182,12 +168,6 @@ static int Open(vlc_va_t *va, AVCodecContext *avctx, enum AVPixelFormat hwfmt, c
             return VLC_EGENERIC;
     }
 
-    if (!vlc_xlib_init(VLC_OBJECT(va)))
-    {
-        msg_Err(va, "Xlib is required for VDPAU");
-        return VLC_EGENERIC;
-    }
-
     unsigned codec_refs;
     switch (avctx->codec_id)
     {
@@ -204,22 +184,22 @@ static int Open(vlc_va_t *va, AVCodecContext *avctx, enum AVPixelFormat hwfmt, c
             codec_refs = 2;
             break;
     }
+
     const unsigned refs = codec_refs + 2 * avctx->thread_count + 5;
-    vlc_va_sys_t *sys = malloc(sizeof (*sys));
+    size_t extra = (refs + 1) * sizeof (vlc_vdp_video_field_t *);
+
+    vlc_va_sys_t *sys = malloc(sizeof (*sys) + extra);
     if (unlikely(sys == NULL))
        return VLC_ENOMEM;
 
-    sys->vctx = vlc_video_context_Create( dec_device, VLC_VIDEO_CONTEXT_VDPAU,
-                                           (refs + 1) * sizeof (vlc_vdp_video_field_t *),
-                                          &vdpau_vctx_ops );
+    sys->vctx = vlc_video_context_Create(dec_device, VLC_VIDEO_CONTEXT_VDPAU,
+                                         0, &vdpau_vctx_ops);
     if (sys->vctx == NULL)
     {
         free(sys);
         return VLC_ENOMEM;
     }
 
-    vlc_vdp_video_field_t **pool = GetVDPAUContextPrivate(sys->vctx);
-
     sys->type = type;
     sys->width = width;
     sys->height = height;
@@ -241,23 +221,20 @@ static int Open(vlc_va_t *va, AVCodecContext *avctx, enum AVPixelFormat hwfmt, c
     unsigned i = 0;
     while (i < refs)
     {
-        pool[i] = CreateSurface(va, vdpau_decoder);
-        if (pool[i] == NULL)
+        sys->pool[i] = CreateSurface(va, vdpau_decoder);
+        if (sys->pool[i] == NULL)
             break;
         i++;
     }
-    pool[i] = NULL;
+    sys->pool[i] = NULL;
 
     if (i < refs)
     {
         msg_Err(va, "not enough video RAM");
-        goto error;
+        Close(va);
+        return VLC_ENOMEM;
     }
 
-    const char *infos;
-    if (vdp_get_information_string(vdpau_decoder->vdp, &infos) == VDP_STATUS_OK)
-        msg_Info(va, "Using %s", infos);
-
     *vtcx_out = sys->vctx;
     va->ops = &ops;
     return VLC_SUCCESS;


=====================================
modules/hw/vdpau/chroma.c
=====================================
@@ -39,8 +39,7 @@
 
 typedef struct
 {
-    vdp_t *vdp;
-    VdpDevice device;
+    struct vlc_vdp_device *device;
     VdpVideoMixer mixer;
     VdpChromaType chroma;
     VdpYCbCrFormat format;
@@ -62,6 +61,7 @@ static VdpStatus MixerSetupColors(filter_t *filter, const VdpProcamp *procamp,
                                   VdpCSCMatrix *restrict csc)
 {
     vlc_vdp_mixer_t *sys = filter->p_sys;
+    vdp_t *vdp = sys->device->vdp;
     VdpStatus err;
     /* XXX: add some margin for padding... */
     VdpColorStandard std;
@@ -81,11 +81,11 @@ static VdpStatus MixerSetupColors(filter_t *filter, const VdpProcamp *procamp,
                 std = VDP_COLOR_STANDARD_ITUR_BT_601;
     }
 
-    err = vdp_generate_csc_matrix(sys->vdp, procamp, std, csc);
+    err = vdp_generate_csc_matrix(vdp, procamp, std, csc);
     if (err != VDP_STATUS_OK)
     {
         msg_Err(filter, "video %s failure: %s", "color space matrix",
-                vdp_get_error_string(sys->vdp, err));
+                vdp_get_error_string(vdp, err));
         return err;
     }
 
@@ -110,6 +110,8 @@ static VdpStatus MixerSetupColors(filter_t *filter, const VdpProcamp *procamp,
 static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
 {
     vlc_vdp_mixer_t *sys = filter->p_sys;
+    vdp_t *vdp = sys->device->vdp;
+    VdpDevice device = sys->device->device;
     VdpVideoMixer mixer;
     VdpStatus err;
     VdpBool ok;
@@ -122,8 +124,7 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
     bool ivtc = false;
     if (algo == VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL)
     {
-        err = vdp_video_mixer_query_feature_support(sys->vdp, sys->device,
-                                                    algo, &ok);
+        err = vdp_video_mixer_query_feature_support(vdp, device, algo, &ok);
         if (err == VDP_STATUS_OK && ok == VDP_TRUE)
             msg_Dbg(filter, "using video mixer %s feature",
                     "temporal-spatial deinterlace");
@@ -132,8 +133,7 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
     }
     if (algo == VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL)
     {
-        err = vdp_video_mixer_query_feature_support(sys->vdp, sys->device,
-                                                    algo, &ok);
+        err = vdp_video_mixer_query_feature_support(vdp, device, algo, &ok);
         if (err == VDP_STATUS_OK && ok == VDP_TRUE)
             msg_Dbg(filter, "using video mixer %s feature",
                     "temporal deinterlace");
@@ -146,7 +146,7 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
         ivtc = var_InheritBool(filter, "vdpau-ivtc");
         if (ivtc)
         {
-            err = vdp_video_mixer_query_feature_support(sys->vdp, sys->device,
+            err = vdp_video_mixer_query_feature_support(vdp, device,
                                 VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, &ok);
             if (err == VDP_STATUS_OK && ok == VDP_TRUE)
                 msg_Dbg(filter, "using video mixer %s feature",
@@ -158,7 +158,7 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
     const float noise = var_InheritFloat(filter, "vdpau-noise-reduction");
     if (noise > 0.f)
     {
-        err = vdp_video_mixer_query_feature_support(sys->vdp, sys->device,
+        err = vdp_video_mixer_query_feature_support(vdp, device,
                                  VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, &ok);
         if (err == VDP_STATUS_OK && ok == VDP_TRUE)
         {
@@ -167,7 +167,7 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
         }
     }
 
-    err = vdp_video_mixer_query_feature_support(sys->vdp, sys->device,
+    err = vdp_video_mixer_query_feature_support(vdp, device,
                                        VDP_VIDEO_MIXER_FEATURE_SHARPNESS, &ok);
     if (err == VDP_STATUS_OK && ok == VDP_TRUE)
     {
@@ -180,7 +180,7 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
     while (level > 0)
     {
 
-        err = vdp_video_mixer_query_feature_support(sys->vdp, sys->device,
+        err = vdp_video_mixer_query_feature_support(vdp, device,
                                                     offset + level, &ok);
         if (err == VDP_STATUS_OK && ok == VDP_TRUE)
         {
@@ -203,12 +203,12 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
                              : filter->fmt_in.video.i_height;
     const void *values[3] = { &width, &height, &sys->chroma, };
 
-    err = vdp_video_mixer_create(sys->vdp, sys->device, featc, featv,
+    err = vdp_video_mixer_create(vdp, device, featc, featv,
                                  3, parms, values, &mixer);
     if (err != VDP_STATUS_OK)
     {
         msg_Err(filter, "video %s %s failure: %s", "mixer", "creation",
-                vdp_get_error_string(sys->vdp, err));
+                vdp_get_error_string(vdp, err));
         return VDP_INVALID_HANDLE;
     }
 
@@ -261,20 +261,20 @@ static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
         for (unsigned i = 0; i < featc; i++)
             enablev[i] = VDP_TRUE;
 
-        err = vdp_video_mixer_set_feature_enables(sys->vdp, mixer,
+        err = vdp_video_mixer_set_feature_enables(vdp, mixer,
                                                   featc, featv, enablev);
         if (err != VDP_STATUS_OK)
             msg_Err(filter, "video %s %s failure: %s", "mixer", "features",
-                    vdp_get_error_string(sys->vdp, err));
+                    vdp_get_error_string(vdp, err));
     }
 
     if (attrc > 0)
     {
-        err = vdp_video_mixer_set_attribute_values(sys->vdp, mixer,
+        err = vdp_video_mixer_set_attribute_values(vdp, mixer,
                                                    attrc, attrv, valv);
         if (err != VDP_STATUS_OK)
             msg_Err(filter, "video %s %s failure: %s", "mixer", "attributes",
-                    vdp_get_error_string(sys->vdp, err));
+                    vdp_get_error_string(vdp, err));
     }
 
     return mixer;
@@ -337,21 +337,23 @@ static picture_t *VideoExport(filter_t *filter, picture_t *src, picture_t *dst,
 static picture_t *VideoImport(filter_t *filter, picture_t *src)
 {
     vlc_vdp_mixer_t *sys = filter->p_sys;
+    vdp_t *vdp = sys->device->vdp;
+    VdpDevice device = sys->device->device;
     VdpVideoSurface surface;
     VdpStatus err;
 
-    if (sys->vdp == NULL)
+    if (vdp == NULL)
         goto drop;
 
     /* Create surface (TODO: reuse?) */
-    err = vdp_video_surface_create(sys->vdp, sys->device, sys->chroma,
+    err = vdp_video_surface_create(vdp, device, sys->chroma,
                                    filter->fmt_in.video.i_width,
                                    filter->fmt_in.video.i_visible_height,
                                    &surface);
     if (err != VDP_STATUS_OK)
     {
         msg_Err(filter, "video %s %s failure: %s", "surface", "creation",
-                vdp_get_error_string(sys->vdp, err));
+                vdp_get_error_string(vdp, err));
         goto drop;
     }
 
@@ -382,12 +384,12 @@ static picture_t *VideoImport(filter_t *filter, picture_t *src)
                 + (filter->fmt_in.video.i_y_offset / 2) * src->p[i].i_pitch;
     }
 
-    err = vdp_video_surface_put_bits_y_cb_cr(sys->vdp, surface, sys->format,
+    err = vdp_video_surface_put_bits_y_cb_cr(vdp, surface, sys->format,
                                              planes, pitches);
     if (err != VDP_STATUS_OK)
     {
         msg_Err(filter, "video %s %s failure: %s", "surface", "import",
-                vdp_get_error_string(sys->vdp, err));
+                vdp_get_error_string(vdp, err));
         goto error;
     }
 
@@ -416,7 +418,7 @@ static picture_t *VideoImport(filter_t *filter, picture_t *src)
     picture_CopyProperties(dst, src);
     picture_Release(src);
 
-    err = vlc_vdp_video_attach(sys->vdp, surface, filter->vctx_out, dst);
+    err = vlc_vdp_video_attach(filter->vctx_out, surface, dst);
     if (unlikely(err != VDP_STATUS_OK))
     {
         picture_Release(dst);
@@ -424,7 +426,7 @@ static picture_t *VideoImport(filter_t *filter, picture_t *src)
     }
     return dst;
 error:
-    vdp_video_surface_destroy(sys->vdp, surface);
+    vdp_video_surface_destroy(vdp, surface);
 drop:
     picture_Release(src);
     return NULL;
@@ -448,6 +450,7 @@ static picture_context_t *OutputSurfaceClone(picture_context_t *ctx)
 static picture_t *Render(filter_t *filter, picture_t *src, bool import)
 {
     vlc_vdp_mixer_t *sys = filter->p_sys;
+    vdp_t *vdp = sys->device->vdp;
     picture_t *dst = NULL;
     VdpStatus err;
 
@@ -493,7 +496,7 @@ static picture_t *Render(filter_t *filter, picture_t *src, bool import)
     };
 
     vlc_vdp_output_surface_t *p_sys = dst->p_sys;
-    assert(p_sys != NULL && p_sys->vdp == sys->vdp);
+    assert(p_sys != NULL && p_sys->vctx == filter->vctx_out);
     dst->date = pic_f->date;
     dst->b_force = pic_f->b_force;
     dst->b_still = pic_f->b_still;
@@ -507,11 +510,11 @@ static picture_t *Render(filter_t *filter, picture_t *src, bool import)
         f->sharpen != 0.f,
     };
 
-    err = vdp_video_mixer_set_feature_enables(sys->vdp, sys->mixer,
+    err = vdp_video_mixer_set_feature_enables(vdp, sys->mixer,
                   sizeof (features) / sizeof (features[0]), features, enables);
     if (err != VDP_STATUS_OK)
         msg_Err(filter, "video %s %s failure: %s", "mixer", "features",
-                vdp_get_error_string(sys->vdp, err));
+                vdp_get_error_string(vdp, err));
 
     /* Configure mixer depending on upstream video filters */
     VdpVideoMixerAttribute attrs[2] = {
@@ -534,11 +537,11 @@ static picture_t *Render(filter_t *filter, picture_t *src, bool import)
         count++;
     }
 
-    err = vdp_video_mixer_set_attribute_values(sys->vdp, sys->mixer,
+    err = vdp_video_mixer_set_attribute_values(vdp, sys->mixer,
                                                count, attrs, values);
     if (err != VDP_STATUS_OK)
         msg_Err(filter, "video %s %s failure: %s", "mixer", "attributes",
-                vdp_get_error_string(sys->vdp, err));
+                vdp_get_error_string(vdp, err));
 
     /* Check video orientation, allocate intermediate surface if needed */
     bool swap = false;
@@ -575,21 +578,21 @@ static picture_t *Render(filter_t *filter, picture_t *src, bool import)
         VdpRGBAFormat fmt;
         uint32_t width, height;
 
-        err = vdp_output_surface_get_parameters(sys->vdp, output,
+        err = vdp_output_surface_get_parameters(vdp, output,
                                                 &fmt, &width, &height);
         if (err != VDP_STATUS_OK)
         {
             msg_Err(filter, "output %s %s failure: %s", "surface", "query",
-                    vdp_get_error_string(sys->vdp, err));
+                    vdp_get_error_string(vdp, err));
             goto error;
         }
 
-        err = vdp_output_surface_create(sys->vdp, sys->device,
+        err = vdp_output_surface_create(vdp, sys->device->device,
                                         fmt, height, width, &output);
         if (err != VDP_STATUS_OK)
         {
             msg_Err(filter, "output %s %s failure: %s", "surface", "creation",
-                    vdp_get_error_string(sys->vdp, err));
+                    vdp_get_error_string(vdp, err));
             goto error;
         }
     }
@@ -634,7 +637,7 @@ static picture_t *Render(filter_t *filter, picture_t *src, bool import)
         future[i] = (pic_f != NULL) ? VDPAU_FIELD_FROM_PICCTX(pic_f->context)->frame->surface : VDP_INVALID_HANDLE;
     }
 
-    err = vdp_video_mixer_render(sys->vdp, sys->mixer, VDP_INVALID_HANDLE,
+    err = vdp_video_mixer_render(vdp, sys->mixer, VDP_INVALID_HANDLE,
                                  NULL, structure,
                                  MAX_PAST, past, surface, MAX_FUTURE, future,
                                  &src_rect, output, &dst_rect, &dst_rect, 0,
@@ -642,20 +645,20 @@ static picture_t *Render(filter_t *filter, picture_t *src, bool import)
     if (err != VDP_STATUS_OK)
     {
         msg_Err(filter, "video %s %s failure: %s", "mixer", "rendering",
-                vdp_get_error_string(sys->vdp, err));
+                vdp_get_error_string(vdp, err));
         goto error;
     }
 
     if (swap)
     {
-        err = vdp_output_surface_render_output_surface(sys->vdp,
+        err = vdp_output_surface_render_output_surface(vdp,
             p_sys->surface, NULL, output, NULL, NULL, NULL,
             VDP_OUTPUT_SURFACE_RENDER_ROTATE_90);
-        vdp_output_surface_destroy(sys->vdp, output);
+        vdp_output_surface_destroy(vdp, output);
         if (err != VDP_STATUS_OK)
         {
             msg_Err(filter, "output %s %s failure: %s", "surface", "render",
-                    vdp_get_error_string(sys->vdp, err));
+                    vdp_get_error_string(vdp, err));
             goto error;
         }
     }
@@ -686,7 +689,7 @@ static picture_t *YCbCrRender(filter_t *filter, picture_t *src)
     return (src != NULL) ? Render(filter, src, true) : NULL;
 }
 
-static int OutputCheckFormat(vlc_object_t *obj, vdpau_decoder_device_t *vdpau_dev,
+static int OutputCheckFormat(vlc_object_t *obj, struct vlc_video_context *vctx,
                              const video_format_t *fmt,
                              VdpRGBAFormat *restrict rgb_fmt)
 {
@@ -694,19 +697,20 @@ static int OutputCheckFormat(vlc_object_t *obj, vdpau_decoder_device_t *vdpau_de
         VDP_RGBA_FORMAT_R10G10B10A2, VDP_RGBA_FORMAT_B10G10R10A2,
         VDP_RGBA_FORMAT_B8G8R8A8, VDP_RGBA_FORMAT_R8G8B8A8,
     };
+    struct vlc_vdp_device *device = GetVDPAUOpaqueContext(vctx);
 
     for (unsigned i = 0; i < ARRAY_SIZE(rgb_fmts); i++)
     {
         uint32_t w, h;
         VdpBool ok;
 
-        VdpStatus err = vdp_output_surface_query_capabilities(vdpau_dev->vdp,
-                                                              vdpau_dev->device,
+        VdpStatus err = vdp_output_surface_query_capabilities(device->vdp,
+                                                              device->device,
                                                      rgb_fmts[i], &ok, &w, &h);
         if (err != VDP_STATUS_OK)
         {
             msg_Err(obj, "%s capabilities query failure: %s", "output surface",
-                    vdp_get_error_string(vdpau_dev->vdp, err));
+                    vdp_get_error_string(device->vdp, err));
             continue;
         }
 
@@ -723,16 +727,16 @@ static int OutputCheckFormat(vlc_object_t *obj, vdpau_decoder_device_t *vdpau_de
 }
 
 static picture_pool_t *OutputPoolAlloc(vlc_object_t *obj,
-    vdpau_decoder_device_t *vdpau_dev, const video_format_t *restrict fmt)
+    struct vlc_video_context *vctx, const video_format_t *restrict fmt)
 {
     /* Check output surface format */
     VdpRGBAFormat rgb_fmt;
 
-    if (OutputCheckFormat(obj, vdpau_dev, fmt, &rgb_fmt))
+    if (OutputCheckFormat(obj, vctx, fmt, &rgb_fmt))
         return NULL;
 
     /* Allocate the pool */
-    return vlc_vdp_output_pool_create(vdpau_dev, rgb_fmt, fmt, 3);
+    return vlc_vdp_output_pool_create(vctx, rgb_fmt, fmt, 3);
 }
 
 const struct vlc_video_context_operations vdpau_vctx_ops = {
@@ -744,7 +748,7 @@ static void OutputClose(filter_t *filter)
     vlc_vdp_mixer_t *sys = filter->p_sys;
 
     Flush(filter);
-    vdp_video_mixer_destroy(sys->vdp, sys->mixer);
+    vdp_video_mixer_destroy(sys->device->vdp, sys->mixer);
     picture_pool_Release(sys->pool);
     vlc_video_context_Release(filter->vctx_out);
 }
@@ -808,10 +812,7 @@ static int OutputOpen(filter_t *filter)
         return VLC_EGENERIC;
     }
 
-    vdpau_decoder_device_t *vdpau_decoder = GetVDPAUOpaqueDevice(dec_device);
-    sys->vdp = vdpau_decoder->vdp;
-    sys->device = vdpau_decoder->device;
-
+    sys->device = GetVDPAUOpaqueDevice(dec_device);
     filter->vctx_out = vlc_video_context_Create(dec_device, VLC_VIDEO_CONTEXT_VDPAU,
                                                 0, &vdpau_vctx_ops);
     vlc_decoder_device_Release(dec_device);
@@ -819,7 +820,7 @@ static int OutputOpen(filter_t *filter)
         return VLC_EGENERIC;
 
     /* Allocate the output surface picture pool */
-    sys->pool = OutputPoolAlloc(VLC_OBJECT(filter), vdpau_decoder,
+    sys->pool = OutputPoolAlloc(VLC_OBJECT(filter), filter->vctx_out,
                                 &filter->fmt_out.video);
     if (sys->pool == NULL)
     {


=====================================
modules/hw/vdpau/device.c
=====================================
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * device.c: VDPAU instance management for VLC
+ *****************************************************************************
+ * Copyright (C) 2013-2021 Rémi Denis-Courmont
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+
+#include <vlc_common.h>
+#include <vlc_codec.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_window.h>
+#include <vlc_xlib.h>
+#include "vlc_vdpau.h"
+
+typedef struct vdp_instance
+{
+    Display *display;
+    struct vlc_vdp_device device;
+} vdp_instance_t;
+
+static void Close(vlc_decoder_device *device)
+{
+    vdp_instance_t *vi = device->sys;
+
+    vdp_device_destroy(vi->device.vdp, vi->device.device);
+    vdp_destroy_x11(vi->device.vdp);
+    XCloseDisplay(vi->display);
+    free(vi);
+}
+
+static const struct vlc_decoder_device_operations ops = {
+    .close = Close,
+};
+
+static int ScreenNumberOfWindow(Display *dpy, Window w)
+{
+    XWindowAttributes attrs;
+
+    XGetWindowAttributes(dpy, w, &attrs);
+
+    for (int num = 0; num < ScreenCount(dpy); num++)
+        if (RootWindow(dpy, num) == attrs.root)
+            return num;
+
+    return -1;
+}
+
+static int Open(vlc_decoder_device *device, vout_window_t *window)
+{
+    if (window == NULL || window->type != VOUT_WINDOW_TYPE_XID)
+        return VLC_ENOTSUP;
+    if (!vlc_xlib_init(VLC_OBJECT(device)))
+        return VLC_ENOTSUP;
+
+    vdp_instance_t *vi = malloc(sizeof (*vi));
+    if (unlikely(vi == NULL))
+        return VLC_ENOMEM;
+
+    vi->display = XOpenDisplay(window->display.x11);
+    if (vi->display == NULL)
+    {
+        free(vi);
+        return -ENOBUFS;
+    }
+
+    int num = ScreenNumberOfWindow(vi->display, window->handle.xid);
+    if (unlikely(num < 0))
+        goto error;
+
+    VdpStatus err = vdp_create_x11(vi->display, num, &vi->device.vdp,
+                                   &vi->device.device);
+    if (err != VDP_STATUS_OK)
+        goto error;
+
+    const char *infos;
+    err = vdp_get_information_string(vi->device.vdp, &infos);
+    if (err == VDP_STATUS_OK)
+    {
+        if (strstr(infos, "VAAPI") != NULL)
+        {
+            Close(device);
+            return -EACCES;
+        }
+
+        msg_Info(device, "Using %s", infos);
+    }
+
+    device->ops = &ops;
+    device->sys = vi;
+    device->type = VLC_DECODER_DEVICE_VDPAU;
+    device->opaque = &vi->device;
+    return VLC_SUCCESS;
+
+error:
+    XCloseDisplay(vi->display);
+    free(vi);
+    return VLC_EGENERIC;
+}
+
+vlc_module_begin()
+    set_description("VDPAU decoder device")
+    set_callback_dec_device(Open, 3)
+    add_shortcut("vdpau")
+    set_subcategory(SUBCAT_VIDEO_VOUT)
+vlc_module_end()


=====================================
modules/hw/vdpau/display.c
=====================================
@@ -324,10 +324,6 @@ static int Open(vout_display_t *vd,
 
     vlc_decoder_device_Release(dec_device);
 
-    const char *info;
-    if (vdp_get_information_string(sys->vdp, &info) == VDP_STATUS_OK)
-        msg_Dbg(vd, "using back-end %s", info);
-
     /* Check source format */
     video_format_t fmt;
     VdpChromaType chroma;


=====================================
modules/hw/vdpau/instance.c deleted
=====================================
@@ -1,218 +0,0 @@
-/*****************************************************************************
- * instance.c: VDPAU instance management for VLC
- *****************************************************************************
- * Copyright (C) 2013 Rémi Denis-Courmont
- *
- * 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 <stdlib.h>
-#include <stdint.h>
-#include <assert.h>
-#include <pthread.h>
-#include <X11/Xlib.h>
-#include <vlc_common.h>
-#include "vlc_vdpau.h"
-
-#pragma GCC visibility push(default)
-
-typedef struct vdp_instance
-{
-    Display *display;
-    vdp_t *vdp;
-    VdpDevice device;
-
-    int num; /**< X11 screen number */
-
-    uintptr_t refs; /**< Reference count */
-    struct vdp_instance *next;
-    char name[]; /**< X11 display name */
-} vdp_instance_t;
-
-static vdp_instance_t *vdp_instance_create(const char *name, int num)
-{
-    size_t namelen = strlen(name) + 1;
-    vdp_instance_t *vi = malloc(sizeof (*vi) + namelen);
-
-    if (unlikely(vi == NULL))
-        return NULL;
-
-    vi->display = XOpenDisplay(name);
-    if (vi->display == NULL)
-    {
-        free(vi);
-        return NULL;
-    }
-
-    if (num >= 0)
-        vi->num = num;
-    else
-        vi->num = XDefaultScreen(vi->display);
-
-    VdpStatus err = vdp_create_x11(vi->display, vi->num,
-                                   &vi->vdp, &vi->device);
-    if (err != VDP_STATUS_OK)
-    {
-        XCloseDisplay(vi->display);
-        free(vi);
-        return NULL;
-    }
-
-    vi->next = NULL;
-    memcpy(vi->name, name, namelen);
-    vi->refs = 1;
-
-    return vi;
-}
-
-static void vdp_instance_destroy(vdp_instance_t *vi)
-{
-    vdp_device_destroy(vi->vdp, vi->device);
-    vdp_destroy_x11(vi->vdp);
-    XCloseDisplay(vi->display);
-    free(vi);
-}
-
-static int vicmp(const char *name, int num, const vdp_instance_t *vi)
-{
-    int val = strcmp(name, vi->name);
-    if (val)
-        return val;
-
-    if (num < 0)
-        num = XDefaultScreen(vi->display);
-    return num - vi->num;
-}
-
-static vdp_instance_t *list = NULL;
-
-static vdp_instance_t *vdp_instance_lookup(const char *name, int num)
-{
-    vdp_instance_t *vi = NULL;
-
-    for (vi = list; vi != NULL; vi = vi->next)
-    {
-        int val = vicmp(name, num, vi);
-        if (val == 0)
-        {
-            assert(vi->refs < UINTPTR_MAX);
-            vi->refs++;
-            break;
-        }
-    }
-    return vi;
-}
-
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
-/** Finds an existing VDPAU instance for the given X11 display and screen.
- * If not found, (try to) create a new one.
- * @param display_name X11 display string, NULL for default
- * @param snum X11 screen number, strictly negative for default
- **/
-VdpStatus vdp_get_x11(const char *display_name, int snum,
-                      vdp_t **restrict vdpp, VdpDevice *restrict devicep)
-{
-    vdp_instance_t *vi, *vi2;
-
-    if (display_name == NULL)
-    {
-        display_name = getenv("DISPLAY");
-        if (display_name == NULL)
-            return VDP_STATUS_ERROR;
-    }
-
-    pthread_mutex_lock(&lock);
-    vi = vdp_instance_lookup(display_name, snum);
-    pthread_mutex_unlock(&lock);
-    if (vi != NULL)
-        goto found;
-
-    vi = vdp_instance_create(display_name, snum);
-    if (vi == NULL)
-        return VDP_STATUS_ERROR;
-
-    pthread_mutex_lock(&lock);
-    vi2 = vdp_instance_lookup(display_name, snum);
-    if (unlikely(vi2 != NULL))
-    {   /* Another thread created the instance (race condition corner case) */
-        pthread_mutex_unlock(&lock);
-        vdp_instance_destroy(vi);
-        vi = vi2;
-    }
-    else
-    {
-        vi->next = list;
-        list = vi;
-        pthread_mutex_unlock(&lock);
-    }
-found:
-    *vdpp = vi->vdp;
-    *devicep = vi->device;
-    return VDP_STATUS_OK;
-}
-
-vdp_t *vdp_hold_x11(vdp_t *vdp, VdpDevice *restrict devp)
-{
-    vdp_instance_t *vi, **pp = &list;
-
-    pthread_mutex_lock(&lock);
-    for (;;)
-    {
-        vi = *pp;
-        assert(vi != NULL);
-        if (vi->vdp == vdp)
-            break;
-        pp = &vi->next;
-    }
-
-    assert(vi->refs < UINTPTR_MAX);
-    vi->refs++;
-    pthread_mutex_unlock(&lock);
-
-    if (devp != NULL)
-        *devp = vi->device;
-   return vdp;
-}
-
-void vdp_release_x11(vdp_t *vdp)
-{
-    vdp_instance_t *vi, **pp = &list;
-
-    pthread_mutex_lock(&lock);
-    for (;;)
-    {
-        vi = *pp;
-        assert(vi != NULL);
-        if (vi->vdp == vdp)
-            break;
-        pp = &vi->next;
-    }
-
-    assert(vi->refs > 0);
-    vi->refs--;
-    if (vi->refs > 0)
-        vi = NULL; /* Keep the instance for now */
-    else
-        *pp = vi->next; /* Unlink the instance */
-    pthread_mutex_unlock(&lock);
-
-    if (vi != NULL)
-        vdp_instance_destroy(vi);
-}


=====================================
modules/hw/vdpau/picture.c
=====================================
@@ -38,6 +38,7 @@ static_assert(offsetof (vlc_vdp_video_field_t, context) == 0,
 
 static void VideoSurfaceDestroy(struct picture_context_t *ctx)
 {
+    struct vlc_vdp_device *device = GetVDPAUOpaqueContext(ctx->vctx);
     vlc_vdp_video_field_t *field = container_of(ctx, vlc_vdp_video_field_t,
                                                 context);
     vlc_vdp_video_frame_t *frame = field->frame;
@@ -50,11 +51,10 @@ static void VideoSurfaceDestroy(struct picture_context_t *ctx)
         return;
 
     /* Destroy frame (video surface) */
-    err = vdp_video_surface_destroy(frame->vdp, frame->surface);
+    err = vdp_video_surface_destroy(device->vdp, frame->surface);
     if (err != VDP_STATUS_OK)
         fprintf(stderr, "video surface destruction failure: %s\n",
-                vdp_get_error_string(frame->vdp, err));
-    vdp_release_x11(frame->vdp);
+                vdp_get_error_string(device->vdp, err));
     free(frame);
 }
 
@@ -67,7 +67,7 @@ static picture_context_t *VideoSurfaceCopy(picture_context_t *ctx)
         return NULL;
 
     *fnew = *fold;
-
+    vlc_video_context_Hold(ctx->vctx);
     atomic_fetch_add(&fold->frame->refs, 1);
     return &fnew->context;
 }
@@ -81,12 +81,15 @@ static const VdpProcamp procamp_default =
     .hue = 0.f,
 };
 
-vlc_vdp_video_field_t *vlc_vdp_video_create(vdp_t *vdp,
+vlc_vdp_video_field_t *vlc_vdp_video_create(struct vlc_video_context *vctx,
                                             VdpVideoSurface surface)
 {
+    struct vlc_vdp_device *device = GetVDPAUOpaqueContext(vctx);
     vlc_vdp_video_field_t *field = malloc(sizeof (*field));
     vlc_vdp_video_frame_t *frame = malloc(sizeof (*frame));
 
+    if (device == NULL)
+        vlc_assert_unreachable();
     if (unlikely(field == NULL || frame == NULL))
     {
         free(frame);
@@ -95,8 +98,7 @@ vlc_vdp_video_field_t *vlc_vdp_video_create(vdp_t *vdp,
     }
 
     field->context = (picture_context_t) {
-        VideoSurfaceDestroy, VideoSurfaceCopy,
-        NULL /*TODO*/
+        VideoSurfaceDestroy, VideoSurfaceCopy, vlc_video_context_Hold(vctx),
     };
     field->frame = frame;
     field->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
@@ -105,30 +107,16 @@ vlc_vdp_video_field_t *vlc_vdp_video_create(vdp_t *vdp,
 
     atomic_init(&frame->refs, 1);
     frame->surface = surface;
-    frame->vdp = vdp_hold_x11(vdp, &frame->device);
     return field;
 }
 
-picture_context_t *VideoSurfaceCloneWithContext(picture_context_t *src_ctx)
+VdpStatus vlc_vdp_video_attach(struct vlc_video_context *vctx,
+                               VdpVideoSurface surface, picture_t *pic)
 {
-    picture_context_t *dst_ctx = VideoSurfaceCopy(src_ctx);
-    if (unlikely(dst_ctx == NULL))
-        return NULL;
-    vlc_video_context_Hold(dst_ctx->vctx);
-    return dst_ctx;
-}
-
-VdpStatus vlc_vdp_video_attach(vdp_t *vdp, VdpVideoSurface surface,
-                               vlc_video_context *vctx, picture_t *pic)
-{
-    vlc_vdp_video_field_t *field = vlc_vdp_video_create(vdp, surface);
+    vlc_vdp_video_field_t *field = vlc_vdp_video_create(vctx, surface);
     if (unlikely(field == NULL))
         return VDP_STATUS_RESOURCES;
 
-    field->context.destroy = VideoSurfaceDestroy;
-    field->context.copy = VideoSurfaceCloneWithContext;
-    field->context.vctx = vlc_video_context_Hold(vctx);
-
     assert(pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_420
         || pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_422
         || pic->format.i_chroma == VLC_CODEC_VDPAU_VIDEO_444);
@@ -140,31 +128,31 @@ VdpStatus vlc_vdp_video_attach(vdp_t *vdp, VdpVideoSurface surface,
 static void vlc_vdp_output_surface_destroy(picture_t *pic)
 {
     vlc_vdp_output_surface_t *sys = pic->p_sys;
+    struct vlc_vdp_device *device = GetVDPAUOpaqueContext(sys->vctx);
 
-    vdp_output_surface_destroy(sys->vdp, sys->surface);
-    vdp_release_x11(sys->vdp);
+    vdp_output_surface_destroy(device->vdp, sys->surface);
+    vlc_video_context_Release(sys->vctx);
     free(sys);
 }
 
 static
-picture_t *vlc_vdp_output_surface_create(vdpau_decoder_device_t *vdpau_dev,
+picture_t *vlc_vdp_output_surface_create(struct vlc_video_context *vctx,
                                          VdpRGBAFormat rgb_fmt,
                                          const video_format_t *restrict fmt)
 {
+    struct vlc_vdp_device *device = GetVDPAUOpaqueContext(vctx);
     vlc_vdp_output_surface_t *sys = malloc(sizeof (*sys));
     if (unlikely(sys == NULL))
         return NULL;
 
-    sys->vdp = vdp_hold_x11(vdpau_dev->vdp, &sys->device);
     sys->gl_nv_surface = 0;
 
-    VdpStatus err = vdp_output_surface_create(vdpau_dev->vdp, vdpau_dev->device,
+    VdpStatus err = vdp_output_surface_create(device->vdp, device->device,
         rgb_fmt,
         fmt->i_visible_width, fmt->i_visible_height, &sys->surface);
     if (err != VDP_STATUS_OK)
     {
 error:
-        vdp_release_x11(vdpau_dev->vdp);
         free(sys);
         return NULL;
     }
@@ -177,13 +165,15 @@ error:
     picture_t *pic = picture_NewFromResource(fmt, &res);
     if (unlikely(pic == NULL))
     {
-        vdp_output_surface_destroy(vdpau_dev->vdp, sys->surface);
+        vdp_output_surface_destroy(device->vdp, sys->surface);
         goto error;
     }
+
+    sys->vctx = vlc_video_context_Hold(vctx);
     return pic;
 }
 
-picture_pool_t *vlc_vdp_output_pool_create(vdpau_decoder_device_t *vdpau_dev,
+picture_pool_t *vlc_vdp_output_pool_create(struct vlc_video_context *vctx,
                                            VdpRGBAFormat rgb_fmt,
                                            const video_format_t *restrict fmt,
                                            unsigned requested_count)
@@ -193,7 +183,7 @@ picture_pool_t *vlc_vdp_output_pool_create(vdpau_decoder_device_t *vdpau_dev,
 
     while (count < requested_count)
     {
-        pics[count] = vlc_vdp_output_surface_create(vdpau_dev, rgb_fmt, fmt);
+        pics[count] = vlc_vdp_output_surface_create(vctx, rgb_fmt, fmt);
         if (pics[count] == NULL)
             break;
         count++;


=====================================
modules/hw/vdpau/vlc_vdpau.h
=====================================
@@ -172,40 +172,6 @@ VdpStatus vdp_create_x11(void *dpy, int snum, vdp_t **vdpp, VdpDevice *devp);
  */
 void vdp_destroy_x11(vdp_t *);
 
-/* Instance reuse */
-
-/**
- * Finds an existing pair of VDPAU instance and VDPAU device matching the
- * specified X11 display and screen number from within the process-wide list.
- * If no existing instance corresponds, connect to the X11 server,
- * create a new pair of instance and device, and set the reference count to 1.
- * @param name X11 display name
- * @param snum X11 screen number
- * @param vdp memory location to hold the VDPAU instance pointer [OUT]
- * @param dev memory location to hold the VDPAU device handle [OUT]
- * @return VDP_STATUS_OK on success, otherwise a VDPAU error code.
- *
- * @note Use vdp_release_x11() to release the instance. <b>Do not use</b>
- * vdp_device_destroy() and/or vdp_destroy_x11() with vdp_get_x11().
- */
-VdpStatus vdp_get_x11(const char *name, int num, vdp_t **vdp, VdpDevice *dev);
-
-/**
- * Increases the reference count of a VDPAU instance created by vdp_get_x11().
- * @param vdp VDPAU instance (as returned by vdp_get_x11())
- * @param device location to store the VDPAU device corresponding to the
- *               VDPAU instance (or NULL) [OUT]
- * @return the first pameter, always succeeds.
- */
-vdp_t *vdp_hold_x11(vdp_t *vdp, VdpDevice *device);
-
-/**
- * Decreases the reference count of a VDPAU instance created by vdp_get_x11().
- * If it reaches zero, destroy the corresponding VDPAU device, then the VDPAU
- * instance and remove the pair from the process-wide list.
- */
-void vdp_release_x11(vdp_t *);
-
 /* VLC specifics */
 # include <stdatomic.h>
 # include <stdbool.h>
@@ -214,6 +180,11 @@ void vdp_release_x11(vdp_t *);
 # include <vlc_fourcc.h>
 # include <vlc_picture.h>
 
+struct vlc_vdp_device {
+    vdp_t *vdp; /**< VDPAU driver instance */
+    VdpDevice device; /**< VDPAU device handle */
+};
+
 /** Converts VLC YUV format to VDPAU chroma type and YCbCr format */
 static inline
 bool vlc_fourcc_to_vdp_ycc(vlc_fourcc_t fourcc,
@@ -263,8 +234,6 @@ bool vlc_fourcc_to_vdp_ycc(vlc_fourcc_t fourcc,
 typedef struct vlc_vdp_video_frame
 {
     VdpVideoSurface surface;
-    VdpDevice device;
-    vdp_t *vdp;
     atomic_uintptr_t refs;
 } vlc_vdp_video_frame_t;
 
@@ -280,10 +249,7 @@ typedef struct vlc_vdp_video_field
 #define VDPAU_FIELD_FROM_PICCTX(pic_ctx)  \
     container_of((pic_ctx), vlc_vdp_video_field_t, context)
 
-typedef struct {
-    vdp_t              *vdp;
-    VdpDevice          device;
-} vdpau_decoder_device_t;
+typedef struct vlc_vdp_device vdpau_decoder_device_t;
 
 static inline vdpau_decoder_device_t *GetVDPAUOpaqueDevice(vlc_decoder_device *device)
 {
@@ -310,16 +276,21 @@ static inline vdpau_decoder_device_t *GetVDPAUOpaqueContext(vlc_video_context *v
 /**
  * Attaches a VDPAU video surface as context of a VLC picture.
  */
-VdpStatus vlc_vdp_video_attach(vdp_t *, VdpVideoSurface, vlc_video_context *, picture_t *);
+VdpStatus vlc_vdp_video_attach(struct vlc_video_context *, VdpVideoSurface,
+                               picture_t *);
 
 /**
  * Wraps a VDPAU video surface into a VLC picture context.
  */
-vlc_vdp_video_field_t *vlc_vdp_video_create(vdp_t *, VdpVideoSurface);
+vlc_vdp_video_field_t *vlc_vdp_video_create(struct vlc_video_context *,
+                                            VdpVideoSurface);
 
 static inline void vlc_vdp_video_destroy(vlc_vdp_video_field_t *f)
 {
+    struct vlc_video_context *vctx = f->context.vctx;
+
     f->context.destroy(&f->context);
+    vlc_video_context_Release(vctx);
 }
 
 /**
@@ -332,22 +303,16 @@ static inline vlc_vdp_video_field_t *vlc_vdp_video_copy(
     return VDPAU_FIELD_FROM_PICCTX(fold->context.copy(&fold->context));
 }
 
-/**
- * Clone a VPD field based picture context that contains a video context
- */
-picture_context_t *VideoSurfaceCloneWithContext(picture_context_t *);
-
 typedef struct vlc_vdp_output_surface
 {
     VdpOutputSurface surface;
-    VdpDevice device;
-    vdp_t *vdp;
+    struct vlc_video_context *vctx;
     ptrdiff_t gl_nv_surface;
 } vlc_vdp_output_surface_t;
 
 struct picture_pool_t;
 
-struct picture_pool_t *vlc_vdp_output_pool_create(vdpau_decoder_device_t *,
+struct picture_pool_t *vlc_vdp_output_pool_create(struct vlc_video_context *,
                                                   VdpRGBAFormat,
                                                   const video_format_t *,
                                                   unsigned count);


=====================================
modules/video_output/opengl/interop_vdpau.c
=====================================
@@ -197,53 +197,6 @@ Open(vlc_object_t *obj)
     return VLC_SUCCESS;
 }
 
-static void
-DecoderDeviceClose(vlc_decoder_device *device)
-{
-    vdpau_decoder_device_t *vdpau_dev = GetVDPAUOpaqueDevice(device);
-    vdp_release_x11(vdpau_dev->vdp);
-}
-
-static const struct vlc_decoder_device_operations dev_ops = {
-    .close = DecoderDeviceClose,
-};
-
-static int
-DecoderDeviceOpen(vlc_decoder_device *device, vout_window_t *window)
-{
-    if (!window || window->type != VOUT_WINDOW_TYPE_XID)
-        return VLC_EGENERIC;
-
-    if (!vlc_xlib_init(VLC_OBJECT(window)))
-        return VLC_EGENERIC;
-
-    vdpau_decoder_device_t *sys = vlc_obj_malloc(VLC_OBJECT(device), sizeof(*sys));
-    if (unlikely(sys == NULL))
-        return VLC_ENOMEM;
-
-    if (vdp_get_x11(window->display.x11, -1,
-                    &sys->vdp, &sys->device) != VDP_STATUS_OK)
-        return VLC_EGENERIC;
-
-    const char *infos;
-    VdpStatus status = vdp_get_information_string(sys->vdp, &infos);
-    /* Favor original backends. Example: don't use a VAAPI backend when we
-     * have VAAPI decoder devices. */
-    if (status != VDP_STATUS_OK
-     || strstr(infos, "VAAPI") != NULL)
-    {
-        if (status == VDP_STATUS_OK)
-            msg_Dbg(device, "Not using '%s', favor a decdev with a compatible backend",
-                    infos);
-        vdp_release_x11(sys->vdp);
-        return VLC_EGENERIC;
-    }
-
-    device->ops = &dev_ops;
-    device->type = VLC_DECODER_DEVICE_VDPAU;
-    device->opaque = sys;
-    return VLC_SUCCESS;
-}
 
 vlc_module_begin ()
     set_description("VDPAU OpenGL surface converter")
@@ -251,6 +204,4 @@ vlc_module_begin ()
     set_callback(Open)
     set_subcategory(SUBCAT_VIDEO_VOUT)
     add_shortcut("vdpau")
-    add_submodule()
-        set_callback_dec_device(DecoderDeviceOpen, 3)
 vlc_module_end ()



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2b225963d0680294de37e8eecb27dd05e139b12b...647bafc3b9002b1c6f75a2fadf94a193c94e7df0

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2b225963d0680294de37e8eecb27dd05e139b12b...647bafc3b9002b1c6f75a2fadf94a193c94e7df0
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list