d3d11: Move core methods to gst-libs

Move d3d11 device, memory, buffer pool and minimal method
to gst-libs so that other plugins can access d3d11 resource.
Since Direct3D is primary graphics API on Windows, we need
this infrastructure for various plugins can share GPU resource
without downloading GPU memory.
Note that this implementation is public only for -bad scope
for now.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/464>
This commit is contained in:
Seungha Yang 2020-12-21 02:47:45 +09:00 committed by GStreamer Merge Bot
parent 98eebf3322
commit 0f7af4b143
60 changed files with 2130 additions and 1479 deletions

View file

@ -0,0 +1,33 @@
/* GStreamer
* Copyright (C) 2020 GStreamer developers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_D3D11_PRELUDE_H__
#define __GST_D3D11_PRELUDE_H__
#include <gst/gst.h>
#ifndef GST_D3D11_API
# ifdef BUILDING_GST_D3D11
# define GST_D3D11_API GST_API_EXPORT /* from config.h */
# else
# define GST_D3D11_API GST_API_IMPORT
# endif
#endif
#endif /* __GST_D3D11_PRELUDE_H__ */

View file

@ -0,0 +1,37 @@
/* GStreamer
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_D3D11_H__
#define __GST_D3D11_H__
#ifndef GST_USE_UNSTABLE_API
#pragma message ("The d3d11 library from gst-plugins-bad is unstable API and may change in future.")
#pragma message ("You can define GST_USE_UNSTABLE_API to avoid this warning.")
#endif
#include <gst/gst.h>
#include <gst/d3d11/gstd3d11config.h>
#include <gst/d3d11/gstd3d11_fwd.h>
#include <gst/d3d11/gstd3d11device.h>
#include <gst/d3d11/gstd3d11memory.h>
#include <gst/d3d11/gstd3d11bufferpool.h>
#include <gst/d3d11/gstd3d11utils.h>
#include <gst/d3d11/gstd3d11format.h>
#endif /* __GST_D3D11_H__ */

View file

@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -21,33 +22,34 @@
#define __GST_D3D11_FWD_H__
#include <gst/gst.h>
#include "gstd3d11config.h"
#include <gst/d3d11/gstd3d11config.h>
#include <gst/d3d11/d3d11-prelude.h>
#ifndef INITGUID
#include <initguid.h>
#endif
#if (D3D11_HEADER_VERSION >= 4)
#if (GST_D3D11_HEADER_VERSION >= 4)
#include <d3d11_4.h>
#elif (D3D11_HEADER_VERSION >= 3)
#elif (GST_D3D11_HEADER_VERSION >= 3)
#include <d3d11_3.h>
#elif (D3D11_HEADER_VERSION >= 2)
#elif (GST_D3D11_HEADER_VERSION >= 2)
#include <d3d11_2.h>
#elif (D3D11_HEADER_VERSION >= 1)
#elif (GST_D3D11_HEADER_VERSION >= 1)
#include <d3d11_1.h>
#else
#include <d3d11.h>
#endif
#if (DXGI_HEADER_VERSION >= 6)
#if (GST_D3D11_DXGI_H_VERSION >= 6)
#include <dxgi1_6.h>
#elif (DXGI_HEADER_VERSION >= 5)
#elif (GST_D3D11_DXGI_H_VERSION >= 5)
#include <dxgi1_5.h>
#elif (DXGI_HEADER_VERSION >= 4)
#elif (GST_D3D11_DXGI_H_VERSION >= 4)
#include <dxgi1_4.h>
#elif (DXGI_HEADER_VERSION >= 3)
#elif (GST_D3D11_DXGI_H_VERSION >= 3)
#include <dxgi1_3.h>
#elif (DXGI_HEADER_VERSION >= 2)
#elif (GST_D3D11_DXGI_H_VERSION >= 2)
#include <dxgi1_2.h>
#else
#include <dxgi.h>
@ -61,6 +63,7 @@ typedef struct _GstD3D11DevicePrivate GstD3D11DevicePrivate;
typedef struct _GstD3D11AllocationParams GstD3D11AllocationParams;
typedef struct _GstD3D11Memory GstD3D11Memory;
typedef struct _GstD3D11MemoryPrivate GstD3D11MemoryPrivate;
typedef struct _GstD3D11Allocator GstD3D11Allocator;
typedef struct _GstD3D11AllocatorClass GstD3D11AllocatorClass;
typedef struct _GstD3D11AllocatorPrivate GstD3D11AllocatorPrivate;

View file

@ -0,0 +1,41 @@
/* GStreamer
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_D3D11_PRIVATE_H__
#define __GST_D3D11_PRIVATE_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/d3d11/gstd3d11_fwd.h>
G_BEGIN_DECLS
void gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
const gchar * file,
const gchar * function,
gint line);
void gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
const gchar * file,
const gchar * function,
gint line);
G_END_DECLS
#endif /* __GST_D3D11_PRIVATE_H__ */

View file

@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -28,6 +29,17 @@
#include <string.h>
/**
* SECTION:gstd3d11bufferpool
* @title: GstD3D11BufferPool
* @short_description: buffer pool for #GstD3D11Memory objects
* @see_also: #GstBufferPool, #GstGLMemory
*
* a #GstD3D11BufferPool is an object that allocates buffers with #GstD3D11Memory
*
* A #GstGLBufferPool is created with gst_d3d11_buffer_pool_new()
*/
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_buffer_pool_debug);
#define GST_CAT_DEFAULT gst_d3d11_buffer_pool_debug
@ -106,6 +118,79 @@ gst_d3d11_buffer_pool_get_options (GstBufferPool * pool)
return options;
}
static GstBuffer *
allocate_staging_buffer (GstD3D11Allocator * allocator,
const GstVideoInfo * info, const GstD3D11Format * format,
const D3D11_TEXTURE2D_DESC desc[GST_VIDEO_MAX_PLANES],
gboolean add_videometa)
{
GstBuffer *buffer;
gint i;
gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
GstMemory *mem;
g_return_val_if_fail (GST_IS_D3D11_ALLOCATOR (allocator), NULL);
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (format != NULL, NULL);
g_return_val_if_fail (desc != NULL, NULL);
buffer = gst_buffer_new ();
if (format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
gsize size[GST_VIDEO_MAX_PLANES] = { 0, };
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
mem = gst_d3d11_allocator_alloc_staging (allocator, &desc[i], 0,
&stride[i]);
if (!mem) {
GST_ERROR_OBJECT (allocator, "Couldn't allocate memory for plane %d",
i);
goto error;
}
size[i] = gst_memory_get_sizes (mem, NULL, NULL);
if (i > 0)
offset[i] = offset[i - 1] + size[i - 1];
gst_buffer_append_memory (buffer, mem);
}
} else {
/* must be YUV semi-planar or single plane */
g_assert (GST_VIDEO_INFO_N_PLANES (info) <= 2);
mem = gst_d3d11_allocator_alloc_staging (allocator, &desc[0], 0,
&stride[0]);
if (!mem) {
GST_ERROR_OBJECT (allocator, "Couldn't allocate memory");
goto error;
}
gst_memory_get_sizes (mem, NULL, NULL);
gst_buffer_append_memory (buffer, mem);
if (GST_VIDEO_INFO_N_PLANES (info) == 2) {
stride[1] = stride[0];
offset[1] = stride[0] * desc[0].Height;
}
}
if (add_videometa) {
gst_buffer_add_video_meta_full (buffer, GST_VIDEO_FRAME_FLAG_NONE,
GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
offset, stride);
}
return buffer;
error:
gst_buffer_unref (buffer);
return NULL;
}
static gboolean
gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
{
@ -230,7 +315,7 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
}
}
staging_buffer = gst_d3d11_allocate_staging_buffer (priv->allocator,
staging_buffer = allocate_staging_buffer (priv->allocator,
&info, priv->d3d11_params->d3d11_format, priv->d3d11_params->desc, TRUE);
if (!staging_buffer) {
@ -360,6 +445,14 @@ gst_d3d11_buffer_pool_flush_stop (GstBufferPool * pool)
gst_d3d11_allocator_set_flushing (priv->allocator, FALSE);
}
/**
* gst_d3d11_buffer_pool_new:
* @device: a #GstD3D11Device to use
*
* Returns: a #GstBufferPool that allocates buffers with #GstD3D11Memory
*
* Since: 1.20
*/
GstBufferPool *
gst_d3d11_buffer_pool_new (GstD3D11Device * device)
{
@ -377,6 +470,16 @@ gst_d3d11_buffer_pool_new (GstD3D11Device * device)
return GST_BUFFER_POOL_CAST (pool);
}
/**
* gst_buffer_pool_config_get_d3d11_allocation_params:
* @config: a buffer pool config
*
* Returns: (transfer full) (nullable): the currently configured
* #GstD3D11AllocationParams on @config or %NULL if @config doesn't contain
* #GstD3D11AllocationParams
*
* Since: 1.20
*/
GstD3D11AllocationParams *
gst_buffer_pool_config_get_d3d11_allocation_params (GstStructure * config)
{
@ -389,6 +492,15 @@ gst_buffer_pool_config_get_d3d11_allocation_params (GstStructure * config)
return ret;
}
/**
* gst_buffer_pool_config_set_d3d11_allocation_params:
* @config: a buffer pool config
* @params: (transfer none): a #GstD3D11AllocationParams
*
* Sets @params on @config
*
* Since: 1.20
*/
void
gst_buffer_pool_config_set_d3d11_allocation_params (GstStructure * config,
GstD3D11AllocationParams * params)

View file

@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -23,8 +24,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11_fwd.h>
G_BEGIN_DECLS
@ -56,12 +56,16 @@ struct _GstD3D11BufferPoolClass
gpointer _gst_reserved[GST_PADDING];
};
GST_D3D11_API
GType gst_d3d11_buffer_pool_get_type (void);
GstBufferPool * gst_d3d11_buffer_pool_new (GstD3D11Device *device);
GST_D3D11_API
GstBufferPool * gst_d3d11_buffer_pool_new (GstD3D11Device * device);
GST_D3D11_API
GstD3D11AllocationParams * gst_buffer_pool_config_get_d3d11_allocation_params (GstStructure * config);
GST_D3D11_API
void gst_buffer_pool_config_set_d3d11_allocation_params (GstStructure * config,
GstD3D11AllocationParams * params);

View file

@ -0,0 +1,16 @@
/* gstd3d11config.h */
#ifndef __GST_D3D11_CONFIG_H__
#define __GST_D3D11_CONFIG_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#mesondefine GST_D3D11_DXGI_HEADER_VERSION
#mesondefine GST_D3D11_HEADER_VERSION
#mesondefine GST_D3D11_WINAPI_ONLY_APP
G_END_DECLS
#endif /* __GST_D3D11_CONFIG_H__ */

View file

@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -24,7 +25,26 @@
#include "gstd3d11device.h"
#include "gstd3d11utils.h"
#include "gstd3d11format.h"
#include "gmodule.h"
#include "gstd3d11_private.h"
#include <gmodule.h>
#include <windows.h>
#include <versionhelpers.h>
/**
* SECTION:gstd3d11device
* @short_description: Direct3D11 device abstraction
* @title: GstD3D11Device
*
* #GstD3D11Device wraps ID3D11Device and ID3D11DeviceContext for GPU resources
* to be able to be shared among various elements. Caller can get native
* Direct3D11 handles via getter method.
* Basically Direct3D11 API doesn't require dedicated thread like that of
* OpenGL context, and ID3D11Device APIs are supposed to be thread-safe.
* But concurrent call for ID3D11DeviceContext and DXGI API are not allowed.
* To protect such object, callers need to make use of gst_d3d11_device_lock()
* and gst_d3d11_device_unlock()
*/
#if HAVE_D3D11SDKLAYERS_H
#include <d3d11sdklayers.h>
@ -48,9 +68,9 @@ static DXGIGetDebugInterface_t GstDXGIGetDebugInterface = NULL;
#endif
#if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_debug_layer_debug);
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_debug_layer_debug);
#endif
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_device_debug);
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_device_debug);
#define GST_CAT_DEFAULT gst_d3d11_device_debug
enum
@ -99,8 +119,20 @@ struct _GstD3D11DevicePrivate
#endif
};
static void
do_debug_init (void)
{
GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug,
"d3d11device", 0, "d3d11 device object");
#if defined(HAVE_D3D11SDKLAYERS_H) || defined(HAVE_DXGIDEBUG_H)
GST_DEBUG_CATEGORY_INIT (gst_d3d11_debug_layer_debug,
"d3d11debuglayer", 0, "native d3d11 and dxgi debug");
#endif
}
#define gst_d3d11_device_parent_class parent_class
G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Device, gst_d3d11_device, GST_TYPE_OBJECT);
G_DEFINE_TYPE_WITH_CODE (GstD3D11Device, gst_d3d11_device, GST_TYPE_OBJECT,
G_ADD_PRIVATE (GstD3D11Device); do_debug_init ());
static void gst_d3d11_device_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
@ -215,7 +247,7 @@ gst_d3d11_device_enable_dxgi_debug (void)
g_module_symbol (dxgi_debug_module,
"DXGIGetDebugInterface", (gpointer *) & GstDXGIGetDebugInterface);
ret = ! !GstDXGIGetDebugInterface;
#elif (DXGI_HEADER_VERSION >= 3)
#elif (GST_D3D11_DXGI_HEADER_VERSION >= 3)
ret = TRUE;
#endif
g_once_init_leave (&_init, 1);
@ -231,7 +263,7 @@ gst_d3d11_device_dxgi_get_device_interface (REFIID riid, void **debug)
if (GstDXGIGetDebugInterface) {
return GstDXGIGetDebugInterface (riid, debug);
}
#elif (DXGI_HEADER_VERSION >= 3)
#elif (GST_D3D11_DXGI_HEADER_VERSION >= 3)
return DXGIGetDebugInterface1 (0, riid, debug);
#endif
@ -374,6 +406,26 @@ gst_d3d11_device_init (GstD3D11Device * self)
self->priv = priv;
}
static gboolean
is_windows_8_or_greater (void)
{
static gsize version_once = 0;
static gboolean ret = FALSE;
if (g_once_init_enter (&version_once)) {
#if (!GST_D3D11_WINAPI_ONLY_APP)
if (IsWindows8OrGreater ())
ret = TRUE;
#else
ret = TRUE;
#endif
g_once_init_leave (&version_once, 1);
}
return ret;
}
static gboolean
can_support_format (GstD3D11Device * self, DXGI_FORMAT format,
D3D11_FORMAT_SUPPORT extra_flags)
@ -386,7 +438,7 @@ can_support_format (GstD3D11Device * self, DXGI_FORMAT format,
flags |= extra_flags;
if (!gst_d3d11_is_windows_8_or_greater ()) {
if (!is_windows_8_or_greater ()) {
GST_WARNING_OBJECT (self, "DXGI format %d needs Windows 8 or greater",
(guint) format);
return FALSE;
@ -567,7 +619,7 @@ gst_d3d11_device_constructed (GObject * object)
D3D_FEATURE_LEVEL selected_level;
GST_DEBUG_OBJECT (self,
"Built with DXGI header version %d", DXGI_HEADER_VERSION);
"Built with DXGI header version %d", GST_D3D11_DXGI_HEADER_VERSION);
#if HAVE_DXGIDEBUG_H
if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
@ -601,7 +653,7 @@ gst_d3d11_device_constructed (GObject * object)
}
#endif
#if (DXGI_HEADER_VERSION >= 5)
#if (GST_D3D11_DXGI_HEADER_VERSION >= 5)
hr = CreateDXGIFactory1 (&IID_IDXGIFactory5, (void **) &factory);
if (!gst_d3d11_result (hr, NULL)) {
GST_INFO_OBJECT (self, "IDXGIFactory5 was unavailable");
@ -714,7 +766,8 @@ gst_d3d11_device_constructed (GObject * object)
if (gst_d3d11_result (hr, NULL)) {
GST_DEBUG_OBJECT (self, "Selected feature level 0x%x", selected_level);
} else {
GST_ERROR_OBJECT (self, "cannot create d3d11 device, hr: 0x%x", (guint) hr);
GST_WARNING_OBJECT (self,
"cannot create d3d11 device, hr: 0x%x", (guint) hr);
goto error;
}
@ -901,8 +954,10 @@ gst_d3d11_device_finalize (GObject * object)
* @adapter: the index of adapter for creating d3d11 device
* @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
*
* Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter or %NULL
* when failed to create D3D11 device with given adapter index.
* Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter
* or %NULL when failed to create D3D11 device with given adapter index.
*
* Since: 1.20
*/
GstD3D11Device *
gst_d3d11_device_new (guint adapter, guint flags)
@ -929,10 +984,12 @@ gst_d3d11_device_new (guint adapter, guint flags)
* gst_d3d11_device_get_device_handle:
* @device: a #GstD3D11Device
*
* Used for various D3D11 APIs directly.
* Caller must not destroy returned device object.
* Used for various D3D11 APIs directly. Caller must not destroy returned device
* object.
*
* Returns: (transfer none): the ID3D11Device
* Returns: (transfer none): the ID3D11Device handle
*
* Since: 1.20
*/
ID3D11Device *
gst_d3d11_device_get_device_handle (GstD3D11Device * device)
@ -946,10 +1003,13 @@ gst_d3d11_device_get_device_handle (GstD3D11Device * device)
* gst_d3d11_device_get_device_context_handle:
* @device: a #GstD3D11Device
*
* Used for various D3D11 APIs directly.
* Caller must not destroy returned device object.
* Used for various D3D11 APIs directly. Caller must not destroy returned device
* object. Any ID3D11DeviceContext call needs to be protected by
* gst_d3d11_device_lock() and gst_d3d11_device_unlock() method.
*
* Returns: (transfer none): the ID3D11DeviceContext
* Returns: (transfer none): the immeidate ID3D11DeviceContext handle
*
* Since: 1.20
*/
ID3D11DeviceContext *
gst_d3d11_device_get_device_context_handle (GstD3D11Device * device)
@ -959,6 +1019,17 @@ gst_d3d11_device_get_device_context_handle (GstD3D11Device * device)
return device->priv->device_context;
}
/**
* gst_d3d11_device_get_dxgi_factory_handle:
* @device: a #GstD3D11Device
*
* Used for various D3D11 APIs directly. Caller must not destroy returned device
* object.
*
* Returns: (transfer none): the IDXGIFactory1 handle
*
* Since: 1.20
*/
IDXGIFactory1 *
gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device)
{
@ -967,6 +1038,16 @@ gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device)
return device->priv->factory;
}
/**
* gst_d3d11_device_lock:
* @device: a #GstD3D11Device
*
* Take lock for @device. Any thread-unsafe API call needs to be
* protected by this method. This call must be paired with
* gst_d3d11_device_unlock()
*
* Since: 1.20
*/
void
gst_d3d11_device_lock (GstD3D11Device * device)
{
@ -981,6 +1062,15 @@ gst_d3d11_device_lock (GstD3D11Device * device)
GST_TRACE_OBJECT (device, "device locked");
}
/**
* gst_d3d11_device_unlock:
* @device: a #GstD3D11Device
*
* Release lock for @device. This call must be paired with
* gst_d3d11_device_lock()
*
* Since: 1.20
*/
void
gst_d3d11_device_unlock (GstD3D11Device * device)
{
@ -994,6 +1084,16 @@ gst_d3d11_device_unlock (GstD3D11Device * device)
GST_TRACE_OBJECT (device, "device unlocked");
}
/**
* gst_d3d11_device_format_from_gst:
* @device: a #GstD3D11Device
* @format: a #GstVideoFormat
*
* Returns: (transfer none) (nullable): a pointer to #GstD3D11Format
* or %NULL if @format is not supported by @device
*
* Since: 1.20
*/
const GstD3D11Format *
gst_d3d11_device_format_from_gst (GstD3D11Device * device,
GstVideoFormat format)

