[vlc-commits] direct3d11: add a decoder device

Steve Lhomme git at videolan.org
Wed Sep 18 15:58:28 CEST 2019


vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Fri Jun  7 12:58:18 2019 +0200| [b45d5e87944b5d9d7c04f403aa86863c82d4e15c] | committer: Steve Lhomme

direct3d11: add a decoder device

It also handles internal/external rendering, the legacy "winrt-d3dcontext" variable.

Do not use it if a DXVA2 decoder would be preferred on Win7/8.0.

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

 modules/hw/d3d11/Makefile.am     |   1 +
 modules/hw/d3d11/d3d11_device.c  | 146 +++++++++++++++++++++++++++++++++++++++
 modules/hw/d3d11/d3d11_filters.c |  10 +++
 modules/hw/d3d11/d3d11_filters.h |   3 +
 4 files changed, 160 insertions(+)

diff --git a/modules/hw/d3d11/Makefile.am b/modules/hw/d3d11/Makefile.am
index e5c5afa3b8..3c9ae52e15 100644
--- a/modules/hw/d3d11/Makefile.am
+++ b/modules/hw/d3d11/Makefile.am
@@ -3,6 +3,7 @@ d3d11dir = $(pluginsdir)/d3d11
 libdirect3d11_filters_plugin_la_SOURCES = hw/d3d11/d3d11_filters.h \
     hw/d3d11/d3d11_filters.c \
     hw/d3d11/d3d11_deinterlace.c \
+    hw/d3d11/d3d11_device.c \
     hw/d3d11/d3d11_surface.c \
     hw/d3d11/d3d11_instance.c \
     hw/d3d11/d3d11_processor.c hw/d3d11/d3d11_processor.h
diff --git a/modules/hw/d3d11/d3d11_device.c b/modules/hw/d3d11/d3d11_device.c
new file mode 100644
index 0000000000..1d543e2087
--- /dev/null
+++ b/modules/hw/d3d11/d3d11_device.c
@@ -0,0 +1,146 @@
+/*****************************************************************************
+ * d3d11_device.c : D3D11 decoder device from external ID3D11DeviceContext
+ *****************************************************************************
+ * Copyright © 2019 VLC authors, VideoLAN and VideoLabs
+ *
+ * Authors: Steve Lhomme <robux4 at ycbcr.xyz>
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_codec.h>
+
+#include <vlc/libvlc.h>
+#include <vlc/libvlc_picture.h>
+#include <vlc/libvlc_media.h>
+#include <vlc/libvlc_renderer_discoverer.h>
+#include <vlc/libvlc_media_player.h>
+
+#define COBJMACROS
+#include <d3d11.h>
+#include "d3d11_filters.h"
+
+typedef struct {
+    d3d11_handle_t         hd3d;
+    d3d11_device_t         d3d_dev;
+
+    struct {
+        void                                     *opaque;
+        libvlc_video_direct3d_device_cleanup_cb  cleanupDeviceCb;
+    } external;
+
+    d3d11_decoder_device_t                    dec_device;
+} d3d11_decoder_device;
+
+static void D3D11CloseDecoderDevice(vlc_decoder_device *device)
+{
+    d3d11_decoder_device *sys = device->sys;
+
+    ID3D11DeviceContext_Release(sys->dec_device.device);
+
+    D3D11_Destroy(&sys->hd3d);
+
+    if ( sys->external.cleanupDeviceCb )
+        sys->external.cleanupDeviceCb( sys->external.opaque );
+
+    vlc_obj_free( VLC_OBJECT(device), sys );
+}
+
+static const struct vlc_decoder_device_operations d3d11_dev_ops = {
+    .close = D3D11CloseDecoderDevice,
+};
+
+int D3D11OpenDecoderDevice(vlc_decoder_device *device, vout_window_t *wnd)
+{
+    VLC_UNUSED(wnd);
+    d3d11_decoder_device *sys = vlc_obj_malloc(VLC_OBJECT(device), sizeof(*sys));
+    if (unlikely(sys==NULL))
+        return VLC_ENOMEM;
+
+    int ret = D3D11_Create(device, &sys->hd3d, true);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    sys->external.cleanupDeviceCb = NULL;
+#if VLC_WINSTORE_APP
+    /* LEGACY, the d3dcontext and swapchain were given by the host app */
+    ID3D11DeviceContext *d3dcontext = (ID3D11DeviceContext*)(uintptr_t) var_InheritInteger(device, "winrt-d3dcontext");
+    if ( likely(d3dcontext != NULL) )
+    {
+        D3D11_CreateDeviceExternal(device, d3dcontext, true, &sys->d3d_dev);
+    }
+    else
+#endif
+    {
+        libvlc_video_direct3d_device_setup_cb setupDeviceCb = var_InheritAddress( device, "vout-cb-setup" );
+        if ( setupDeviceCb )
+        {
+            /* decoder device coming from the external app */
+            sys->external.opaque          = var_InheritAddress( device, "vout-cb-opaque" );
+            sys->external.cleanupDeviceCb = var_InheritAddress( device, "vout-cb-cleanup" );
+            libvlc_video_direct3d_device_cfg_t cfg = {
+                .hardware_decoding = true, /* always favor hardware decoding */
+            };
+            libvlc_video_direct3d_device_setup_t out = { .device_context = NULL };
+            if (!setupDeviceCb( &sys->external.opaque, &cfg, &out ))
+            {
+                if (sys->external.cleanupDeviceCb)
+                    sys->external.cleanupDeviceCb( sys->external.opaque );
+                goto error;
+            }
+            D3D11_CreateDeviceExternal(device, out.device_context, true, &sys->d3d_dev);
+        }
+        else
+        {
+            /* internal decoder device */
+            HRESULT hr = D3D11_CreateDevice( device, &sys->hd3d, NULL,
+                                            true /* is_d3d11_opaque(chroma) */,
+                                            &sys->d3d_dev );
+            if ( FAILED( hr ) )
+            {
+                D3D11_Destroy(&sys->hd3d);
+                return VLC_EGENERIC;
+            }
+        }
+    }
+
+    if ( !sys->d3d_dev.d3dcontext )
+    {
+        return VLC_EGENERIC;
+    }
+
+    sys->dec_device.device = sys->d3d_dev.d3dcontext;
+    ID3D11DeviceContext_AddRef(sys->dec_device.device);
+
+    device->ops = &d3d11_dev_ops;
+    device->opaque = &sys->dec_device;
+    device->type = VLC_DECODER_DEVICE_D3D11VA;
+    device->sys = sys;
+
+    return VLC_SUCCESS;
+error:
+    D3D11_Destroy(&sys->hd3d);
+    vlc_obj_free( VLC_OBJECT(device), sys );
+    return VLC_EGENERIC;
+}
diff --git a/modules/hw/d3d11/d3d11_filters.c b/modules/hw/d3d11/d3d11_filters.c
index ae159a0d08..1feb03fc5f 100644
--- a/modules/hw/d3d11/d3d11_filters.c
+++ b/modules/hw/d3d11/d3d11_filters.c
@@ -33,6 +33,7 @@
 #include <vlc_plugin.h>
 #include <vlc_filter.h>
 #include <vlc_picture.h>
