[vlc-commits] gl: add converter_vdpau

Victorien Le Couviour--Tuffet git at videolan.org
Thu Aug 31 11:50:48 CEST 2017


vlc | branch: master | Victorien Le Couviour--Tuffet <victorien.lecouviour.tuffet at gmail.com> | Thu Jul 20 12:37:37 2017 +0200| [9f6cb2d381c944ee7fe877e485359ea44e0a0f46] | committer: Thomas Guillem

gl: add converter_vdpau

Signed-off-by: Thomas Guillem <thomas at gllm.fr>

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

 modules/MODULES_LIST                          |   1 +
 modules/hw/vdpau/vlc_vdpau.h                  |   1 +
 modules/video_output/Makefile.am              |   9 +
 modules/video_output/opengl/converter_vdpau.c | 249 ++++++++++++++++++++++++++
 po/POTFILES.in                                |   1 +
 5 files changed, 261 insertions(+)

diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST
index 2f1656d930..698118fe5e 100644
--- a/modules/MODULES_LIST
+++ b/modules/MODULES_LIST
@@ -167,6 +167,7 @@ $Id$
  * glconv_vaapi_drm: VA-API OpenGL hardware converter for DRM
  * glconv_vaapi_wl: VA-API OpenGL hardware converter for Wayland
  * glconv_vaapi_x11: VA-API OpenGL hardware converter for X11
+ * glconv_vdpau: VDPAU OpenGL surface converter
  * gles2: OpenGL ES2 video output using the generic OpenGL provider
  * glspectrum: 3D OpenGL spectrum visualization
  * glwin32: a opengl provider using DirectX OpenGL
diff --git a/modules/hw/vdpau/vlc_vdpau.h b/modules/hw/vdpau/vlc_vdpau.h
index af62bddcc1..01289ffbae 100644
--- a/modules/hw/vdpau/vlc_vdpau.h
+++ b/modules/hw/vdpau/vlc_vdpau.h
@@ -261,6 +261,7 @@ struct picture_sys_t
     VdpOutputSurface surface;
     VdpDevice device;
     vdp_t *vdp;
+    void *gl_nv_surface;
 };
 
 typedef struct vlc_vdp_video_frame
diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index 004bc51952..50fa534499 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -76,6 +76,11 @@ libglconv_vaapi_drm_plugin_la_CFLAGS = $(AM_CFLAGS) -DHAVE_VA_DRM
 libglconv_vaapi_drm_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) \
 	$(LIBVA_DRM_LIBS)
 
+libglconv_vdpau_plugin_la_SOURCES = video_output/opengl/converter_vdpau.c \
+	video_output/opengl/converter.h hw/vdpau/vlc_vdpau.h
+libglconv_vdpau_plugin_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS)
+libglconv_vdpau_plugin_la_LIBADD = $(LIBDL) libvlc_vdpau.la $(X_LIBS) $(X_PRE_LIBS) -lX11
+
 if HAVE_GL
 vout_LTLIBRARIES += libgl_plugin.la
 if HAVE_EGL
@@ -95,6 +100,10 @@ vout_LTLIBRARIES += libglconv_vaapi_drm_plugin.la
 endif
 endif
 endif # HAVE_EGL
+
+if HAVE_VDPAU
+vout_LTLIBRARIES += libglconv_vdpau_plugin.la
+endif
 endif # HAVE_GL
 
 ### XCB ###