View file

@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -22,8 +23,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11_fwd.h>
G_BEGIN_DECLS
@ -55,31 +55,29 @@ struct _GstD3D11DeviceClass
gpointer _gst_reserved[GST_PADDING];
};
GST_D3D11_API
GType gst_d3d11_device_get_type (void);
GST_D3D11_API
GstD3D11Device * gst_d3d11_device_new (guint adapter,
guint flags);
GST_D3D11_API
ID3D11Device * gst_d3d11_device_get_device_handle (GstD3D11Device * device);
GST_D3D11_API
ID3D11DeviceContext * gst_d3d11_device_get_device_context_handle (GstD3D11Device * device);
GST_D3D11_API
IDXGIFactory1 * gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device);
GST_D3D11_API
void gst_d3d11_device_lock (GstD3D11Device * device);
GST_D3D11_API
void gst_d3d11_device_unlock (GstD3D11Device * device);
void gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
const gchar * file,
const gchar * function,
gint line);
void gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
const gchar * file,
const gchar * function,
gint line);
GST_D3D11_API
const GstD3D11Format * gst_d3d11_device_format_from_gst (GstD3D11Device * device,
GstVideoFormat format);

View file

@ -0,0 +1,152 @@
/* GStreamer
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstd3d11format.h"
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include <string.h>
#ifndef GST_DISABLE_GST_DEBUG
#define GST_CAT_DEFAULT ensure_debug_category()
static GstDebugCategory *
ensure_debug_category (void)
{
static gsize cat_gonce = 0;
if (g_once_init_enter (&cat_gonce)) {
gsize cat_done;
cat_done = (gsize) _gst_debug_category_new ("d3d11format", 0,
"d3d11 specific formats");
g_once_init_leave (&cat_gonce, cat_done);
}
return (GstDebugCategory *) cat_gonce;
}
#else
#define ensure_debug_category() /* NOOP */
#endif /* GST_DISABLE_GST_DEBUG */
/**
* gst_d3d11_dxgi_format_n_planes:
* @format: a DXGI_FORMAT
*
* Returns: the number of planes for @format
*
* Since: 1.20
*/
guint
gst_d3d11_dxgi_format_n_planes (DXGI_FORMAT format)
{
switch (format) {
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_YUY2:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y410:
case DXGI_FORMAT_R16G16B16A16_UNORM:
return 1;
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
return 2;
default:
break;
}
return 0;
}
/**
* gst_d3d11_dxgi_format_get_size:
* @format: a DXGI_FORMAT
* @width: a texture width
* @height: a texture height
* @pitch: a pitch of texture
* @offset: offset for each plane
* @stride: stride for each plane
* @size: (out): required memory size for given format
*
* Calculate required memory size and per plane stride with
* based on information
*
* Returns: %TRUE if @size can be calculated with given information
*
* Since: 1.20
*/
gboolean
gst_d3d11_dxgi_format_get_size (DXGI_FORMAT format, guint width, guint height,
guint pitch, gsize offset[GST_VIDEO_MAX_PLANES],
gint stride[GST_VIDEO_MAX_PLANES], gsize * size)
{
g_return_val_if_fail (format != DXGI_FORMAT_UNKNOWN, FALSE);
switch (format) {
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_YUY2:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y410:
case DXGI_FORMAT_R16G16B16A16_UNORM:
offset[0] = 0;
stride[0] = pitch;
*size = pitch * height;
break;
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
offset[0] = 0;
stride[0] = pitch;
offset[1] = offset[0] + stride[0] * height;
stride[1] = pitch;
*size = offset[1] + stride[1] * GST_ROUND_UP_2 (height / 2);
break;
default:
return FALSE;
}
GST_LOG ("Calculated buffer size: %" G_GSIZE_FORMAT
" (dxgi format:%d, %dx%d, Pitch %d)",
*size, format, width, height, pitch);
return TRUE;
}

View file

@ -22,8 +22,9 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/d3d11/gstd3d11_fwd.h>
#include "gstd3d11_fwd.h"
G_BEGIN_DECLS
#define GST_D3D11_COMMON_FORMATS \
"BGRA, RGBA, RGB10A2_LE, VUYA, NV12, P010_10LE, P016_LE, I420, I420_10LE"
@ -42,10 +43,6 @@
#define GST_D3D11_N_FORMATS 14
G_BEGIN_DECLS
typedef struct _GstDxgiColorSpace GstDxgiColorSpace;
struct _GstD3D11Format
{
GstVideoFormat format;
@ -54,20 +51,16 @@ struct _GstD3D11Format
DXGI_FORMAT dxgi_format;
/* formats for texture processing */
DXGI_FORMAT resource_format[GST_VIDEO_MAX_COMPONENTS];
};
struct _GstDxgiColorSpace
{
guint dxgi_color_space_type;
GstVideoColorRange range;
GstVideoColorMatrix matrix;
GstVideoTransferFunction transfer;
GstVideoColorPrimaries primaries;
DXGI_FORMAT resource_format[GST_VIDEO_MAX_PLANES];
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GST_D3D11_API
guint gst_d3d11_dxgi_format_n_planes (DXGI_FORMAT format);
GST_D3D11_API
gboolean gst_d3d11_dxgi_format_get_size (DXGI_FORMAT format,
guint width,
guint height,
@ -76,23 +69,6 @@ gboolean gst_d3d11_dxgi_format_get_size (DXGI_FORMAT format,
gint stride[GST_VIDEO_MAX_PLANES],
gsize *size);
GstCaps * gst_d3d11_device_get_supported_caps (GstD3D11Device * device,
D3D11_FORMAT_SUPPORT flags);
#if (DXGI_HEADER_VERSION >= 5)
gboolean gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
GstVideoContentLightLevel * cll,
DXGI_HDR_METADATA_HDR10 * dxgi_hdr10);
#endif
#if (DXGI_HEADER_VERSION >= 4)
const GstDxgiColorSpace * gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info);
const GstDxgiColorSpace * gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
IDXGISwapChain3 * swapchain,
gboolean use_hdr10);
#endif
G_END_DECLS
#endif /* __GST_D3D11_FORMAT_H__ */

View file