+#include <vlc_codec.h>
 
 #define COBJMACROS
 #include <d3d11.h>
@@ -585,4 +586,13 @@ vlc_module_begin()
     set_callbacks( D3D11OpenCPUConverter, D3D11CloseCPUConverter )
     set_capability( "video converter", 10 )
 
+    add_submodule()
+    set_description(N_("Direct3D11"))
+    set_callback_dec_device( D3D11OpenDecoderDevice, 20 )
+#if VLC_WINSTORE_APP
+    /* LEGACY, the d3dcontext and swapchain were given by the host app */
+    add_integer("winrt-d3dcontext",    0x0, NULL, NULL, true) /* ID3D11DeviceContext* */
+#endif /* VLC_WINSTORE_APP */
+    add_shortcut ("d3d11-device")
+
 vlc_module_end()
diff --git a/modules/hw/d3d11/d3d11_filters.h b/modules/hw/d3d11/d3d11_filters.h
index c4433937f9..0c03523dde 100644
--- a/modules/hw/d3d11/d3d11_filters.h
+++ b/modules/hw/d3d11/d3d11_filters.h
@@ -24,6 +24,7 @@
 #define VLC_D3D11_FILTERS_H
 
 #include <vlc_common.h>
+#include <vlc_vout_display.h>
 
 #include "../../video_chroma/d3d11_fmt.h"
 
@@ -34,6 +35,8 @@ void D3D11CloseConverter(vlc_object_t *);
 int  D3D11OpenCPUConverter(vlc_object_t *);
 void D3D11CloseCPUConverter(vlc_object_t *);
 
+int  D3D11OpenDecoderDevice(vlc_decoder_device *, vout_window_t *);
+
 void D3D11_FilterHoldInstance(filter_t *, d3d11_device_t *, D3D11_TEXTURE2D_DESC *);
 void D3D11_FilterReleaseInstance(d3d11_device_t *);
 



More information about the vlc-commits mailing list