diff --git a/modules/video_output/opengl/converter_vdpau.c b/modules/video_output/opengl/converter_vdpau.c
new file mode 100644
index 0000000000..6b3467c37e
--- /dev/null
+++ b/modules/video_output/opengl/converter_vdpau.c
@@ -0,0 +1,249 @@
+/*****************************************************************************
+ * converter_vdpau.c: OpenGL VDPAU opaque converter
+ *****************************************************************************
+ * 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 <GL/gl.h>
+#include <GL/glext.h>
+
+#include <vlc_common.h>
+#include <vlc_vout_window.h>
+#include <vlc_xlib.h>
+
+#include "../../hw/vdpau/vlc_vdpau.h"
+#include "internal.h"
+
+#define INTEROP_CALL(fct, ...) \
+    _##fct(__VA_ARGS__); \
+    { \
+        GLenum ret = tc->vt->GetError(); \
+        if (ret != GL_NO_ERROR) \
+        { \
+            msg_Err(tc->gl, #fct " failed: 0x%x\n", ret); \
+            return VLC_EGENERIC; \
+        } \
+    }
+
+struct  priv
+{
+    vdp_t *vdp;
+    VdpDevice vdp_device;
+};
+
+static PFNGLVDPAUINITNVPROC                     _glVDPAUInitNV;
+static PFNGLVDPAUFININVPROC                     _glVDPAUFiniNV;
+static PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC    _glVDPAURegisterOutputSurfaceNV;
+static PFNGLVDPAUISSURFACENVPROC                _glVDPAUIsSurfaceNV;
+static PFNGLVDPAUUNREGISTERSURFACENVPROC        _glVDPAUUnregisterSurfaceNV;
+static PFNGLVDPAUGETSURFACEIVNVPROC             _glVDPAUGetSurfaceivNV;
+static PFNGLVDPAUSURFACEACCESSNVPROC            _glVDPAUSurfaceAccessNV;
+static PFNGLVDPAUMAPSURFACESNVPROC              _glVDPAUMapSurfacesNV;
+static PFNGLVDPAUUNMAPSURFACESNVPROC            _glVDPAUUnmapSurfacesNV;
+
+static void
+pool_pic_destroy_cb(picture_t *pic)
+{
+    vdp_output_surface_destroy(pic->p_sys->vdp, pic->p_sys->surface);
+    vdp_release_x11(pic->p_sys->vdp);
+    free(pic->p_sys);
+    free(pic);
+}
+
+static picture_pool_t *
+tc_vdpau_gl_get_pool(opengl_tex_converter_t const *tc,
+                     unsigned int requested_count)
+{
+    struct priv *priv = tc->priv;
+    picture_t *pics[requested_count];
+
+    unsigned int i;
+    for (i = 0; i < requested_count; ++i)
+    {
+        VdpOutputSurface surface;
+
+        VdpStatus st;
+        if ((st = vdp_output_surface_create(priv->vdp, priv->vdp_device,
+                                            VDP_RGBA_FORMAT_B8G8R8A8,
+                                            tc->fmt.i_visible_width,
+                                            tc->fmt.i_visible_height,
+                                            &surface)) != VDP_STATUS_OK)
+            goto error;
+
+        picture_sys_t *picsys = calloc(1, sizeof(*picsys));
+        if (!picsys)
+            goto error;
+
+        picsys->vdp = vdp_hold_x11(priv->vdp, NULL);
+        picsys->device = priv->vdp_device;
+        picsys->surface = surface;
+
+        picture_resource_t rsc = { .p_sys = picsys,
+                                   .pf_destroy = pool_pic_destroy_cb };
+
+        pics[i] = picture_NewFromResource(&tc->fmt, &rsc);
+        if (!pics[i])
+            goto error;
+    }
+
+    picture_pool_t *pool = picture_pool_New(requested_count, pics);
+    if (!pool)
+        goto error;
+
+    return pool;
+
+error:
+    while (i--)
+        picture_Release(pics[i]);
+    return NULL;
+}
+
+static int
+tc_vdpau_gl_update(opengl_tex_converter_t const *tc, GLuint textures[],
+                   GLsizei const tex_widths[], GLsizei const tex_heights[],
+                   picture_t *pic, size_t const plane_offsets[])
+{
+    VLC_UNUSED(tex_widths);
+    VLC_UNUSED(tex_heights);
+    VLC_UNUSED(plane_offsets);
+
+    GLvdpauSurfaceNV *p_gl_nv_surface =
+        (GLvdpauSurfaceNV *)&pic->p_sys->gl_nv_surface;
+
+    if (*p_gl_nv_surface)
+    {
+        assert(_glVDPAUIsSurfaceNV(*p_gl_nv_surface) == GL_TRUE);
+
+        GLint state;
+        GLsizei num_val;
+        INTEROP_CALL(glVDPAUGetSurfaceivNV, *p_gl_nv_surface,
+                     GL_SURFACE_STATE_NV, 1, &num_val, &state);
+        assert(num_val == 1); assert(state == GL_SURFACE_MAPPED_NV);
+
+        INTEROP_CALL(glVDPAUUnmapSurfacesNV, 1, p_gl_nv_surface);
+        INTEROP_CALL(glVDPAUUnregisterSurfaceNV, *p_gl_nv_surface);
+    }
+
+    *p_gl_nv_surface =
+        INTEROP_CALL(glVDPAURegisterOutputSurfaceNV,
+                     (void *)(size_t)pic->p_sys->surface,
+                     GL_TEXTURE_2D, tc->tex_count, textures);
+    INTEROP_CALL(glVDPAUSurfaceAccessNV, *p_gl_nv_surface, GL_READ_ONLY);
+    INTEROP_CALL(glVDPAUMapSurfacesNV, 1, p_gl_nv_surface);
+
+    return VLC_SUCCESS;
+}
+
+static void
+Close(vlc_object_t *obj)
+{
+    opengl_tex_converter_t *tc = (void *)obj;
+    _glVDPAUFiniNV(); assert(tc->vt->GetError() == GL_NO_ERROR);
+    vdp_release_x11(((struct priv *)tc->priv)->vdp);
+    free(tc->priv);
+}
+
+static int
+Open(vlc_object_t *obj)
+{
+    opengl_tex_converter_t *tc = (void *) obj;
+    if ((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) ||
+        !HasExtension(tc->glexts, "GL_NV_vdpau_interop") ||
+        tc->gl->surface->type != VOUT_WINDOW_TYPE_XID)
+        return VLC_EGENERIC;
+
+    tc->fmt.i_chroma = VLC_CODEC_VDPAU_OUTPUT;
+
+    if (!vlc_xlib_init(VLC_OBJECT(tc->gl)))
+        return VLC_EGENERIC;
+
+    struct priv *priv = calloc(1, sizeof(*priv));
+    if (!priv)
+        return VLC_EGENERIC;
+    tc->priv = priv;
+
+    if (vdp_get_x11(tc->gl->surface->display.x11, -1,
+                    &priv->vdp, &priv->vdp_device) != VDP_STATUS_OK)
+    {
+        free(priv);
+        return VLC_EGENERIC;
+    }
+
+    void *vdp_gpa;
+    if (vdp_get_proc_address(priv->vdp, priv->vdp_device,
+                             VDP_FUNC_ID_GET_PROC_ADDRESS, &vdp_gpa)
+        != VDP_STATUS_OK)
+    {
+        vdp_release_x11(priv->vdp);
+        free(priv);
+        return VLC_EGENERIC;
+    }
+
+#define SAFE_GPA(fct) \
+    _##fct = vlc_gl_GetProcAddress(tc->gl, #fct); \
+    if (!_##fct) \
+    { \
+        vdp_release_x11(priv->vdp); \
+        free(priv); \
+        return VLC_EGENERIC; \
+    }
+    SAFE_GPA(glVDPAUInitNV);
+    SAFE_GPA(glVDPAUFiniNV);
+    SAFE_GPA(glVDPAURegisterOutputSurfaceNV);
+    SAFE_GPA(glVDPAUIsSurfaceNV);
+    SAFE_GPA(glVDPAUUnregisterSurfaceNV);
+    SAFE_GPA(glVDPAUGetSurfaceivNV);
+    SAFE_GPA(glVDPAUSurfaceAccessNV);
+    SAFE_GPA(glVDPAUMapSurfacesNV);
+    SAFE_GPA(glVDPAUUnmapSurfacesNV);
+#undef SAFE_GPA
+
+    INTEROP_CALL(glVDPAUInitNV, (void *)(size_t)priv->vdp_device, vdp_gpa);
+
+    tc->fshader = opengl_fragment_shader_init(tc, GL_TEXTURE_2D,
+                                              VLC_CODEC_RGB32,
+                                              COLOR_SPACE_UNDEF);
+    if (!tc->fshader)
+    {
+        Close(obj);
+        return VLC_EGENERIC;
+    }
+
+    tc->pf_get_pool = tc_vdpau_gl_get_pool;
+    tc->pf_update = tc_vdpau_gl_update;
+
+    return VLC_SUCCESS;
+}
+
+vlc_module_begin ()
+    set_description("VDPAU OpenGL surface converter")
+    set_capability("glconv", 2)
+    set_callbacks(Open, Close)
+    set_category(CAT_VIDEO)
+    set_subcategory(SUBCAT_VIDEO_VOUT)
+    add_shortcut("vdpau")
+vlc_module_end ()
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 57ef6ba7b5..767a9d25fc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1135,6 +1135,7 @@ modules/video_output/macosx.m
 modules/video_output/opengl/converter_android.c
 modules/video_output/opengl/converter_cvpx.c
 modules/video_output/opengl/converter_vaapi.c
+modules/video_output/opengl/converter_vdpau.c
 modules/video_output/opengl/display.c
 modules/video_output/opengl/egl.c
 modules/video_output/win32/direct3d9.c



More information about the vlc-commits mailing list