@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -38,9 +39,26 @@ GST_DEBUG_CATEGORY_STATIC (gst_d3d11_allocator_debug);
#define GST_D3D11_MEMORY_LOCK(m) g_mutex_lock(GST_D3D11_MEMORY_GET_LOCK(m))
#define GST_D3D11_MEMORY_UNLOCK(m) g_mutex_unlock(GST_D3D11_MEMORY_GET_LOCK(m))
#define GST_D3D11_MEMORY_NAME "D3D11Memory"
/**
* gst_d3d11_allocation_params_new:
* @device: a #GstD3D11Device
* @info: a #GstVideoInfo
* @flags: a #GstD3D11AllocationFlags
* @bind_flags: D3D11_BIND_FLAG value used for creating Direct3D11 texture
*
* Create #GstD3D11AllocationParams object which is used by #GstD3D11BufferPool
* and #GstD3D11Allocator in order to allocate new ID3D11Texture2D
* object with given configuration
*
* Returns: a #GstD3D11AllocationParams or %NULL if @info is not supported
*
* Since: 1.20
*/
GstD3D11AllocationParams *
gst_d3d11_allocation_params_new (GstD3D11Device * device, GstVideoInfo * info,
GstD3D11AllocationFlags flags, gint bind_flags)
GstD3D11AllocationFlags flags, guint bind_flags)
{
GstD3D11AllocationParams *ret;
const GstD3D11Format *d3d11_format;
@ -106,6 +124,18 @@ gst_d3d11_allocation_params_new (GstD3D11Device * device, GstVideoInfo * info,
return ret;
}
/**
* gst_d3d11_allocation_params_alignment:
* @params: a #GstD3D11AllocationParams
* @align: a #GstVideoAlignment
*
* Adjust Width and Height fields of D3D11_TEXTURE2D_DESC with given
* @align
*
* Returns: %TRUE if alignment could be applied
*
* Since: 1.20
*/
gboolean
gst_d3d11_allocation_params_alignment (GstD3D11AllocationParams * params,
GstVideoAlignment * align)
@ -141,6 +171,14 @@ gst_d3d11_allocation_params_alignment (GstD3D11AllocationParams * params,
return TRUE;
}
/**
* gst_d3d11_allocation_params_copy:
* @src: a #GstD3D11AllocationParams
*
* Returns: a copy of @src
*
* Since: 1.20
*/
GstD3D11AllocationParams *
gst_d3d11_allocation_params_copy (GstD3D11AllocationParams * src)
{
@ -154,6 +192,14 @@ gst_d3d11_allocation_params_copy (GstD3D11AllocationParams * src)
return dst;
}
/**
* gst_d3d11_allocation_params_free:
* @params: a #GstD3D11AllocationParams
*
* Free @params
*
* Since: 1.20
*/
void
gst_d3d11_allocation_params_free (GstD3D11AllocationParams * params)
{
@ -608,6 +654,14 @@ gst_d3d11_allocator_init (GstD3D11Allocator * allocator)
allocator->priv = priv;
}
/**
* gst_d3d11_allocator_new:
* @device: a #GstD3D11Device
*
* Returns: a newly created #GstD3D11Allocator
*
* Since: 1.20
*/
GstD3D11Allocator *
gst_d3d11_allocator_new (GstD3D11Device * device)
{
@ -860,6 +914,17 @@ check_bind_flags_for_processor_input_view (guint bind_flags)
return FALSE;
}
/**
* gst_d3d11_allocator_alloc:
* @allocator: a #GstD3D11Allocator
* @desc: a D3D11_TEXTURE2D_DESC struct
* @flags: a #GstD3D11AllocationFlags
* @size: a size of CPU accesible memory
*
* Returns: a newly allocated #GstD3D11Memory with given parameters.
*
* Since: 1.20
*/
GstMemory *
gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
const D3D11_TEXTURE2D_DESC * desc, GstD3D11AllocationFlags flags,
@ -978,6 +1043,18 @@ error:
return NULL;
}
/**
* gst_d3d11_allocator_alloc_staging:
* @allocator: a #GstD3D11Allocator
* @desc: a D3D11_TEXTURE2D_DESC struct
* @flags: a #GstD3D11AllocationFlags
* @stride: (out): a stride of CPU accesible memory
*
* Returns: a newly allocated #GstD3D11Memory with given parameters.
* Returned #GstD3D11Memory can be used only for staging texture.
*
* Since: 1.20
*/
GstMemory *
gst_d3d11_allocator_alloc_staging (GstD3D11Allocator * allocator,
const D3D11_TEXTURE2D_DESC * desc, GstD3D11AllocationFlags flags,
@ -1031,6 +1108,15 @@ error:
return NULL;
}
/**
* gst_d3d11_allocator_set_flushing:
* @allocator: a #GstD3D11Allocator
* @flusing: whether to start or stop flusing
*
* Enable or disable the flushing state of @allocator.
*
* Since: 1.20
*/
void
gst_d3d11_allocator_set_flushing (GstD3D11Allocator * allocator,
gboolean flushing)
@ -1047,6 +1133,14 @@ gst_d3d11_allocator_set_flushing (GstD3D11Allocator * allocator,
GST_D3D11_ALLOCATOR_UNLOCK (allocator);
}
/**
* gst_is_d3d11_memory:
* @mem: a #GstMemory
*
* Returns: whether @mem is a #GstD3D11Memory
*
* Since: 1.20
*/
gboolean
gst_is_d3d11_memory (GstMemory * mem)
{
@ -1054,6 +1148,15 @@ gst_is_d3d11_memory (GstMemory * mem)
GST_IS_D3D11_ALLOCATOR (mem->allocator);
}
/**
* gst_d3d11_memory_get_texture_handle:
* @mem: a #GstD3D11Memory
*
* Returns: (transfer none): a ID3D11Texture2D handle. Caller must not release
* returned handle.
*
* Since: 1.20
*/
ID3D11Texture2D *
gst_d3d11_memory_get_texture_handle (GstD3D11Memory * mem)
{
@ -1062,6 +1165,14 @@ gst_d3d11_memory_get_texture_handle (GstD3D11Memory * mem)
return mem->priv->texture;
}
/**
* gst_d3d11_memory_get_subresource_index:
* @mem: a #GstD3D11Memory
*
* Returns: subresource index corresponding to @mem.
*
* Since: 1.20
*/
guint
gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem)
{
@ -1070,6 +1181,17 @@ gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem)
return mem->priv->subresource_index;
}
/**
* gst_d3d11_memory_get_texture_desc:
* @mem: a #GstD3D11Memory
* @desc: (out): a D3D11_TEXTURE2D_DESC
*
* Fill @desc with D3D11_TEXTURE2D_DESC for ID3D11Texture2D
*
* Returns: %TRUE if successeed
*
* Since: 1.20
*/
gboolean
gst_d3d11_memory_get_texture_desc (GstD3D11Memory * mem,
D3D11_TEXTURE2D_DESC * desc)
@ -1108,6 +1230,15 @@ done:
return ret;
}
/**
* gst_d3d11_memory_get_shader_resource_view_size:
* @mem: a #GstD3D11Memory
*
* Returns: the number of ID3D11ShaderResourceView that can be used
* for processing GPU operation with @mem
*
* Since: 1.20
*/
guint
gst_d3d11_memory_get_shader_resource_view_size (GstD3D11Memory * mem)
{
@ -1119,6 +1250,17 @@ gst_d3d11_memory_get_shader_resource_view_size (GstD3D11Memory * mem)
return mem->priv->num_shader_resource_views;
}
/**
* gst_d3d11_memory_get_shader_resource_view:
* @mem: a #GstD3D11Memory
* @index: the index of the ID3D11ShaderResourceView
*
* Returns: (transfer none) (nullable): a pointer to the
* ID3D11ShaderResourceView or %NULL if ID3D11ShaderResourceView is unavailable
* for @index
*
* Since: 1.20
*/
ID3D11ShaderResourceView *
gst_d3d11_memory_get_shader_resource_view (GstD3D11Memory * mem, guint index)
{
@ -1165,6 +1307,15 @@ done:
return ret;
}
/**
* gst_d3d11_memory_get_render_target_view_size:
* @mem: a #GstD3D11Memory
*
* Returns: the number of ID3D11RenderTargetView that can be used
* for processing GPU operation with @mem
*
* Since: 1.20
*/
guint
gst_d3d11_memory_get_render_target_view_size (GstD3D11Memory * mem)
{
@ -1176,6 +1327,17 @@ gst_d3d11_memory_get_render_target_view_size (GstD3D11Memory * mem)
return mem->priv->num_render_target_views;
}
/**
* gst_d3d11_memory_get_render_target_view:
* @mem: a #GstD3D11Memory
* @index: the index of the ID3D11RenderTargetView
*
* Returns: (transfer none) (nullable): a pointer to the
* ID3D11RenderTargetView or %NULL if ID3D11RenderTargetView is unavailable
* for @index
*
* Since: 1.20
*/
ID3D11RenderTargetView *
gst_d3d11_memory_get_render_target_view (GstD3D11Memory * mem, guint index)
{
@ -1299,6 +1461,16 @@ done:
return ret;
}
/**
* gst_d3d11_memory_get_decoder_output_view:
* @mem: a #GstD3D11Memory
*
* Returns: (transfer none) (nullable): a pointer to the
* ID3D11VideoDecoderOutputView or %NULL if ID3D11VideoDecoderOutputView is
* unavailable
*
* Since: 1.20
*/
ID3D11VideoDecoderOutputView *
gst_d3d11_memory_get_decoder_output_view (GstD3D11Memory * mem,
ID3D11VideoDevice * video_device, GUID * decoder_profile)
@ -1395,6 +1567,18 @@ done:
return ret;
}
/**
* gst_d3d11_memory_get_processor_input_view:
* @mem: a #GstD3D11Memory
* @video_device: a #ID3D11VideoDevice
* @enumerator: a #ID3D11VideoProcessorEnumerator
*
* Returns: (transfer none) (nullable): a pointer to the
* ID3D11VideoProcessorInputView or %NULL if ID3D11VideoProcessorInputView is
* unavailable
*
* Since: 1.20
*/
ID3D11VideoProcessorInputView *
gst_d3d11_memory_get_processor_input_view (GstD3D11Memory * mem,
ID3D11VideoDevice * video_device,
@ -1462,6 +1646,18 @@ done:
return ret;
}
/**
* gst_d3d11_memory_get_processor_output_view:
* @mem: a #GstD3D11Memory
* @video_device: a #ID3D11VideoDevice
* @enumerator: a #ID3D11VideoProcessorEnumerator
*
* Returns: (transfer none) (nullable): a pointer to the
* ID3D11VideoProcessorOutputView or %NULL if ID3D11VideoProcessorOutputView is
* unavailable
*
* Since: 1.20
*/
ID3D11VideoProcessorOutputView *
gst_d3d11_memory_get_processor_output_view (GstD3D11Memory * mem,
ID3D11VideoDevice * video_device,

View file

@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -23,9 +24,8 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11format.h"
#include <gst/d3d11/gstd3d11_fwd.h>
#include <gst/d3d11/gstd3d11format.h>
G_BEGIN_DECLS
@ -38,14 +38,12 @@ G_BEGIN_DECLS
#define GST_D3D11_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_D3D11_ALLOCATOR, GstD3D11AllocatorClass))
#define GST_D3D11_ALLOCATOR_CAST(obj) ((GstD3D11Allocator *)obj)
typedef struct _GstD3D11MemoryPrivate GstD3D11MemoryPrivate;
#define GST_D3D11_MEMORY_NAME "D3D11Memory"
/**
* GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY:
*
* Name of the caps feature for indicating the use of #GstD3D11Memory
*
* Since: 1.20
*/
#define GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY "memory:D3D11Memory"
@ -53,12 +51,19 @@ typedef struct _GstD3D11MemoryPrivate GstD3D11MemoryPrivate;
* GST_MAP_D3D11:
*
* Flag indicating that we should map the D3D11 resource instead of to system memory.
*
* Since: 1.20
*/
#define GST_MAP_D3D11 (GST_MAP_FLAG_LAST << 1)
/**
* GstD3D11AllocationFlags:
* GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY: Indicates each allocated texture should be array type
* GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY: Indicates each allocated texture
* should be array type. This type of
* is used for D3D11/DXVA decoders
* in general.
*
* Since: 1.20
*/
typedef enum
{
@ -71,6 +76,8 @@ typedef enum
* to the staging texture memory
* @GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD: the staging texture needs uploading
* to the texture
*
* Since: 1.20
*/
typedef enum
{
@ -124,65 +131,85 @@ struct _GstD3D11AllocatorClass
gpointer _gst_reserved[GST_PADDING];
};
GST_D3D11_API
GType gst_d3d11_allocation_params_get_type (void);
GST_D3D11_API
GstD3D11AllocationParams * gst_d3d11_allocation_params_new (GstD3D11Device * device,
GstVideoInfo * info,
GstD3D11AllocationFlags flags,
gint bind_flags);
guint bind_flags);
GST_D3D11_API
GstD3D11AllocationParams * gst_d3d11_allocation_params_copy (GstD3D11AllocationParams * src);
GST_D3D11_API
void gst_d3d11_allocation_params_free (GstD3D11AllocationParams * params);
GST_D3D11_API
gboolean gst_d3d11_allocation_params_alignment (GstD3D11AllocationParams * parms,
GstVideoAlignment * align);
GST_D3D11_API
GType gst_d3d11_allocator_get_type (void);
GST_D3D11_API
GstD3D11Allocator * gst_d3d11_allocator_new (GstD3D11Device *device);
GST_D3D11_API
GstMemory * gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
const D3D11_TEXTURE2D_DESC * desc,
GstD3D11AllocationFlags flags,
gsize size);
GST_D3D11_API
GstMemory * gst_d3d11_allocator_alloc_staging (GstD3D11Allocator * allocator,
const D3D11_TEXTURE2D_DESC * desc,
GstD3D11AllocationFlags flags,
gint * stride);
GST_D3D11_API
void gst_d3d11_allocator_set_flushing (GstD3D11Allocator * allocator,
gboolean flushing);
GST_D3D11_API
gboolean gst_is_d3d11_memory (GstMemory * mem);
GST_D3D11_API
ID3D11Texture2D * gst_d3d11_memory_get_texture_handle (GstD3D11Memory * mem);
GST_D3D11_API
gboolean gst_d3d11_memory_get_texture_desc (GstD3D11Memory * mem,
D3D11_TEXTURE2D_DESC * desc);
GST_D3D11_API
guint gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem);
GST_D3D11_API
guint gst_d3d11_memory_get_shader_resource_view_size (GstD3D11Memory * mem);
GST_D3D11_API
ID3D11ShaderResourceView * gst_d3d11_memory_get_shader_resource_view (GstD3D11Memory * mem,
guint index);
GST_D3D11_API
guint gst_d3d11_memory_get_render_target_view_size (GstD3D11Memory * mem);
GST_D3D11_API
ID3D11RenderTargetView * gst_d3d11_memory_get_render_target_view (GstD3D11Memory * mem,
guint index);
GST_D3D11_API
ID3D11VideoDecoderOutputView * gst_d3d11_memory_get_decoder_output_view (GstD3D11Memory * mem,
ID3D11VideoDevice * video_device,
GUID * decoder_profile);
GST_D3D11_API
ID3D11VideoProcessorInputView * gst_d3d11_memory_get_processor_input_view (GstD3D11Memory * mem,
ID3D11VideoDevice * video_device,
ID3D11VideoProcessorEnumerator * enumerator);
GST_D3D11_API
ID3D11VideoProcessorOutputView * gst_d3d11_memory_get_processor_output_view (GstD3D11Memory * mem,
ID3D11VideoDevice * video_device,
ID3D11VideoProcessorEnumerator * enumerator);

View file

@ -0,0 +1,402 @@
/* GStreamer
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11_private.h"
#include <windows.h>
#include <versionhelpers.h>
GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
#ifndef GST_DISABLE_GST_DEBUG
#define GST_CAT_DEFAULT ensure_debug_category()
static GstDebugCategory *
ensure_debug_category (void)
{
static gsize cat_gonce = 0;
if (g_once_init_enter (&cat_gonce)) {
gsize cat_done;
cat_done = (gsize) _gst_debug_category_new ("d3d11utils", 0,
"d3d11 utility functions");
g_once_init_leave (&cat_gonce, cat_done);
}
return (GstDebugCategory *) cat_gonce;
}
#else
#define ensure_debug_category() /* NOOP */
#endif /* GST_DISABLE_GST_DEBUG */
static void
_init_context_debug (void)
{
static volatile gsize _init = 0;
if (g_once_init_enter (&_init)) {
GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT");
g_once_init_leave (&_init, 1);
}
}
/**
* gst_d3d11_handle_set_context:
* @element: a #GstElement
* @context: a #GstContext
* @device: (inout) (transfer full): location of a #GstD3D11Device
*
* Helper function for implementing #GstElementClass.set_context() in
* D3D11 capable elements.
*
* Retrieve's the #GstD3D11Device in @context and places the result in @device.
*
* Returns: whether the @device could be set successfully
*
* Since: 1.20
*/
gboolean
gst_d3d11_handle_set_context (GstElement * element, GstContext * context,
gint adapter, GstD3D11Device ** device)
{
const gchar *context_type;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (device != NULL, FALSE);
_init_context_debug ();
if (!context)
return FALSE;
context_type = gst_context_get_context_type (context);
if (g_strcmp0 (context_type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE) == 0) {
const GstStructure *str;
GstD3D11Device *other_device = NULL;
guint other_adapter = 0;
/* If we had device already, will not replace it */
if (*device)
return TRUE;
str = gst_context_get_structure (context);
if (gst_structure_get (str, "device", GST_TYPE_D3D11_DEVICE,
&other_device, "adapter", G_TYPE_UINT, &other_adapter, NULL)) {
if (adapter == -1 || (guint) adapter == other_adapter) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT,
element, "Found D3D11 device context");
*device = other_device;
return TRUE;
}
gst_object_unref (other_device);
}
}
return FALSE;
}
static void
context_set_d3d11_device (GstContext * context, GstD3D11Device * device)
{
GstStructure *s;
guint adapter = 0;
guint device_id = 0;
guint vendor_id = 0;
gboolean hardware = FALSE;
gchar *desc = NULL;
gint64 adapter_luid = 0;
g_return_if_fail (context != NULL);
g_object_get (G_OBJECT (device), "adapter", &adapter, "device-id", &device_id,
"vendor-id", &vendor_id, "hardware", &hardware, "description", &desc,
"adapter-luid", &adapter_luid, NULL);
GST_CAT_LOG (GST_CAT_CONTEXT,
"setting GstD3D11Device(%" GST_PTR_FORMAT
") with adapter %d on context(%" GST_PTR_FORMAT ")",
device, adapter, context);
s = gst_context_writable_structure (context);
gst_structure_set (s, "device", GST_TYPE_D3D11_DEVICE, device,
"adapter", G_TYPE_UINT, adapter,
"adapter-luid", G_TYPE_INT64, adapter_luid,
"device-id", G_TYPE_UINT, device_id,
"vendor-id", G_TYPE_UINT, vendor_id,
"hardware", G_TYPE_BOOLEAN, hardware,
"description", G_TYPE_STRING, GST_STR_NULL (desc), NULL);
g_free (desc);
}
/**
* gst_d3d11_handle_context_query:
* @element: a #GstElement
* @query: a #GstQuery of type %GST_QUERY_CONTEXT
* @device: (transfer none) (nullable): a #GstD3D11Device
*
* Returns: Whether the @query was successfully responded to from the passed
* @device.
*
* Since: 1.20
*/
gboolean
gst_d3d11_handle_context_query (GstElement * element, GstQuery * query,
GstD3D11Device * device)
{
const gchar *context_type;
GstContext *context, *old_context;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
_init_context_debug ();
GST_LOG_OBJECT (element, "handle context query %" GST_PTR_FORMAT, query);
if (!device)
return FALSE;
gst_query_parse_context_type (query, &context_type);
if (g_strcmp0 (context_type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE) != 0)
return FALSE;
gst_query_parse_context (query, &old_context);
if (old_context)
context = gst_context_copy (old_context);
else
context = gst_context_new (GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
context_set_d3d11_device (context, device);
gst_query_set_context (query, context);
gst_context_unref (context);
GST_DEBUG_OBJECT (element, "successfully set %" GST_PTR_FORMAT
" on %" GST_PTR_FORMAT, device, query);
return TRUE;
}
static gboolean
pad_query (const GValue * item, GValue * value, gpointer user_data)
{
GstPad *pad = g_value_get_object (item);
GstQuery *query = user_data;
gboolean res;
res = gst_pad_peer_query (pad, query);
if (res) {
g_value_set_boolean (value, TRUE);
return FALSE;
}
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, pad, "pad peer query failed");
return TRUE;
}
static gboolean
run_query (GstElement * element, GstQuery * query, GstPadDirection direction)
{
GstIterator *it;
GstIteratorFoldFunction func = pad_query;
GValue res = { 0 };
g_value_init (&res, G_TYPE_BOOLEAN);
g_value_set_boolean (&res, FALSE);
/* Ask neighbor */
if (direction == GST_PAD_SRC)
it = gst_element_iterate_src_pads (element);
else
it = gst_element_iterate_sink_pads (element);
while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
gst_iterator_resync (it);
gst_iterator_free (it);
return g_value_get_boolean (&res);
}
static void
run_d3d11_context_query (GstElement * element, GstD3D11Device ** device)
{
GstQuery *query;
GstContext *ctxt = NULL;
/* 1) Query downstream with GST_QUERY_CONTEXT for the context and
* check if downstream already has a context of the specific type
*/
query = gst_query_new_context (GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE);
if (run_query (element, query, GST_PAD_SRC)) {
gst_query_parse_context (query, &ctxt);
if (ctxt) {
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"found context (%" GST_PTR_FORMAT ") in downstream query", ctxt);
gst_element_set_context (element, ctxt);
}
}
/* 2) although we found d3d11 device context above, the element does not want
* to use the context. Then try to find from the other direction */
if (*device == NULL && run_query (element, query, GST_PAD_SINK)) {
gst_query_parse_context (query, &ctxt);
if (ctxt) {
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"found context (%" GST_PTR_FORMAT ") in upstream query", ctxt);
gst_element_set_context (element, ctxt);
}
}
if (*device == NULL) {
/* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
* the required context type and afterwards check if a
* usable context was set now as in 1). The message could
* be handled by the parent bins of the element and the
* application.
*/
GstMessage *msg;
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"posting need context message");
msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE);
gst_element_post_message (element, msg);
}
/*
* Whomever responds to the need-context message performs a
* GstElement::set_context() with the required context in which the element
* is required to update the display_ptr or call gst_gl_handle_set_context().
*/
gst_query_unref (query);
}
/**
* gst_d3d11_ensure_element_data:
* @element: the #GstElement running the query
* @adapter: preferred adapter index, pass adapter >=0 when
* the adapter explicitly required. Otherwise, set -1.
* @device: (inout): the resulting #GstD3D11Device
*
* Perform the steps necessary for retrieving a #GstD3D11Device
* from the surrounding elements or from the application using the #GstContext mechanism.
*
* If the contents of @device is not %NULL, then no #GstContext query is
* necessary for #GstD3D11Device retrieval is performed.
*
* Returns: whether a #GstD3D11Device exists in @device
*
* Since: 1.20
*/
gboolean
gst_d3d11_ensure_element_data (GstElement * element, gint adapter,
GstD3D11Device ** device)
{
guint target_adapter = 0;
g_return_val_if_fail (element != NULL, FALSE);
g_return_val_if_fail (device != NULL, FALSE);
_init_context_debug ();
if (*device) {
GST_LOG_OBJECT (element, "already have a device %" GST_PTR_FORMAT, *device);
return TRUE;
}
run_d3d11_context_query (element, device);
if (*device)
return TRUE;
if (adapter > 0)
target_adapter = adapter;
/* Needs D3D11_CREATE_DEVICE_BGRA_SUPPORT flag for Direct2D interop */
*device = gst_d3d11_device_new (target_adapter,
D3D11_CREATE_DEVICE_BGRA_SUPPORT);
if (*device == NULL) {
GST_ERROR_OBJECT (element,
"Couldn't create new device with adapter index %d", target_adapter);
return FALSE;
} else {
GstContext *context;
GstMessage *msg;
/* Propagate new D3D11 device context */
context = gst_context_new (GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
context_set_d3d11_device (context, *device);
gst_element_set_context (element, context);
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"posting have context (%p) message with D3D11 device context (%p)",
context, *device);
msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context);
gst_element_post_message (GST_ELEMENT_CAST (element), msg);
}
return TRUE;
}
gboolean
_gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
const gchar * file, const gchar * function, gint line)
{
#ifndef GST_DISABLE_GST_DEBUG
gboolean ret = TRUE;
if (FAILED (hr)) {
gchar *error_text = NULL;
error_text = g_win32_error_message ((guint) hr);
/* g_win32_error_message() doesn't cover all HERESULT return code,
* so it could be empty string, or null if there was an error
* in g_utf16_to_utf8() */
gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line,
NULL, "D3D11 call failed: 0x%x, %s", (guint) hr,
GST_STR_NULL (error_text));
g_free (error_text);
ret = FALSE;
}
#if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
if (device) {
gst_d3d11_device_d3d11_debug (device, file, function, line);
gst_d3d11_device_dxgi_debug (device, file, function, line);
}
#endif
return ret;
#else
return SUCCEEDED (hr);
#endif
}

View file

@ -0,0 +1,65 @@
/* GStreamer
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_D3D11_UTILS_H__
#define __GST_D3D11_UTILS_H__
#include <gst/gst.h>
#include <gst/d3d11/gstd3d11_fwd.h>
G_BEGIN_DECLS
GST_D3D11_API
gboolean gst_d3d11_handle_set_context (GstElement * element,
GstContext * context,
gint adapter,
GstD3D11Device ** device);
GST_D3D11_API
gboolean gst_d3d11_handle_context_query (GstElement * element,
GstQuery * query,
GstD3D11Device * device);
GST_D3D11_API
gboolean gst_d3d11_ensure_element_data (GstElement * element,
gint adapter,
GstD3D11Device ** device);
GST_D3D11_API
gboolean _gst_d3d11_result (HRESULT hr,
GstD3D11Device * device,
GstDebugCategory * cat,
const gchar * file,
const gchar * function,
gint line);
/**
* gst_d3d11_result:
* @result: HRESULT D3D11 API return code
* @device: (nullable): Associated #GstD3D11Device
*
* Returns: %TRUE if D3D11 API call result is SUCCESS
*
* Since: 1.20
*/
#define gst_d3d11_result(result,device) \
_gst_d3d11_result (result, device, GST_CAT_DEFAULT, __FILE__, GST_FUNCTION, __LINE__)
G_END_DECLS
#endif /* __GST_D3D11_UTILS_H__ */

View file

@ -0,0 +1,186 @@
d3d11_sources = [
'gstd3d11bufferpool.c',
'gstd3d11device.c',
'gstd3d11format.c',
'gstd3d11memory.c',
'gstd3d11utils.c',
]
dxgi_headers = [
['dxgi1_6.h', 6],
['dxgi1_5.h', 5],
['dxgi1_4.h', 4],
['dxgi1_3.h', 3],
['dxgi1_2.h', 2],
['dxgi.h', 1]
]
d3d11_headers = [
['d3d11_4.h', 4],
['d3d11_3.h', 3],
['d3d11_2.h', 2],
['d3d11_1.h', 1],
['d3d11.h', 0]
]
gstd3d11_dep = dependency('', required : false)
d3d11_option = get_option('d3d11')
if host_system != 'windows' or d3d11_option.disabled()
subdir_done()
endif
have_d3d11 = false
extra_c_args = [
'-DCOBJMACROS',
'-DGST_USE_UNSTABLE_API',
'-DBUILDING_GST_D3D11'
]
have_dxgi_header = false
have_d3d11_header = false
have_d3d11sdk_h = false
have_dxgidebug_h = false
winapi_desktop = false
winapi_app = false
d3d11_conf = configuration_data()
d3d11_conf_options = [
'GST_D3D11_DXGI_HEADER_VERSION',
'GST_D3D11_HEADER_VERSION',
'GST_D3D11_WINAPI_ONLY_APP',
]
foreach option : d3d11_conf_options
d3d11_conf.set10(option, false)
endforeach
d3d11_lib = cc.find_library('d3d11', required : d3d11_option)
dxgi_lib = cc.find_library('dxgi', required : d3d11_option)
d3dcompiler_lib = cc.find_library('d3dcompiler', required: d3d11_option)
runtimeobject_lib = cc.find_library('runtimeobject', required : false)
foreach dxgi_h: dxgi_headers
if not have_dxgi_header and cc.has_header(dxgi_h[0])
d3d11_conf.set('GST_D3D11_DXGI_HEADER_VERSION', dxgi_h[1])
have_dxgi_header = true
endif
endforeach
foreach d3d11_h: d3d11_headers
if not have_d3d11_header and cc.has_header(d3d11_h[0])
d3d11_conf.set('GST_D3D11_HEADER_VERSION', d3d11_h[1])
have_d3d11_header = true
endif
endforeach
have_d3d11 = d3d11_lib.found() and dxgi_lib.found() and have_d3d11_header and have_dxgi_header
if not have_d3d11
if d3d11_option.enabled()
error('The d3d11 was enabled explicitly, but required dependencies were not found.')
endif
subdir_done()
endif
winapi_desktop = cxx.compiles('''#include <winapifamily.h>
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#error "not win32"
#endif''',
dependencies: [d3d11_lib, dxgi_lib],
name: 'checking if building for Win32')
if runtimeobject_lib.found() and d3dcompiler_lib.found()
winapi_app = cxx.compiles('''#include <winapifamily.h>
#include <windows.applicationmodel.core.h>
#include <wrl.h>
#include <wrl/wrappers/corewrappers.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#error "not winrt"
#endif''',
dependencies: [d3d11_lib, dxgi_lib, runtimeobject_lib],
name: 'checking if building for WinRT')
endif
if not winapi_desktop and not winapi_app
error('Neither Desktop partition nor App partition')
endif
d3d11_winapi_only_app = winapi_app and not winapi_desktop
d3d11_conf.set10('GST_D3D11_WINAPI_ONLY_APP', d3d11_winapi_only_app)
# for enabling debug layer
# NOTE: Disable d3d11/dxgi debug layer in case of [UWP build + release CRT]
# WACK (Windows App Certification Kit) doesn't seem to be happy with
# the DXGIGetDebugInterface1 symbol.
# FIXME: Probably DXGIGetDebugInterface1 might be used on UWP app for development
# purpose. So, I suspect one possible reason why WACK is complaining about
# DXGIGetDebugInterface1 is that debugging APIs couldn't be used for
# Windows store app, but couldn't find any reference about that.
#
# [IDXGIDebug1]
# https://docs.microsoft.com/en-us/windows/win32/api/dxgidebug/nn-dxgidebug-idxgidebug1
# is saying that the IDXGIDebug1 interface is available for both desktop app and
# UWP. And then the *DXGIGetDebugInterface1* method need to be called to obtain
# the IDXGIDebug1 interface.
#
# [DXGIGetDebugInterface1]
# https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-dxgigetdebuginterface1
# is mentioning that DXGIGetDebugInterface1 is desktop app only.
#
# PLEASE LET US KNOW A CORRECT WAY TO OBTAIN IDXGIDebug1 ON UWP, MICROSOFT
if get_option('debug') and not (d3d11_winapi_only_app and get_option('b_vscrt') == 'md')
d3d11_debug_libs = [
['d3d11sdklayers.h', 'ID3D11Debug', 'ID3D11InfoQueue', 'have_d3d11sdk_h'],
['dxgidebug.h', 'IDXGIDebug', 'IDXGIInfoQueue', 'have_dxgidebug_h'],
]
foreach f : d3d11_debug_libs
header = f.get(0)
debug_obj = f.get(1)
info_obj = f.get(2)
compile_code = '''
#include <d3d11.h>
#include <dxgi.h>
#include <@0@>
int main(int arc, char ** argv) {
@1@ *debug = NULL;
@2@ *info_queue = NULL;
return 0;
}'''.format(header, debug_obj, info_obj)
if cc.compiles(compile_code, dependencies: [d3d11_lib, dxgi_lib], name: debug_obj)
set_variable(f.get(3), true)
endif
endforeach
else
message('Disable D3D11Debug and DXGIDebug layers')
endif
# don't need to be defined in gstd3d11config.h since it's gstd3d11device internal
if have_d3d11sdk_h
extra_c_args += ['-DHAVE_D3D11SDKLAYERS_H']
endif
if have_dxgidebug_h
extra_c_args += ['-DHAVE_DXGIDEBUG_H']
endif
configure_file(
output: 'gstd3d11config.h',
configuration: d3d11_conf,
)
gstd3d11 = library('gstd3d11-' + api_version,
d3d11_sources,
c_args : gst_plugins_bad_args + extra_c_args,
include_directories : [configinc, libsinc],
version : libversion,
soversion : soversion,
install : true,
dependencies : [gstbase_dep, gstvideo_dep, gmodule_dep, d3d11_lib, dxgi_lib]
)
# Still non-public api, should not install headers
gstd3d11_dep = declare_dependency(link_with : gstd3d11,
include_directories : [libsinc],
dependencies : [gstbase_dep, gstvideo_dep, gmodule_dep, d3d11_lib, dxgi_lib])

View file

@ -5,6 +5,7 @@ subdir('audio')
subdir('basecamerabinsrc')
subdir('codecparsers')
subdir('codecs')
subdir('d3d11')
subdir('insertbin')
subdir('interfaces')
subdir('isoff')

View file

@ -22,10 +22,6 @@
#endif
#include "gstd3d11basefilter.h"
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11memory.h"
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_base_filter_debug);
#define GST_CAT_DEFAULT gst_d3d11_base_filter_debug

View file

@ -23,8 +23,8 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/base/gstbasetransform.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
#include "gstd3d11pluginutils.h"
G_BEGIN_DECLS

View file

@ -49,12 +49,7 @@
#include "gstd3d11colorconvert.h"
#include "gstd3d11colorconverter.h"
#include "gstd3d11utils.h"
#include "gstd3d11memory.h"
#include "gstd3d11device.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11videoprocessor.h"
#include "gstd3d11format.h"
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_convert_debug);
#define GST_CAT_DEFAULT gst_d3d11_convert_debug

View file

@ -23,10 +23,7 @@
#endif
#include "gstd3d11colorconverter.h"
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11shader.h"
#include "gstd3d11format.h"
#include <string.h>

View file

@ -22,7 +22,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -26,15 +26,10 @@
#include "config.h"
#endif
#include "gstd3d11_fwd.h"
#include "gstd3d11compositor.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11utils.h"
#include "gstd3d11format.h"
#include "gstd3d11colorconverter.h"
#include "gstd3d11shader.h"
#include "gstd3d11pluginutils.h"
#include <string.h>
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_compositor_debug);

View file

@ -24,6 +24,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/video/gstvideoaggregator.h>
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -24,14 +24,8 @@
#endif
#include <gst/controller/gstproxycontrolbinding.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11compositorbin.h"
#include "gstd3d11compositor.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11utils.h"
#include "gstd3d11format.h"
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_compositor_debug);
#define GST_CAT_DEFAULT gst_d3d11_compositor_debug

View file

@ -24,6 +24,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/video/gstvideoaggregator.h>
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -52,10 +52,8 @@
#endif
#include "gstd3d11decoder.h"
#include "gstd3d11memory.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11device.h"
#include "gstd3d11colorconverter.h"
#include "gstd3d11pluginutils.h"
#include <string.h>
GST_DEBUG_CATEGORY (d3d11_decoder_debug);

View file

@ -22,9 +22,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11device.h"
#include "gstd3d11utils.h"
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -47,9 +47,6 @@
#endif
#include "gstd3d11desktopdup.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11shader.h"
#include <string.h>

View file

@ -23,7 +23,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -37,12 +37,6 @@
#include "config.h"
#endif
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11format.h"
#include "gstd3d11device.h"
#include "gstd3d11desktopdupsrc.h"
#include "gstd3d11desktopdup.h"

View file

@ -24,7 +24,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/base/gstpushsrc.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -22,10 +22,6 @@
#endif
#include "gstd3d11download.h"
#include "gstd3d11memory.h"
#include "gstd3d11device.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11utils.h"
GST_DEBUG_CATEGORY_STATIC (gst_d3d11_download_debug);
#define GST_CAT_DEFAULT gst_d3d11_download_debug

View file

@ -52,8 +52,6 @@
#endif
#include "gstd3d11h264dec.h"
#include "gstd3d11memory.h"
#include "gstd3d11bufferpool.h"
#include <gst/codecs/gsth264decoder.h>
#include <string.h>

View file

@ -22,8 +22,6 @@
#endif
#include "gstd3d11h265dec.h"
#include "gstd3d11memory.h"
#include "gstd3d11bufferpool.h"
#include <gst/codecs/gsth265decoder.h>
#include <string.h>

View file

@ -22,10 +22,7 @@
#endif
#include "gstd3d11overlaycompositor.h"
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11shader.h"
#include "gstd3d11format.h"
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_overlay_compositor_debug);
#define GST_CAT_DEFAULT gst_d3d11_overlay_compositor_debug

View file

@ -22,7 +22,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -21,165 +22,75 @@
#include "config.h"
#endif
#include "gstd3d11format.h"
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11pluginutils.h"
#include <string.h>
#include <windows.h>
#include <versionhelpers.h>
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_format_debug);
#define GST_CAT_DEFAULT gst_d3d11_format_debug
guint
gst_d3d11_dxgi_format_n_planes (DXGI_FORMAT format)
{
switch (format) {
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_YUY2:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y410:
case DXGI_FORMAT_R16G16B16A16_UNORM:
return 1;
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
return 2;
default:
break;
}
return 0;
}
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_plugin_utils_debug);
#define GST_CAT_DEFAULT gst_d3d11_plugin_utils_debug
gboolean
gst_d3d11_dxgi_format_get_size (DXGI_FORMAT format, guint width, guint height,
guint pitch, gsize offset[GST_VIDEO_MAX_PLANES],
gint stride[GST_VIDEO_MAX_PLANES], gsize * size)
gst_d3d11_is_windows_8_or_greater (void)
{
g_return_val_if_fail (format != DXGI_FORMAT_UNKNOWN, FALSE);
static gsize version_once = 0;
static gboolean ret = FALSE;
switch (format) {
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_YUY2:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y410:
case DXGI_FORMAT_R16G16B16A16_UNORM:
offset[0] = 0;
stride[0] = pitch;
*size = pitch * height;
if (g_once_init_enter (&version_once)) {
#if (!GST_D3D11_WINAPI_ONLY_APP)
if (IsWindows8OrGreater ())
ret = TRUE;
#else
ret = TRUE;
#endif
g_once_init_leave (&version_once, 1);
}
return ret;
}
GstD3D11DeviceVendor
gst_d3d11_get_device_vendor (GstD3D11Device * device)
{
guint device_id = 0;
guint vendor_id = 0;
gchar *desc = NULL;
GstD3D11DeviceVendor vendor = GST_D3D11_DEVICE_VENDOR_UNKNOWN;
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
g_object_get (device, "device-id", &device_id, "vendor-id", &vendor_id,
"description", &desc, NULL);
switch (vendor_id) {
case 0:
if (device_id == 0 && desc && g_strrstr (desc, "SraKmd"))
vendor = GST_D3D11_DEVICE_VENDOR_XBOX;
break;
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
offset[0] = 0;
stride[0] = pitch;
offset[1] = offset[0] + stride[0] * height;
stride[1] = pitch;
*size = offset[1] + stride[1] * GST_ROUND_UP_2 (height / 2);
case 0x1002:
case 0x1022:
vendor = GST_D3D11_DEVICE_VENDOR_AMD;
break;
case 0x8086:
vendor = GST_D3D11_DEVICE_VENDOR_INTEL;
break;
case 0x10de:
vendor = GST_D3D11_DEVICE_VENDOR_NVIDIA;
break;
case 0x4d4f4351:
vendor = GST_D3D11_DEVICE_VENDOR_QUALCOMM;
break;
default:
return FALSE;
break;
}
GST_LOG ("Calculated buffer size: %" G_GSIZE_FORMAT
" (dxgi format:%d, %dx%d, Pitch %d)",
*size, format, width, height, pitch);
g_free (desc);
return TRUE;
return vendor;
}
/**
* gst_d3d11_device_get_supported_caps:
* @device: a #GstD3DDevice
* @flags: D3D11_FORMAT_SUPPORT flags
*
* Check supported format with given flags
*
* Returns: a #GstCaps representing supported format
*/
GstCaps *
gst_d3d11_device_get_supported_caps (GstD3D11Device * device,
D3D11_FORMAT_SUPPORT flags)
{
ID3D11Device *d3d11_device;
HRESULT hr;
gint i;
GValue v_list = G_VALUE_INIT;
GstCaps *supported_caps;
static const GstVideoFormat format_list[] = {
GST_VIDEO_FORMAT_BGRA,
GST_VIDEO_FORMAT_RGBA,
GST_VIDEO_FORMAT_RGB10A2_LE,
GST_VIDEO_FORMAT_VUYA,
GST_VIDEO_FORMAT_NV12,
GST_VIDEO_FORMAT_P010_10LE,
GST_VIDEO_FORMAT_P016_LE,
GST_VIDEO_FORMAT_I420,
GST_VIDEO_FORMAT_I420_10LE,
};
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
d3d11_device = gst_d3d11_device_get_device_handle (device);
g_value_init (&v_list, GST_TYPE_LIST);
for (i = 0; i < G_N_ELEMENTS (format_list); i++) {
UINT format_support = 0;
GstVideoFormat format;
const GstD3D11Format *d3d11_format;
d3d11_format = gst_d3d11_device_format_from_gst (device, format_list[i]);
if (!d3d11_format || d3d11_format->dxgi_format == DXGI_FORMAT_UNKNOWN)
continue;
format = d3d11_format->format;
hr = ID3D11Device_CheckFormatSupport (d3d11_device,
d3d11_format->dxgi_format, &format_support);
if (SUCCEEDED (hr) && ((format_support & flags) == flags)) {
GValue v_str = G_VALUE_INIT;
g_value_init (&v_str, G_TYPE_STRING);
GST_LOG_OBJECT (device, "d3d11 device can support %s with flags 0x%x",
gst_video_format_to_string (format), flags);
g_value_set_string (&v_str, gst_video_format_to_string (format));
gst_value_list_append_and_take_value (&v_list, &v_str);
}
}
supported_caps = gst_caps_new_simple ("video/x-raw",
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
gst_caps_set_value (supported_caps, "format", &v_list);
g_value_unset (&v_list);
gst_caps_set_features_simple (supported_caps,
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY));
return supported_caps;
}
#if (DXGI_HEADER_VERSION >= 5)
#if (GST_D3D11_DXGI_HEADER_VERSION >= 5)
gboolean
gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * dxgi_hdr10)
@ -211,7 +122,7 @@ gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
}
#endif
#if (DXGI_HEADER_VERSION >= 4)
#if (GST_D3D11_DXGI_HEADER_VERSION >= 4)
typedef enum
{
GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0,
@ -608,5 +519,493 @@ gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
return colorspace;
}
#endif
GstBuffer *
gst_d3d11_allocate_staging_buffer (GstD3D11Allocator * allocator,
const GstVideoInfo * info, const GstD3D11Format * format,
const D3D11_TEXTURE2D_DESC desc[GST_VIDEO_MAX_PLANES],
gboolean add_videometa)
{
GstBuffer *buffer;
gint i;
gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
GstMemory *mem;
g_return_val_if_fail (GST_IS_D3D11_ALLOCATOR (allocator), NULL);
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (format != NULL, NULL);
g_return_val_if_fail (desc != NULL, NULL);
buffer = gst_buffer_new ();
if (format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
gsize size[GST_VIDEO_MAX_PLANES] = { 0, };
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
mem = gst_d3d11_allocator_alloc_staging (allocator, &desc[i], 0,
&stride[i]);
if (!mem) {
GST_ERROR_OBJECT (allocator, "Couldn't allocate memory for plane %d",
i);
goto error;
}
size[i] = gst_memory_get_sizes (mem, NULL, NULL);
if (i > 0)
offset[i] = offset[i - 1] + size[i - 1];
gst_buffer_append_memory (buffer, mem);
}
} else {
/* must be YUV semi-planar or single plane */
g_assert (GST_VIDEO_INFO_N_PLANES (info) <= 2);
mem = gst_d3d11_allocator_alloc_staging (allocator, &desc[0], 0,
&stride[0]);
if (!mem) {
GST_ERROR_OBJECT (allocator, "Couldn't allocate memory");
goto error;
}
gst_memory_get_sizes (mem, NULL, NULL);
gst_buffer_append_memory (buffer, mem);
if (GST_VIDEO_INFO_N_PLANES (info) == 2) {
stride[1] = stride[0];
offset[1] = stride[0] * desc[0].Height;
}
}
if (add_videometa) {
gst_buffer_add_video_meta_full (buffer, GST_VIDEO_FRAME_FLAG_NONE,
GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
offset, stride);
}
return buffer;
error:
gst_buffer_unref (buffer);
return NULL;
}
GstBuffer *
gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
const GstVideoInfo * info, gboolean add_videometa)
{
GstD3D11Memory *dmem;
GstD3D11Device *device;
GstD3D11AllocationParams *params = NULL;
GstD3D11Allocator *alloc = NULL;
GstBuffer *staging_buffer = NULL;
D3D11_TEXTURE2D_DESC *desc;
gint i;
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
if (!gst_is_d3d11_memory (mem)) {
GST_DEBUG ("Not a d3d11 memory");
return NULL;
}
}
dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
device = dmem->device;
params = gst_d3d11_allocation_params_new (device, (GstVideoInfo *) info,
0, 0);
if (!params) {
GST_WARNING ("Couldn't create alloc params");
goto done;
}
desc = &params->desc[0];
/* resolution of semi-planar formats must be multiple of 2 */
if (desc[0].Format == DXGI_FORMAT_NV12 || desc[0].Format == DXGI_FORMAT_P010
|| desc[0].Format == DXGI_FORMAT_P016) {
if (desc[0].Width % 2 || desc[0].Height % 2) {
gint width, height;
GstVideoAlignment align;
width = GST_ROUND_UP_2 (desc[0].Width);
height = GST_ROUND_UP_2 (desc[0].Height);
gst_video_alignment_reset (&align);
align.padding_right = width - desc[0].Width;
align.padding_bottom = height - desc[0].Height;
gst_d3d11_allocation_params_alignment (params, &align);
}
}
alloc = gst_d3d11_allocator_new (device);
if (!alloc) {
GST_WARNING ("Couldn't create allocator");
goto done;
}
staging_buffer = gst_d3d11_allocate_staging_buffer (alloc,
info, params->d3d11_format, params->desc, add_videometa);
if (!staging_buffer)
GST_WARNING ("Couldn't allocate staging buffer");
done:
if (params)
gst_d3d11_allocation_params_free (params);
if (alloc)
gst_object_unref (alloc);
return staging_buffer;
}
static gboolean
gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src,
const GstVideoInfo * info)
{
GstVideoFrame in_frame, out_frame;
gboolean ret;
if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src,
GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))
goto invalid_buffer;
if (!gst_video_frame_map (&out_frame, (GstVideoInfo *) info, dst,
GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) {
gst_video_frame_unmap (&in_frame);
goto invalid_buffer;
}
ret = gst_video_frame_copy (&out_frame, &in_frame);
gst_video_frame_unmap (&in_frame);
gst_video_frame_unmap (&out_frame);
return ret;
/* ERRORS */
invalid_buffer:
{
GST_ERROR ("Invalid video buffer");
return FALSE;
}
}
gboolean
gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src,
const GstVideoInfo * info)
{
guint i;
g_return_val_if_fail (GST_IS_BUFFER (dst), FALSE);
g_return_val_if_fail (GST_IS_BUFFER (src), FALSE);
g_return_val_if_fail (info != NULL, FALSE);
if (gst_buffer_n_memory (dst) != gst_buffer_n_memory (src)) {
GST_LOG ("different memory layout, perform fallback copy");
return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
}
if (!gst_is_d3d11_buffer (dst) || !gst_is_d3d11_buffer (src)) {
GST_LOG ("non-d3d11 memory, perform fallback copy");
return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
}
for (i = 0; i < gst_buffer_n_memory (dst); i++) {
GstMemory *dst_mem, *src_mem;
GstD3D11Memory *dst_dmem, *src_dmem;
GstMapInfo dst_info;
GstMapInfo src_info;
ID3D11Resource *dst_texture, *src_texture;
ID3D11DeviceContext *device_context;
GstD3D11Device *device;
D3D11_BOX src_box = { 0, };
D3D11_TEXTURE2D_DESC dst_desc, src_desc;
guint dst_subidx, src_subidx;
dst_mem = gst_buffer_peek_memory (dst, i);
src_mem = gst_buffer_peek_memory (src, i);
dst_dmem = (GstD3D11Memory *) dst_mem;
src_dmem = (GstD3D11Memory *) src_mem;
device = dst_dmem->device;
if (device != src_dmem->device) {
GST_LOG ("different device, perform fallback copy");
return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
}
gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc);
gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc);
if (dst_desc.Format != src_desc.Format) {
GST_WARNING ("different dxgi format");
return FALSE;
}
device_context = gst_d3d11_device_get_device_context_handle (device);
if (!gst_memory_map (dst_mem, &dst_info, GST_MAP_WRITE | GST_MAP_D3D11)) {
GST_ERROR ("Cannot map dst d3d11 memory");
return FALSE;
}
if (!gst_memory_map (src_mem, &src_info, GST_MAP_READ | GST_MAP_D3D11)) {
GST_ERROR ("Cannot map src d3d11 memory");
gst_memory_unmap (dst_mem, &dst_info);
return FALSE;
}
dst_texture = (ID3D11Resource *) dst_info.data;
src_texture = (ID3D11Resource *) src_info.data;
/* src/dst texture size might be different if padding was used.
* select smaller size */
src_box.left = 0;
src_box.top = 0;
src_box.front = 0;
src_box.back = 1;
src_box.right = MIN (src_desc.Width, dst_desc.Width);
src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem);
src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem);
gst_d3d11_device_lock (device);
ID3D11DeviceContext_CopySubresourceRegion (device_context,
dst_texture, dst_subidx, 0, 0, 0, src_texture, src_subidx, &src_box);
gst_d3d11_device_unlock (device);
gst_memory_unmap (src_mem, &src_info);
gst_memory_unmap (dst_mem, &dst_info);
}
return TRUE;
}
gboolean
gst_is_d3d11_buffer (GstBuffer * buffer)
{
guint i;
guint size;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
size = gst_buffer_n_memory (buffer);
if (size == 0)
return FALSE;
for (i = 0; i < size; i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
if (!gst_is_d3d11_memory (mem))
return FALSE;
}
return TRUE;
}
gboolean
gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device)
{
guint i;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (device != NULL, FALSE);
if (!gst_is_d3d11_buffer (buffer)) {
GST_LOG ("Not a d3d11 buffer");
return FALSE;
}
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
ID3D11Device *handle;
handle = gst_d3d11_device_get_device_handle (mem->device);
if (handle != device) {
GST_LOG ("D3D11 device is incompatible");
return FALSE;
}
}
return TRUE;
}
gboolean
gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device,
GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
{
GstMapFlags map_flags;
gint num_mapped = 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (info != NULL, FALSE);
if (!gst_d3d11_buffer_can_access_device (buffer, device))
return FALSE;
map_flags = flags | GST_MAP_D3D11;
for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
if (!gst_memory_map (mem, &info[num_mapped], map_flags)) {
GST_ERROR ("Couldn't map memory");
goto error;
}
}
return TRUE;
error:
{
gint i;
for (i = 0; i < num_mapped; i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
gst_memory_unmap (mem, &info[i]);
}
return FALSE;
}
}
gboolean
gst_d3d11_buffer_unmap (GstBuffer * buffer,
GstMapInfo info[GST_VIDEO_MAX_PLANES])
{
gint i;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (info != NULL, FALSE);
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
gst_memory_unmap (mem, &info[i]);
}
return TRUE;
}
guint
gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer,
ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])
{
gint i;
guint num_views = 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
g_return_val_if_fail (view != NULL, 0);
if (!gst_is_d3d11_buffer (buffer)) {
GST_ERROR ("Buffer contains non-d3d11 memory");
return 0;
}
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
guint view_size;
gint j;
view_size = gst_d3d11_memory_get_shader_resource_view_size (mem);
if (!view_size) {
GST_LOG ("SRV is unavailable for memory index %d", i);
return 0;
}
for (j = 0; j < view_size; j++) {
if (num_views >= GST_VIDEO_MAX_PLANES) {
GST_ERROR ("Too many SRVs");
return 0;
}
view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j);
}
}
return num_views;
}
guint
gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer,
ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])
{
gint i;
guint num_views = 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
g_return_val_if_fail (view != NULL, 0);
if (!gst_is_d3d11_buffer (buffer)) {
GST_ERROR ("Buffer contains non-d3d11 memory");
return 0;
}
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
guint view_size;
gint j;
view_size = gst_d3d11_memory_get_render_target_view_size (mem);
if (!view_size) {
GST_LOG ("RTV is unavailable for memory index %d", i);
return 0;
}
for (j = 0; j < view_size; j++) {
if (num_views >= GST_VIDEO_MAX_PLANES) {
GST_ERROR ("Too many RTVs");
return 0;
}
view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j);
}
}
return num_views;
}
GstBufferPool *
gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
GstCaps * caps, GstD3D11AllocationParams * alloc_params,
guint min_buffers, guint max_buffers)
{
GstBufferPool *pool;
GstStructure *config;
GstVideoInfo info;
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
g_return_val_if_fail (alloc_params != NULL, NULL);
if (!gst_video_info_from_caps (&info, caps)) {
GST_ERROR_OBJECT (device, "invalid caps");
return NULL;
}
pool = gst_d3d11_buffer_pool_new (device);
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config,
caps, GST_VIDEO_INFO_SIZE (&info), min_buffers, max_buffers);
gst_buffer_pool_config_set_d3d11_allocation_params (config, alloc_params);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
if (!gst_buffer_pool_set_config (pool, config)) {
GST_ERROR_OBJECT (pool, "Couldn't set config");
gst_object_unref (pool);
return NULL;
}
return pool;
}

View file

@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -17,17 +18,17 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_D3D11_UTILS_H__
#define __GST_D3D11_UTILS_H__
#ifndef __GST_D3D11_PLUGIN_UTILS_H__
#define __GST_D3D11_PLUGIN_UTILS_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11memory.h"
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS
typedef struct _GstDxgiColorSpace GstDxgiColorSpace;
typedef enum
{
GST_D3D11_DEVICE_VENDOR_UNKNOWN = 0,
@ -38,23 +39,33 @@ typedef enum
GST_D3D11_DEVICE_VENDOR_XBOX,
} GstD3D11DeviceVendor;
gboolean gst_d3d11_handle_set_context (GstElement * element,
GstContext * context,
gint adapter,
GstD3D11Device ** device);
gboolean gst_d3d11_handle_context_query (GstElement * element,
GstQuery * query,
GstD3D11Device * device);
gboolean gst_d3d11_ensure_element_data (GstElement * element,
gint adapter,
GstD3D11Device ** device);
struct _GstDxgiColorSpace
{
guint dxgi_color_space_type;
GstVideoColorRange range;
GstVideoColorMatrix matrix;
GstVideoTransferFunction transfer;
GstVideoColorPrimaries primaries;
};
gboolean gst_d3d11_is_windows_8_or_greater (void);
GstD3D11DeviceVendor gst_d3d11_get_device_vendor (GstD3D11Device * device);
#if (GST_D3D11_DXGI_HEADER_VERSION >= 5)
gboolean gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
GstVideoContentLightLevel * cll,
DXGI_HDR_METADATA_HDR10 * dxgi_hdr10);
#endif
#if (GST_D3D11_DXGI_HEADER_VERSION >= 4)
const GstDxgiColorSpace * gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info);
const GstDxgiColorSpace * gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
IDXGISwapChain3 * swapchain,
gboolean use_hdr10);
#endif
GstBuffer * gst_d3d11_allocate_staging_buffer (GstD3D11Allocator * allocator,
const GstVideoInfo * info,
const GstD3D11Format * format,
@ -94,23 +105,6 @@ GstBufferPool * gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device
guint min_buffers,
guint max_buffers);
gboolean _gst_d3d11_result (HRESULT hr,
GstD3D11Device * device,
GstDebugCategory * cat,
const gchar * file,
const gchar * function,
gint line);
/**
* gst_d3d11_result:
* @result: D3D11 API return code #HRESULT
* @device: (nullable): Associated #GstD3D11Device
*
* Returns: %TRUE if D3D11 API call result is SUCCESS
*/
#define gst_d3d11_result(result,device) \
_gst_d3d11_result (result, device, GST_CAT_DEFAULT, __FILE__, GST_FUNCTION, __LINE__)
G_END_DECLS
#endif /* __GST_D3D11_UTILS_H__ */
#endif /* __GST_D3D11_PLUGIN_UTILS_H__ */

View file

@ -22,8 +22,6 @@
#endif
#include "gstd3d11shader.h"
#include "gstd3d11device.h"
#include "gstd3d11utils.h"
#include <gmodule.h>
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_shader_debug);

View file

@ -21,8 +21,8 @@
#define __GST_D3D11_SHADER_H__
#include <gst/gst.h>
#include "gstd3d11_fwd.h"
#include <gst/video/video.h>
#include <gst/d3d11/gstd3d11.h>
#include <d3dcompiler.h>

View file

@ -22,10 +22,6 @@
#endif
#include "gstd3d11upload.h"
#include "gstd3d11memory.h"
#include "gstd3d11device.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11utils.h"
#include <string.h>

View file

@ -1,926 +0,0 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11bufferpool.h"
#include <windows.h>
#include <versionhelpers.h>
GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_utils_debug);
#define GST_CAT_DEFAULT gst_d3d11_utils_debug
static void
_init_context_debug (void)
{
static volatile gsize _init = 0;
if (g_once_init_enter (&_init)) {
GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT");
g_once_init_leave (&_init, 1);
}
}
/**
* gst_d3d11_handle_set_context:
* @element: a #GstElement
* @context: a #GstContext
* @device: (inout) (transfer full): location of a #GstD3DDevice
*
* Helper function for implementing #GstElementClass.set_context() in
* D3D11 capable elements.
*
* Retrieve's the #GstD3D11Device in @context and places the result in @device.
*
* Returns: whether the @device could be set successfully
*/
gboolean
gst_d3d11_handle_set_context (GstElement * element, GstContext * context,
gint adapter, GstD3D11Device ** device)
{
const gchar *context_type;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (device != NULL, FALSE);
_init_context_debug ();
if (!context)
return FALSE;
context_type = gst_context_get_context_type (context);
if (g_strcmp0 (context_type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE) == 0) {
const GstStructure *str;
GstD3D11Device *other_device = NULL;
guint other_adapter = 0;
/* If we had device already, will not replace it */
if (*device)
return TRUE;
str = gst_context_get_structure (context);
if (gst_structure_get (str, "device", GST_TYPE_D3D11_DEVICE,
&other_device, "adapter", G_TYPE_UINT, &other_adapter, NULL)) {
if (adapter == -1 || (guint) adapter == other_adapter) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT,
element, "Found D3D11 device context");
*device = other_device;
return TRUE;
}
gst_object_unref (other_device);
}
}
return FALSE;
}
static void
context_set_d3d11_device (GstContext * context, GstD3D11Device * device)
{
GstStructure *s;
guint adapter = 0;
guint device_id = 0;
guint vendor_id = 0;
gboolean hardware = FALSE;
gchar *desc = NULL;
gint64 adapter_luid = 0;
g_return_if_fail (context != NULL);
g_object_get (G_OBJECT (device), "adapter", &adapter, "device-id", &device_id,
"vendor-id", &vendor_id, "hardware", &hardware, "description", &desc,
"adapter-luid", &adapter_luid, NULL);
GST_CAT_LOG (GST_CAT_CONTEXT,
"setting GstD3D11Device(%" GST_PTR_FORMAT
") with adapter %d on context(%" GST_PTR_FORMAT ")",
device, adapter, context);
s = gst_context_writable_structure (context);
gst_structure_set (s, "device", GST_TYPE_D3D11_DEVICE, device,
"adapter", G_TYPE_UINT, adapter,
"adapter-luid", G_TYPE_INT64, adapter_luid,
"device-id", G_TYPE_UINT, device_id,
"vendor-id", G_TYPE_UINT, vendor_id,
"hardware", G_TYPE_BOOLEAN, hardware,
"description", G_TYPE_STRING, GST_STR_NULL (desc), NULL);
g_free (desc);
}
/**
* gst_d3d11_handle_context_query:
* @element: a #GstElement
* @query: a #GstQuery of type %GST_QUERY_CONTEXT
* @device: (transfer none) (nullable): a #GstD3D11Device
*
* Returns: Whether the @query was successfully responded to from the passed
* @device.
*/
gboolean
gst_d3d11_handle_context_query (GstElement * element, GstQuery * query,
GstD3D11Device * device)
{
const gchar *context_type;
GstContext *context, *old_context;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
_init_context_debug ();
GST_LOG_OBJECT (element, "handle context query %" GST_PTR_FORMAT, query);
if (!device)
return FALSE;
gst_query_parse_context_type (query, &context_type);
if (g_strcmp0 (context_type, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE) != 0)
return FALSE;
gst_query_parse_context (query, &old_context);
if (old_context)
context = gst_context_copy (old_context);
else
context = gst_context_new (GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
context_set_d3d11_device (context, device);
gst_query_set_context (query, context);
gst_context_unref (context);
GST_DEBUG_OBJECT (element, "successfully set %" GST_PTR_FORMAT
" on %" GST_PTR_FORMAT, device, query);
return TRUE;
}
static gboolean
pad_query (const GValue * item, GValue * value, gpointer user_data)
{
GstPad *pad = g_value_get_object (item);
GstQuery *query = user_data;
gboolean res;
res = gst_pad_peer_query (pad, query);
if (res) {
g_value_set_boolean (value, TRUE);
return FALSE;
}
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, pad, "pad peer query failed");
return TRUE;
}
static gboolean
run_query (GstElement * element, GstQuery * query, GstPadDirection direction)
{
GstIterator *it;
GstIteratorFoldFunction func = pad_query;
GValue res = { 0 };
g_value_init (&res, G_TYPE_BOOLEAN);
g_value_set_boolean (&res, FALSE);
/* Ask neighbor */
if (direction == GST_PAD_SRC)
it = gst_element_iterate_src_pads (element);
else
it = gst_element_iterate_sink_pads (element);
while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
gst_iterator_resync (it);
gst_iterator_free (it);
return g_value_get_boolean (&res);
}
static void
run_d3d11_context_query (GstElement * element, GstD3D11Device ** device)
{
GstQuery *query;
GstContext *ctxt = NULL;
/* 1) Query downstream with GST_QUERY_CONTEXT for the context and
* check if downstream already has a context of the specific type
*/
query = gst_query_new_context (GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE);
if (run_query (element, query, GST_PAD_SRC)) {
gst_query_parse_context (query, &ctxt);
if (ctxt) {
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"found context (%" GST_PTR_FORMAT ") in downstream query", ctxt);
gst_element_set_context (element, ctxt);
}
}
/* 2) although we found d3d11 device context above, the element does not want
* to use the context. Then try to find from the other direction */
if (*device == NULL && run_query (element, query, GST_PAD_SINK)) {
gst_query_parse_context (query, &ctxt);
if (ctxt) {
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"found context (%" GST_PTR_FORMAT ") in upstream query", ctxt);
gst_element_set_context (element, ctxt);
}
}
if (*device == NULL) {
/* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
* the required context type and afterwards check if a
* usable context was set now as in 1). The message could
* be handled by the parent bins of the element and the
* application.
*/
GstMessage *msg;
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"posting need context message");
msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE);
gst_element_post_message (element, msg);
}
/*
* Whomever responds to the need-context message performs a
* GstElement::set_context() with the required context in which the element
* is required to update the display_ptr or call gst_gl_handle_set_context().
*/
gst_query_unref (query);
}
/**
* gst_d3d11_ensure_element_data:
* @element: the #GstElement running the query
* @adapter: prefered adapter index, pass adapter >=0 when
* the adapter explicitly required. Otherwise, set -1.
* @device: (inout): the resulting #GstD3D11Device
*
* Perform the steps necessary for retrieving a #GstD3D11Device
* from the surrounding elements or from the application using the #GstContext mechanism.
*
* If the contents of @device is not %NULL, then no #GstContext query is
* necessary for #GstD3D11Device retrieval is performed.
*
* Returns: whether a #GstD3D11Device exists in @device
*/
gboolean
gst_d3d11_ensure_element_data (GstElement * element, gint adapter,
GstD3D11Device ** device)
{
guint target_adapter = 0;
g_return_val_if_fail (element != NULL, FALSE);
g_return_val_if_fail (device != NULL, FALSE);
_init_context_debug ();
if (*device) {
GST_LOG_OBJECT (element, "already have a device %" GST_PTR_FORMAT, *device);
return TRUE;
}
run_d3d11_context_query (element, device);
if (*device)
return TRUE;
if (adapter > 0)
target_adapter = adapter;
/* Needs D3D11_CREATE_DEVICE_BGRA_SUPPORT flag for Direct2D interop */
*device = gst_d3d11_device_new (target_adapter,
D3D11_CREATE_DEVICE_BGRA_SUPPORT);
if (*device == NULL) {
GST_ERROR_OBJECT (element,
"Couldn't create new device with adapter index %d", target_adapter);
return FALSE;
} else {
GstContext *context;
GstMessage *msg;
/* Propagate new D3D11 device context */
context = gst_context_new (GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
context_set_d3d11_device (context, *device);
gst_element_set_context (element, context);
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"posting have context (%p) message with D3D11 device context (%p)",
context, *device);
msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context);
gst_element_post_message (GST_ELEMENT_CAST (element), msg);
}
return TRUE;
}
gboolean
gst_d3d11_is_windows_8_or_greater (void)
{
static gsize version_once = 0;
static gboolean ret = FALSE;
if (g_once_init_enter (&version_once)) {
#if (!GST_D3D11_WINAPI_ONLY_APP)
if (IsWindows8OrGreater ())
ret = TRUE;
#else
ret = TRUE;
#endif
g_once_init_leave (&version_once, 1);
}
return ret;
}
GstD3D11DeviceVendor
gst_d3d11_get_device_vendor (GstD3D11Device * device)
{
guint device_id = 0;
guint vendor_id = 0;
gchar *desc = NULL;
GstD3D11DeviceVendor vendor = GST_D3D11_DEVICE_VENDOR_UNKNOWN;
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
g_object_get (device, "device-id", &device_id, "vendor-id", &vendor_id,
"description", &desc, NULL);
switch (vendor_id) {
case 0:
if (device_id == 0 && desc && g_strrstr (desc, "SraKmd"))
vendor = GST_D3D11_DEVICE_VENDOR_XBOX;
break;
case 0x1002:
case 0x1022:
vendor = GST_D3D11_DEVICE_VENDOR_AMD;
break;
case 0x8086:
vendor = GST_D3D11_DEVICE_VENDOR_INTEL;
break;
case 0x10de:
vendor = GST_D3D11_DEVICE_VENDOR_NVIDIA;
break;
case 0x4d4f4351:
vendor = GST_D3D11_DEVICE_VENDOR_QUALCOMM;
break;
default:
break;
}
g_free (desc);
return vendor;
}
GstBuffer *
gst_d3d11_allocate_staging_buffer (GstD3D11Allocator * allocator,
const GstVideoInfo * info, const GstD3D11Format * format,
const D3D11_TEXTURE2D_DESC desc[GST_VIDEO_MAX_PLANES],
gboolean add_videometa)
{
GstBuffer *buffer;
gint i;
gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
GstMemory *mem;
g_return_val_if_fail (GST_IS_D3D11_ALLOCATOR (allocator), NULL);
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (format != NULL, NULL);
g_return_val_if_fail (desc != NULL, NULL);
buffer = gst_buffer_new ();
if (format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
gsize size[GST_VIDEO_MAX_PLANES] = { 0, };
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
mem = gst_d3d11_allocator_alloc_staging (allocator, &desc[i], 0,
&stride[i]);
if (!mem) {
GST_ERROR_OBJECT (allocator, "Couldn't allocate memory for plane %d",
i);
goto error;
}
size[i] = gst_memory_get_sizes (mem, NULL, NULL);
if (i > 0)
offset[i] = offset[i - 1] + size[i - 1];
gst_buffer_append_memory (buffer, mem);
}
} else {
/* must be YUV semi-planar or single plane */
g_assert (GST_VIDEO_INFO_N_PLANES (info) <= 2);
mem = gst_d3d11_allocator_alloc_staging (allocator, &desc[0], 0,
&stride[0]);
if (!mem) {
GST_ERROR_OBJECT (allocator, "Couldn't allocate memory");
goto error;
}
gst_memory_get_sizes (mem, NULL, NULL);
gst_buffer_append_memory (buffer, mem);
if (GST_VIDEO_INFO_N_PLANES (info) == 2) {
stride[1] = stride[0];
offset[1] = stride[0] * desc[0].Height;
}
}
if (add_videometa) {
gst_buffer_add_video_meta_full (buffer, GST_VIDEO_FRAME_FLAG_NONE,
GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
offset, stride);
}
return buffer;
error:
gst_buffer_unref (buffer);
return NULL;
}
GstBuffer *
gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
const GstVideoInfo * info, gboolean add_videometa)
{
GstD3D11Memory *dmem;
GstD3D11Device *device;
GstD3D11AllocationParams *params = NULL;
GstD3D11Allocator *alloc = NULL;
GstBuffer *staging_buffer = NULL;
D3D11_TEXTURE2D_DESC *desc;
gint i;
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
if (!gst_is_d3d11_memory (mem)) {
GST_DEBUG ("Not a d3d11 memory");
return NULL;
}
}
dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
device = dmem->device;
params = gst_d3d11_allocation_params_new (device, (GstVideoInfo *) info,
0, 0);
if (!params) {
GST_WARNING ("Couldn't create alloc params");
goto done;
}
desc = &params->desc[0];
/* resolution of semi-planar formats must be multiple of 2 */
if (desc[0].Format == DXGI_FORMAT_NV12 || desc[0].Format == DXGI_FORMAT_P010
|| desc[0].Format == DXGI_FORMAT_P016) {
if (desc[0].Width % 2 || desc[0].Height % 2) {
gint width, height;
GstVideoAlignment align;
width = GST_ROUND_UP_2 (desc[0].Width);
height = GST_ROUND_UP_2 (desc[0].Height);
gst_video_alignment_reset (&align);
align.padding_right = width - desc[0].Width;
align.padding_bottom = height - desc[0].Height;
gst_d3d11_allocation_params_alignment (params, &align);
}
}
alloc = gst_d3d11_allocator_new (device);
if (!alloc) {
GST_WARNING ("Couldn't create allocator");
goto done;
}
staging_buffer = gst_d3d11_allocate_staging_buffer (alloc,
info, params->d3d11_format, params->desc, add_videometa);
if (!staging_buffer)
GST_WARNING ("Couldn't allocate staging buffer");
done:
if (params)
gst_d3d11_allocation_params_free (params);
if (alloc)
gst_object_unref (alloc);
return staging_buffer;
}
gboolean
_gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
const gchar * file, const gchar * function, gint line)
{
#ifndef GST_DISABLE_GST_DEBUG
gboolean ret = TRUE;
if (FAILED (hr)) {
gchar *error_text = NULL;
error_text = g_win32_error_message ((guint) hr);
/* g_win32_error_message() doesn't cover all HERESULT return code,
* so it could be empty string, or null if there was an error
* in g_utf16_to_utf8() */
gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line,
NULL, "D3D11 call failed: 0x%x, %s", (guint) hr,
GST_STR_NULL (error_text));
g_free (error_text);
ret = FALSE;
}
#if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
if (device) {
gst_d3d11_device_d3d11_debug (device, file, function, line);
gst_d3d11_device_dxgi_debug (device, file, function, line);
}
#endif
return ret;
#else
return SUCCEEDED (hr);
#endif
}
static gboolean
gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src,
const GstVideoInfo * info)
{
GstVideoFrame in_frame, out_frame;
gboolean ret;
if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src,
GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))
goto invalid_buffer;
if (!gst_video_frame_map (&out_frame, (GstVideoInfo *) info, dst,
GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) {
gst_video_frame_unmap (&in_frame);
goto invalid_buffer;
}
ret = gst_video_frame_copy (&out_frame, &in_frame);
gst_video_frame_unmap (&in_frame);
gst_video_frame_unmap (&out_frame);
return ret;
/* ERRORS */
invalid_buffer:
{
GST_ERROR ("Invalid video buffer");
return FALSE;
}
}
gboolean
gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src,
const GstVideoInfo * info)
{
guint i;
g_return_val_if_fail (GST_IS_BUFFER (dst), FALSE);
g_return_val_if_fail (GST_IS_BUFFER (src), FALSE);
g_return_val_if_fail (info != NULL, FALSE);
if (gst_buffer_n_memory (dst) != gst_buffer_n_memory (src)) {
GST_LOG ("different memory layout, perform fallback copy");
return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
}
if (!gst_is_d3d11_buffer (dst) || !gst_is_d3d11_buffer (src)) {
GST_LOG ("non-d3d11 memory, perform fallback copy");
return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
}
for (i = 0; i < gst_buffer_n_memory (dst); i++) {
GstMemory *dst_mem, *src_mem;
GstD3D11Memory *dst_dmem, *src_dmem;
GstMapInfo dst_info;
GstMapInfo src_info;
ID3D11Resource *dst_texture, *src_texture;
ID3D11DeviceContext *device_context;
GstD3D11Device *device;
D3D11_BOX src_box = { 0, };
D3D11_TEXTURE2D_DESC dst_desc, src_desc;
guint dst_subidx, src_subidx;
dst_mem = gst_buffer_peek_memory (dst, i);
src_mem = gst_buffer_peek_memory (src, i);
dst_dmem = (GstD3D11Memory *) dst_mem;
src_dmem = (GstD3D11Memory *) src_mem;
device = dst_dmem->device;
if (device != src_dmem->device) {
GST_LOG ("different device, perform fallback copy");
return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
}
gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc);
gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc);
if (dst_desc.Format != src_desc.Format) {
GST_WARNING ("different dxgi format");
return FALSE;
}
device_context = gst_d3d11_device_get_device_context_handle (device);
if (!gst_memory_map (dst_mem, &dst_info, GST_MAP_WRITE | GST_MAP_D3D11)) {
GST_ERROR ("Cannot map dst d3d11 memory");
return FALSE;
}
if (!gst_memory_map (src_mem, &src_info, GST_MAP_READ | GST_MAP_D3D11)) {
GST_ERROR ("Cannot map src d3d11 memory");
gst_memory_unmap (dst_mem, &dst_info);
return FALSE;
}
dst_texture = (ID3D11Resource *) dst_info.data;
src_texture = (ID3D11Resource *) src_info.data;
/* src/dst texture size might be different if padding was used.
* select smaller size */
src_box.left = 0;
src_box.top = 0;
src_box.front = 0;
src_box.back = 1;
src_box.right = MIN (src_desc.Width, dst_desc.Width);
src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem);
src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem);
gst_d3d11_device_lock (device);
ID3D11DeviceContext_CopySubresourceRegion (device_context,
dst_texture, dst_subidx, 0, 0, 0, src_texture, src_subidx, &src_box);
gst_d3d11_device_unlock (device);
gst_memory_unmap (src_mem, &src_info);
gst_memory_unmap (dst_mem, &dst_info);
}
return TRUE;
}
gboolean
gst_is_d3d11_buffer (GstBuffer * buffer)
{
guint i;
guint size;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
size = gst_buffer_n_memory (buffer);
if (size == 0)
return FALSE;
for (i = 0; i < size; i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
if (!gst_is_d3d11_memory (mem))
return FALSE;
}
return TRUE;
}
gboolean
gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device)
{
guint i;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (device != NULL, FALSE);
if (!gst_is_d3d11_buffer (buffer)) {
GST_LOG ("Not a d3d11 buffer");
return FALSE;
}
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
ID3D11Device *handle;
handle = gst_d3d11_device_get_device_handle (mem->device);
if (handle != device) {
GST_LOG ("D3D11 device is incompatible");
return FALSE;
}
}
return TRUE;
}
gboolean
gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device,
GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
{
GstMapFlags map_flags;
gint num_mapped = 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (info != NULL, FALSE);
if (!gst_d3d11_buffer_can_access_device (buffer, device))
return FALSE;
map_flags = flags | GST_MAP_D3D11;
for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
if (!gst_memory_map (mem, &info[num_mapped], map_flags)) {
GST_ERROR ("Couldn't map memory");
goto error;
}
}
return TRUE;
error:
{
gint i;
for (i = 0; i < num_mapped; i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
gst_memory_unmap (mem, &info[i]);
}
return FALSE;
}
}
gboolean
gst_d3d11_buffer_unmap (GstBuffer * buffer,
GstMapInfo info[GST_VIDEO_MAX_PLANES])
{
gint i;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (info != NULL, FALSE);
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
gst_memory_unmap (mem, &info[i]);
}
return TRUE;
}
guint
gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer,
ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])
{
gint i;
guint num_views = 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
g_return_val_if_fail (view != NULL, 0);
if (!gst_is_d3d11_buffer (buffer)) {
GST_ERROR ("Buffer contains non-d3d11 memory");
return 0;
}
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
guint view_size;
gint j;
view_size = gst_d3d11_memory_get_shader_resource_view_size (mem);
if (!view_size) {
GST_LOG ("SRV is unavailable for memory index %d", i);
return 0;
}
for (j = 0; j < view_size; j++) {
if (num_views >= GST_VIDEO_MAX_PLANES) {
GST_ERROR ("Too many SRVs");
return 0;
}
view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j);
}
}
return num_views;
}
guint
gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer,
ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])
{
gint i;
guint num_views = 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
g_return_val_if_fail (view != NULL, 0);
if (!gst_is_d3d11_buffer (buffer)) {
GST_ERROR ("Buffer contains non-d3d11 memory");
return 0;
}
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
guint view_size;
gint j;
view_size = gst_d3d11_memory_get_render_target_view_size (mem);
if (!view_size) {
GST_LOG ("RTV is unavailable for memory index %d", i);
return 0;
}
for (j = 0; j < view_size; j++) {
if (num_views >= GST_VIDEO_MAX_PLANES) {
GST_ERROR ("Too many RTVs");
return 0;
}
view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j);
}
}
return num_views;
}
GstBufferPool *
gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
GstCaps * caps, GstD3D11AllocationParams * alloc_params,
guint min_buffers, guint max_buffers)
{
GstBufferPool *pool;
GstStructure *config;
GstVideoInfo info;
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
g_return_val_if_fail (alloc_params != NULL, NULL);
if (!gst_video_info_from_caps (&info, caps)) {
GST_ERROR_OBJECT (device, "invalid caps");
return NULL;
}
pool = gst_d3d11_buffer_pool_new (device);
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config,
caps, GST_VIDEO_INFO_SIZE (&info), min_buffers, max_buffers);
gst_buffer_pool_config_set_d3d11_allocation_params (config, alloc_params);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
if (!gst_buffer_pool_set_config (pool, config)) {
GST_ERROR_OBJECT (pool, "Couldn't set config");
gst_object_unref (pool);
return NULL;
}
return pool;
}

View file

@ -21,10 +21,6 @@
# include <config.h>
#endif
#include "gstd3d11device.h"
#include "gstd3d11utils.h"
#include "gstd3d11format.h"
#include "gstd3d11memory.h"
#include "gstd3d11videoprocessor.h"
#include <string.h>

View file

@ -22,7 +22,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
G_BEGIN_DECLS

View file

@ -22,12 +22,8 @@
#endif
#include "gstd3d11videosink.h"
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11bufferpool.h"
#include "gstd3d11format.h"
#include "gstd3d11videoprocessor.h"
#include "gstd3d11pluginutils.h"
#if GST_D3D11_WINAPI_ONLY_APP
#include "gstd3d11window_corewindow.h"
@ -326,6 +322,70 @@ gst_d3d11_video_sink_set_context (GstElement * element, GstContext * context)
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
}
static GstCaps *
gst_d3d11_video_sink_get_supported_caps (GstD3D11VideoSink * self,
D3D11_FORMAT_SUPPORT flags)
{
GstD3D11Device *device;
ID3D11Device *d3d11_device;
HRESULT hr;
gint i;
GValue v_list = G_VALUE_INIT;
GstCaps *supported_caps;
static const GstVideoFormat format_list[] = {
GST_VIDEO_FORMAT_BGRA,
GST_VIDEO_FORMAT_RGBA,
GST_VIDEO_FORMAT_RGB10A2_LE,
GST_VIDEO_FORMAT_VUYA,
GST_VIDEO_FORMAT_NV12,
GST_VIDEO_FORMAT_P010_10LE,
GST_VIDEO_FORMAT_P016_LE,
GST_VIDEO_FORMAT_I420,
GST_VIDEO_FORMAT_I420_10LE,
};
device = self->device;
d3d11_device = gst_d3d11_device_get_device_handle (device);
g_value_init (&v_list, GST_TYPE_LIST);
for (i = 0; i < G_N_ELEMENTS (format_list); i++) {
UINT format_support = 0;
GstVideoFormat format;
const GstD3D11Format *d3d11_format;
d3d11_format = gst_d3d11_device_format_from_gst (device, format_list[i]);
if (!d3d11_format || d3d11_format->dxgi_format == DXGI_FORMAT_UNKNOWN)
continue;
format = d3d11_format->format;
hr = ID3D11Device_CheckFormatSupport (d3d11_device,
d3d11_format->dxgi_format, &format_support);
if (SUCCEEDED (hr) && ((format_support & flags) == flags)) {
GValue v_str = G_VALUE_INIT;
g_value_init (&v_str, G_TYPE_STRING);
GST_LOG_OBJECT (self, "d3d11 device can support %s with flags 0x%x",
gst_video_format_to_string (format), flags);
g_value_set_string (&v_str, gst_video_format_to_string (format));
gst_value_list_append_and_take_value (&v_list, &v_str);
}
}
supported_caps = gst_caps_new_simple ("video/x-raw",
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
gst_caps_set_value (supported_caps, "format", &v_list);
g_value_unset (&v_list);
gst_caps_set_features_simple (supported_caps,
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY));
return supported_caps;
}
static GstCaps *
gst_d3d11_video_sink_get_caps (GstBaseSink * sink, GstCaps * filter)
{
@ -336,7 +396,7 @@ gst_d3d11_video_sink_get_caps (GstBaseSink * sink, GstCaps * filter)
GstCaps *overlaycaps;
GstCapsFeatures *features;
caps = gst_d3d11_device_get_supported_caps (self->device,
caps = gst_d3d11_video_sink_get_supported_caps (self,
D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DISPLAY);
overlaycaps = gst_caps_copy (caps);
features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,

View file

@ -25,8 +25,7 @@
#include <gst/video/gstvideosink.h>
#include <gst/video/videooverlay.h>
#include <gst/video/navigation.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
#include "gstd3d11window.h"
G_BEGIN_DECLS

View file

@ -25,15 +25,9 @@
#include <gst/video/gstvideosink.h>
#include <gst/video/videooverlay.h>
#include <gst/video/navigation.h>
#include "gstd3d11videosinkbin.h"
#include <gst/d3d11/gstd3d11.h>
#include "gstd3d11videosink.h"
#include "gstd3d11upload.h"
#include "gstd3d11colorconvert.h"
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11format.h"
#include "gstd3d11videosinkbin.h"
enum
{

View file

@ -22,8 +22,6 @@
#endif
#include "gstd3d11vp8dec.h"
#include "gstd3d11memory.h"
#include "gstd3d11bufferpool.h"
#include <gst/codecs/gstvp8decoder.h>
#include <string.h>

View file

@ -52,8 +52,6 @@
#endif
#include "gstd3d11vp9dec.h"
#include "gstd3d11memory.h"
#include "gstd3d11bufferpool.h"
#include <gst/codecs/gstvp9decoder.h>
#include <string.h>

View file

@ -23,9 +23,7 @@
#endif
#include "gstd3d11window.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11pluginutils.h"
#if GST_D3D11_WINAPI_ONLY_APP
/* workaround for GetCurrentTime collision */

View file

@ -24,10 +24,11 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include <gst/d3d11/gstd3d11.h>
#include "gstd3d11colorconverter.h"
#include "gstd3d11overlaycompositor.h"
#include "gstd3d11videoprocessor.h"
#include "gstd3d11pluginutils.h"
G_BEGIN_DECLS

View file

@ -22,10 +22,6 @@
#include "config.h"
#endif
#include "gstd3d11window.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11window_corewindow.h"
/* workaround for GetCurrentTime collision */

View file

@ -23,7 +23,6 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11window.h"
G_BEGIN_DECLS

View file

@ -22,10 +22,6 @@
#include "config.h"
#endif
#include "gstd3d11window.h"
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11window_swapchainpanel.h"
/* workaround for GetCurrentTime collision */

View file

@ -23,7 +23,6 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11window.h"
G_BEGIN_DECLS

View file

@ -24,9 +24,6 @@
#include "config.h"
#endif
#include "gstd3d11device.h"
#include "gstd3d11memory.h"
#include "gstd3d11utils.h"
#include "gstd3d11window_win32.h"
extern "C" {

View file

@ -23,7 +23,6 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d11_fwd.h"
#include "gstd3d11window.h"
G_BEGIN_DECLS

View file

@ -1,23 +1,19 @@
d3d11_sources = [
'gstd3d11bufferpool.c',
'gstd3d11device.c',
'gstd3d11memory.c',
'gstd3d11utils.c',
'gstd3d11videosink.c',
'gstd3d11window.cpp',
'plugin.c',
'gstd3d11format.c',
'gstd3d11basefilter.c',
'gstd3d11upload.c',
'gstd3d11download.c',
'gstd3d11colorconvert.c',
'gstd3d11videosinkbin.c',
'gstd3d11shader.c',
'gstd3d11colorconverter.c',
'gstd3d11overlaycompositor.c',
'gstd3d11videoprocessor.c',
'gstd3d11compositor.c',
'gstd3d11compositorbin.c',
'gstd3d11download.c',
'gstd3d11overlaycompositor.c',
'gstd3d11pluginutils.c',
'gstd3d11shader.c',
'gstd3d11upload.c',
'gstd3d11videoprocessor.c',
'gstd3d11videosink.c',
'gstd3d11videosinkbin.c',
'gstd3d11window.cpp',
'plugin.c',
]
d3d11_dec_sources = [
@ -28,62 +24,26 @@ d3d11_dec_sources = [
'gstd3d11vp8dec.c',
]
dxgi_headers = [
['dxgi1_6.h', 6],
['dxgi1_5.h', 5],
['dxgi1_4.h', 4],
['dxgi1_3.h', 3],
['dxgi1_2.h', 2],
['dxgi.h', 1]
]
d3d11_headers = [
['d3d11_4.h', 4],
['d3d11_3.h', 3],
['d3d11_2.h', 2],
['d3d11_1.h', 1],
['d3d11.h', 0]
]
have_d3d11 = false
extra_c_args = ['-DCOBJMACROS']
extra_cpp_args = []
have_dxgi_header = false
have_d3d11_header = false
have_d3d11sdk_h = false
have_dxgidebug_h = false
winapi_desktop = false
winapi_app = false
extra_c_args = ['-DCOBJMACROS', '-DGST_USE_UNSTABLE_API']
extra_cpp_args = ['-DGST_USE_UNSTABLE_API']
extra_dep = []
d3d11_conf = configuration_data()
d3d11_option = get_option('d3d11')
if host_system != 'windows' or d3d11_option.disabled()
subdir_done()
endif
d3d11_lib = cc.find_library('d3d11', required : d3d11_option)
dxgi_lib = cc.find_library('dxgi', required : d3d11_option)
if not gstd3d11_dep.found()
if d3d11_option.enabled()
error('The d3d11 was enabled explicitly, but required dependencies were not found.')
endif
subdir_done()
endif
d3dcompiler_lib = cc.find_library('d3dcompiler', required: d3d11_option)
runtimeobject_lib = cc.find_library('runtimeobject', required : false)
dwrite_lib = cc.find_library('dwrite', required : false)
d2d1_lib = cc.find_library('d2d1', required : false)
foreach dxgi_h: dxgi_headers
if not have_dxgi_header and cc.has_header(dxgi_h[0])
d3d11_conf.set('DXGI_HEADER_VERSION', dxgi_h[1])
have_dxgi_header = true
endif
endforeach
foreach d3d11_h: d3d11_headers
if not have_d3d11_header and cc.has_header(d3d11_h[0])
d3d11_conf.set('D3D11_HEADER_VERSION', d3d11_h[1])
have_d3d11_header = true
endif
endforeach
have_d3d11 = d3d11_lib.found() and dxgi_lib.found() and have_d3d11_header and have_dxgi_header and cc.has_header('d3dcompiler.h')
have_d3d11 = cc.has_header('d3dcompiler.h')
if not have_d3d11
if d3d11_option.enabled()
error('The d3d11 plugin was enabled explicitly, but required dependencies were not found.')
@ -93,121 +53,33 @@ endif
# d3d11 video api uses dxva structure for decoding, and dxva.h needs d3d9 types
if cc.has_header('dxva.h') and cc.has_header('d3d9.h')
d3d11_conf.set('HAVE_DXVA_H', 1)
d3d11_sources += d3d11_dec_sources
extra_c_args += ['-DGST_USE_UNSTABLE_API']
extra_c_args += ['-DHAVE_DXVA_H']
extra_dep += [gstcodecs_dep]
endif
winapi_desktop = cxx.compiles('''#include <winapifamily.h>
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#error "not win32"
#endif''',
dependencies: [d3d11_lib, dxgi_lib],
name: 'checking if building for Win32')
if runtimeobject_lib.found() and d3dcompiler_lib.found()
winapi_app = cxx.compiles('''#include <winapifamily.h>
#include <windows.applicationmodel.core.h>
#include <wrl.h>
#include <wrl/wrappers/corewrappers.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#error "not winrt"
#endif''',
dependencies: [d3d11_lib, dxgi_lib, runtimeobject_lib],
name: 'checking if building for WinRT')
if d3d11_winapi_only_app and (not d3dcompiler_lib.found() or not runtimeobject_lib.found())
if d3d11_option.enabled()
error('The d3d11 plugin was enabled explicitly, but required dependencies were not found.')
endif
subdir_done()
endif
if not winapi_desktop and not winapi_app
error('Neither Desktop partition nor App partition')
endif
winapi_app_only = winapi_app and not winapi_desktop
if winapi_app_only
if d3d11_winapi_only_app
d3d11_sources += ['gstd3d11window_corewindow.cpp',
'gstd3d11window_swapchainpanel.cpp']
extra_dep += [runtimeobject_lib, d3dcompiler_lib]
else
d3d11_sources += ['gstd3d11window_win32.cpp']
if d3d11_conf.get('DXGI_HEADER_VERSION') >= 6
if d3d11_conf.get('GST_D3D11_DXGI_HEADER_VERSION') >= 6
# Desktop Duplication API is unavailable for UWP
# and MinGW is not supported due to some missing headers
d3d11_conf.set('HAVE_DXGI_DESKTOP_DUP', 1)
extra_c_args += ['-DHAVE_DXGI_DESKTOP_DUP']
d3d11_sources += ['gstd3d11desktopdup.cpp', 'gstd3d11desktopdupsrc.c']
message('Enable D3D11 Desktop Duplication API')
endif
endif
d3d11_conf.set10('GST_D3D11_WINAPI_ONLY_APP', winapi_app_only)
# for enabling debug layer
# NOTE: Disable d3d11/dxgi debug layer in case of [UWP build + release CRT]
# WACK (Windows App Certification Kit) doesn't seem to be happy with
# the DXGIGetDebugInterface1 symbol.
# FIXME: Probably DXGIGetDebugInterface1 might be used on UWP app for development
# purpose. So, I suspect one possible reason why WACK is complaining about
# DXGIGetDebugInterface1 is that debugging APIs couldn't be used for
# Windows store app, but couldn't find any reference about that.
#
# [IDXGIDebug1]
# https://docs.microsoft.com/en-us/windows/win32/api/dxgidebug/nn-dxgidebug-idxgidebug1
# is saying that the IDXGIDebug1 interface is available for both desktop app and
# UWP. And then the *DXGIGetDebugInterface1* method need to be called to obtain
# the IDXGIDebug1 interface.
#
# [DXGIGetDebugInterface1]
# https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-dxgigetdebuginterface1
# is mentioning that DXGIGetDebugInterface1 is desktop app only.
#
# PLEASE LET US KNOW A CORRECT WAY TO OBTAIN IDXGIDebug1 ON UWP, MICROSOFT
if get_option('debug') and not (winapi_app_only and get_option('b_vscrt') == 'md')
d3d11_debug_libs = [
['d3d11sdklayers.h', 'ID3D11Debug', 'ID3D11InfoQueue', 'have_d3d11sdk_h'],
['dxgidebug.h', 'IDXGIDebug', 'IDXGIInfoQueue', 'have_dxgidebug_h'],
]
foreach f : d3d11_debug_libs
header = f.get(0)
debug_obj = f.get(1)
info_obj = f.get(2)
compile_code = '''
#include <d3d11.h>
#include <dxgi.h>
#include <@0@>
int main(int arc, char ** argv) {
@1@ *debug = NULL;
@2@ *info_queue = NULL;
return 0;
}'''.format(header, debug_obj, info_obj)
if cc.compiles(compile_code, dependencies: [d3d11_lib, dxgi_lib], name: debug_obj)
set_variable(f.get(3), true)
endif
endforeach
# Maybe we want to implement DirectWrite based text rendering in the future,
# but currently only debugging purpose.
# Also, MinGW is not supported for now because of toolchain issue
if cc.get_id() == 'msvc' and dwrite_lib.found() and d2d1_lib.found() and cc.has_header('dwrite.h') and cc.has_header('d2d1_1.h')
d3d11_conf.set('HAVE_DIRECT_WRITE', 1)
extra_dep += [dwrite_lib, d2d1_lib]
message('Enable DirectWrite support in D3D11 plugin')
endif
else
message('Disable D3D11Debug and DXGIDebug layers')
endif
d3d11_conf.set10('HAVE_D3D11SDKLAYERS_H', have_d3d11sdk_h)
d3d11_conf.set10('HAVE_DXGIDEBUG_H', have_dxgidebug_h)
configure_file(
output: 'gstd3d11config.h',
configuration: d3d11_conf,
)
# MinGW 32bits compiler seems to be complaining about redundant-decls
# when ComPtr is in use. Let's just disable the warning
if cc.get_id() != 'msvc'
@ -224,7 +96,7 @@ gstd3d11 = library('gstd3d11',
c_args : gst_plugins_bad_args + extra_c_args,
cpp_args: gst_plugins_bad_args + extra_cpp_args,
include_directories : [configinc],
dependencies : [gstbase_dep, gstvideo_dep, gmodule_dep, gstcontroller_dep, d3d11_lib, dxgi_lib] + extra_dep,
dependencies : [gstbase_dep, gstvideo_dep, gmodule_dep, gstcontroller_dep, gstd3d11_dep] + extra_dep,
install : true,
install_dir : plugins_install_dir,
)

View file

@ -21,9 +21,8 @@
#include "config.h"
#endif
#include "gstd3d11config.h"
#include <gst/gst.h>
#include <gst/d3d11/gstd3d11.h>
#include "gstd3d11videosink.h"
#include "gstd3d11upload.h"
#include "gstd3d11download.h"
@ -33,7 +32,6 @@
#include "gstd3d11compositor.h"
#include "gstd3d11compositorbin.h"
#ifdef HAVE_DXVA_H
#include "gstd3d11utils.h"
#include "gstd3d11h264dec.h"
#include "gstd3d11h265dec.h"
#include "gstd3d11vp9dec.h"
@ -46,7 +44,7 @@
GST_DEBUG_CATEGORY (gst_d3d11_debug);
GST_DEBUG_CATEGORY (gst_d3d11_shader_debug);
GST_DEBUG_CATEGORY (gst_d3d11_colorconverter_debug);
GST_DEBUG_CATEGORY (gst_d3d11_utils_debug);
GST_DEBUG_CATEGORY (gst_d3d11_plugin_utils_debug);
GST_DEBUG_CATEGORY (gst_d3d11_format_debug);
GST_DEBUG_CATEGORY (gst_d3d11_device_debug);
GST_DEBUG_CATEGORY (gst_d3d11_overlay_compositor_debug);
@ -54,10 +52,6 @@ GST_DEBUG_CATEGORY (gst_d3d11_window_debug);
GST_DEBUG_CATEGORY (gst_d3d11_video_processor_debug);
GST_DEBUG_CATEGORY (gst_d3d11_compositor_debug);
#if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
GST_DEBUG_CATEGORY (gst_d3d11_debug_layer_debug);
#endif
#ifdef HAVE_DXVA_H
GST_DEBUG_CATEGORY (gst_d3d11_h264_dec_debug);
GST_DEBUG_CATEGORY (gst_d3d11_h265_dec_debug);
@ -88,12 +82,8 @@ plugin_init (GstPlugin * plugin)
"d3d11shader", 0, "d3d11shader");
GST_DEBUG_CATEGORY_INIT (gst_d3d11_colorconverter_debug,
"d3d11colorconverter", 0, "d3d11colorconverter");
GST_DEBUG_CATEGORY_INIT (gst_d3d11_utils_debug,
"d3d11utils", 0, "d3d11 utility functions");
GST_DEBUG_CATEGORY_INIT (gst_d3d11_format_debug,
"d3d11format", 0, "d3d11 specific formats");
GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug,
"d3d11device", 0, "d3d11 device object");
GST_DEBUG_CATEGORY_INIT (gst_d3d11_plugin_utils_debug,
"d3d11pluginutils", 0, "d3d11 plugin utility functions");
GST_DEBUG_CATEGORY_INIT (gst_d3d11_overlay_compositor_debug,
"d3d11overlaycompositor", 0, "d3d11overlaycompositor");
GST_DEBUG_CATEGORY_INIT (gst_d3d11_window_debug,
@ -103,12 +93,6 @@ plugin_init (GstPlugin * plugin)
GST_DEBUG_CATEGORY_INIT (gst_d3d11_compositor_debug,
"d3d11compositor", 0, "d3d11compositor element");
#if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
/* NOTE: enabled only for debug build */
GST_DEBUG_CATEGORY_INIT (gst_d3d11_debug_layer_debug,
"d3d11debuglayer", 0, "native d3d11 and dxgi debug");
#endif
if (!gst_d3d11_shader_init ()) {
GST_WARNING ("Cannot initialize d3d11 shader");
return TRUE;