d3d11: Implement memory pool

Major changes:
* GstD3D11Allocator: This allocator is now device-independent object
  which can allocate GstD3D11Memory object for any GstD3D11Device.
  User can get this object via gst_allocator_find(GST_D3D11_MEMORY_NAME)
* GstD3D11PoolAllocator: A new allocator implementation for texture pool.
  From now on GstD3D11BufferPool will make use of this memory pool allocator
  to avoid frequent texture reallocation. That usually happens because
  of buffer copy (gst_buffer_make_writable for example)

In addition to that, GstD3D11BufferPool will provide GstBuffer with
GstVideoMeta, because CPU access to a GstD3D11Memory without GstVideoMeta
is almost impossible since GPU drivers needs padding for stride alignment.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2097>
This commit is contained in:
Seungha Yang 2021-03-18 22:31:55 +09:00 committed by GStreamer Marge Bot
parent 4e7e390cab
commit 39b9f79e11
10 changed files with 1495 additions and 1138 deletions

View file

@ -64,9 +64,13 @@ 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;
typedef struct _GstD3D11PoolAllocator GstD3D11PoolAllocator;
typedef struct _GstD3D11PoolAllocatorClass GstD3D11PoolAllocatorClass;
typedef struct _GstD3D11PoolAllocatorPrivate GstD3D11PoolAllocatorPrivate;
typedef struct _GstD3D11BufferPool GstD3D11BufferPool;
typedef struct _GstD3D11BufferPoolClass GstD3D11BufferPoolClass;

View file

@ -45,14 +45,12 @@ GST_DEBUG_CATEGORY_STATIC (gst_d3d11_buffer_pool_debug);
struct _GstD3D11BufferPoolPrivate
{
GstD3D11Device *device;
GstD3D11Allocator *allocator;
GstD3D11Allocator *alloc[GST_VIDEO_MAX_PLANES];
gboolean add_videometa;
GstD3D11AllocationParams *d3d11_params;
gboolean texture_array_pool;
gint stride[GST_VIDEO_MAX_PLANES];
gsize size[GST_VIDEO_MAX_PLANES];
gsize offset[GST_VIDEO_MAX_PLANES];
};
@ -64,10 +62,14 @@ static void gst_d3d11_buffer_pool_dispose (GObject * object);
static const gchar **gst_d3d11_buffer_pool_get_options (GstBufferPool * pool);
static gboolean gst_d3d11_buffer_pool_set_config (GstBufferPool * pool,
GstStructure * config);
static GstFlowReturn gst_d3d11_buffer_pool_alloc (GstBufferPool * pool,
static GstFlowReturn gst_d3d11_buffer_pool_alloc_buffer (GstBufferPool * pool,
GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
static void gst_d3d11_buffer_pool_flush_start (GstBufferPool * pool);
static void gst_d3d11_buffer_pool_flush_stop (GstBufferPool * pool);
static GstFlowReturn gst_d3d11_buffer_pool_acquire_buffer (GstBufferPool * pool,
GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
static void gst_d3d11_buffer_pool_reset_buffer (GstBufferPool * pool,
GstBuffer * buffer);
static gboolean gst_d3d11_buffer_pool_start (GstBufferPool * pool);
static gboolean gst_d3d11_buffer_pool_stop (GstBufferPool * pool);
static void
gst_d3d11_buffer_pool_class_init (GstD3D11BufferPoolClass * klass)
@ -79,9 +81,11 @@ gst_d3d11_buffer_pool_class_init (GstD3D11BufferPoolClass * klass)
bufferpool_class->get_options = gst_d3d11_buffer_pool_get_options;
bufferpool_class->set_config = gst_d3d11_buffer_pool_set_config;
bufferpool_class->alloc_buffer = gst_d3d11_buffer_pool_alloc;
bufferpool_class->flush_start = gst_d3d11_buffer_pool_flush_start;
bufferpool_class->flush_stop = gst_d3d11_buffer_pool_flush_stop;
bufferpool_class->alloc_buffer = gst_d3d11_buffer_pool_alloc_buffer;
bufferpool_class->acquire_buffer = gst_d3d11_buffer_pool_acquire_buffer;
bufferpool_class->reset_buffer = gst_d3d11_buffer_pool_reset_buffer;
bufferpool_class->start = gst_d3d11_buffer_pool_start;
bufferpool_class->stop = gst_d3d11_buffer_pool_stop;
GST_DEBUG_CATEGORY_INIT (gst_d3d11_buffer_pool_debug, "d3d11bufferpool", 0,
"d3d11bufferpool object");
@ -93,18 +97,29 @@ gst_d3d11_buffer_pool_init (GstD3D11BufferPool * self)
self->priv = gst_d3d11_buffer_pool_get_instance_private (self);
}
static void
gst_d3d11_buffer_pool_clear_allocator (GstD3D11BufferPool * self)
{
GstD3D11BufferPoolPrivate *priv = self->priv;
guint i;
for (i = 0; i < G_N_ELEMENTS (priv->alloc); i++) {
if (priv->alloc[i]) {
gst_d3d11_allocator_set_active (priv->alloc[i], FALSE);
gst_clear_object (&priv->alloc[i]);
}
}
}
static void
gst_d3d11_buffer_pool_dispose (GObject * object)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (object);
GstD3D11BufferPoolPrivate *priv = self->priv;
if (priv->d3d11_params)
gst_d3d11_allocation_params_free (priv->d3d11_params);
priv->d3d11_params = NULL;
gst_clear_object (&priv->device);
gst_clear_object (&priv->allocator);
g_clear_pointer (&priv->d3d11_params, gst_d3d11_allocation_params_free);
gst_clear_object (&self->device);
gst_d3d11_buffer_pool_clear_allocator (self);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@ -118,79 +133,6 @@ 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)
{
@ -199,10 +141,10 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
GstVideoInfo info;
GstCaps *caps = NULL;
guint min_buffers, max_buffers;
GstAllocator *allocator = NULL;
gboolean ret = TRUE;
D3D11_TEXTURE2D_DESC *desc;
GstBuffer *staging_buffer;
const GstD3D11Format *format;
gsize offset = 0;
gint i;
if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers,
@ -219,24 +161,10 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height,
caps);
if (!gst_buffer_pool_config_get_allocator (config, &allocator, NULL))
goto wrong_config;
gst_d3d11_buffer_pool_clear_allocator (self);
gst_clear_object (&priv->allocator);
if (allocator) {
if (!GST_IS_D3D11_ALLOCATOR (allocator)) {
goto wrong_allocator;
} else {
priv->allocator = gst_object_ref (allocator);
}
} else {
priv->allocator = gst_d3d11_allocator_new (priv->device);
g_assert (priv->allocator);
}
priv->add_videometa = gst_buffer_pool_config_has_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_META);
memset (priv->stride, 0, sizeof (priv->stride));
memset (priv->offset, 0, sizeof (priv->offset));
if (priv->d3d11_params)
gst_d3d11_allocation_params_free (priv->d3d11_params);
@ -245,7 +173,7 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
if (!priv->d3d11_params) {
/* allocate memory with resource format by default */
priv->d3d11_params =
gst_d3d11_allocation_params_new (priv->device, &info, 0, 0);
gst_d3d11_allocation_params_new (self->device, &info, 0, 0);
}
desc = priv->d3d11_params->desc;
@ -313,35 +241,71 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
max_buffers, max_array_size);
max_buffers = max_array_size;
}
priv->texture_array_pool = TRUE;
} else {
priv->texture_array_pool = FALSE;
}
staging_buffer = allocate_staging_buffer (priv->allocator,
&info, priv->d3d11_params->d3d11_format, priv->d3d11_params->desc, TRUE);
offset = 0;
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
GstD3D11Allocator *alloc;
GstD3D11PoolAllocator *pool_alloc;
GstFlowReturn flow_ret;
GstMemory *mem = NULL;
guint stride = 0;
if (!staging_buffer) {
GST_ERROR_OBJECT (pool, "Couldn't allocated staging buffer");
return FALSE;
} else {
GstVideoMeta *meta = gst_buffer_get_video_meta (staging_buffer);
if (desc[i].Format == DXGI_FORMAT_UNKNOWN)
break;
if (!meta) {
GST_ERROR_OBJECT (pool, "Buffer doesn't have video meta");
gst_buffer_unref (staging_buffer);
alloc =
(GstD3D11Allocator *) gst_d3d11_pool_allocator_new (self->device,
&desc[i]);
if (!gst_d3d11_allocator_set_active (alloc, TRUE)) {
GST_ERROR_OBJECT (self, "Failed to activate allocator");
gst_object_unref (alloc);
return FALSE;
}
for (i = 0; i < gst_buffer_n_memory (staging_buffer); i++) {
GstMemory *mem = gst_buffer_peek_memory (staging_buffer, i);
priv->size[i] = gst_memory_get_sizes (mem, NULL, NULL);
pool_alloc = GST_D3D11_POOL_ALLOCATOR (alloc);
flow_ret = gst_d3d11_pool_allocator_acquire_memory (pool_alloc, &mem);
if (flow_ret != GST_FLOW_OK) {
GST_ERROR_OBJECT (self, "Failed to allocate initial memory");
gst_d3d11_allocator_set_active (alloc, FALSE);
gst_object_unref (alloc);
return FALSE;
}
memcpy (priv->offset, meta->offset, sizeof (priv->offset));
memcpy (priv->stride, meta->stride, sizeof (priv->stride));
if (!gst_d3d11_memory_get_texture_stride (GST_D3D11_MEMORY_CAST (mem),
&stride) || stride < desc[i].Width) {
GST_ERROR_OBJECT (self, "Failed to calculate stride");
gst_d3d11_allocator_set_active (alloc, FALSE);
gst_object_unref (alloc);
gst_memory_unref (mem);
return FALSE;
}
priv->stride[i] = stride;
priv->offset[i] = offset;
offset += mem->size;
priv->alloc[i] = alloc;
gst_memory_unref (mem);
}
self->buffer_size = gst_buffer_get_size (staging_buffer);
gst_buffer_unref (staging_buffer);
g_assert (priv->d3d11_params->d3d11_format != NULL);
format = priv->d3d11_params->d3d11_format;
/* single texture semi-planar formats */
if (format->dxgi_format != DXGI_FORMAT_UNKNOWN &&
GST_VIDEO_INFO_N_PLANES (&info) == 2) {
priv->stride[1] = priv->stride[0];
priv->offset[1] = priv->stride[0] * desc[0].Height;
}
self->buffer_size = offset;
gst_buffer_pool_config_set_params (config,
caps, self->buffer_size, min_buffers, max_buffers);
@ -365,84 +329,172 @@ wrong_caps:
"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
return FALSE;
}
wrong_allocator:
{
GST_WARNING_OBJECT (pool, "Incorrect allocator type for this pool");
return FALSE;
}
}
static GstFlowReturn
gst_d3d11_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
GstBufferPoolAcquireParams * params)
gst_d3d11_buffer_pool_fill_buffer (GstD3D11BufferPool * self, GstBuffer * buf)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
GstMemory *mem;
GstBuffer *buf;
GstD3D11AllocationParams *d3d11_params = priv->d3d11_params;
GstVideoInfo *info = &d3d11_params->info;
GstFlowReturn ret = GST_FLOW_OK;
gint i;
buf = gst_buffer_new ();
for (i = 0; i < G_N_ELEMENTS (priv->alloc); i++) {
GstMemory *mem = NULL;
GstD3D11PoolAllocator *alloc = GST_D3D11_POOL_ALLOCATOR (priv->alloc[i]);
if (d3d11_params->d3d11_format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
mem = gst_d3d11_allocator_alloc (priv->allocator, &d3d11_params->desc[i],
d3d11_params->flags, priv->size[i]);
if (!mem)
goto error;
if (!alloc)
break;
gst_buffer_append_memory (buf, mem);
ret = gst_d3d11_pool_allocator_acquire_memory (alloc, &mem);
if (ret != GST_FLOW_OK) {
GST_WARNING_OBJECT (self, "Failed to acquire memory, ret %s",
gst_flow_get_name (ret));
return ret;
}
} else {
mem = gst_d3d11_allocator_alloc (priv->allocator, &d3d11_params->desc[0],
d3d11_params->flags, priv->size[0]);
if (!mem)
goto error;
gst_buffer_append_memory (buf, mem);
}
if (priv->add_videometa) {
GST_DEBUG_OBJECT (self, "adding GstVideoMeta");
gst_buffer_add_video_meta_full (buf, 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),
priv->offset, priv->stride);
return GST_FLOW_OK;
}
static GstFlowReturn
gst_d3d11_buffer_pool_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
GstBufferPoolAcquireParams * params)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
GstD3D11AllocationParams *d3d11_params = priv->d3d11_params;
GstVideoInfo *info = &d3d11_params->info;
GstBuffer *buf;
GstFlowReturn ret = GST_FLOW_OK;
buf = gst_buffer_new ();
/* For texture-array case, we release memory in reset_buffer() so that it can
* be returned to allocator. So our acquire_buffer() method is expecting
* empty buffer in that case. Don't fill memory here for non-texture-array */
if (!priv->texture_array_pool) {
ret = gst_d3d11_buffer_pool_fill_buffer (self, buf);
if (ret != GST_FLOW_OK) {
gst_buffer_unref (buf);
return ret;
}
}
gst_buffer_add_video_meta_full (buf, 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),
priv->offset, priv->stride);
*buffer = buf;
return GST_FLOW_OK;
}
error:
gst_buffer_unref (buf);
static GstFlowReturn
gst_d3d11_buffer_pool_acquire_buffer (GstBufferPool * pool,
GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
GstFlowReturn ret;
GST_ERROR_OBJECT (self, "cannot create texture memory");
ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (pool,
buffer, params);
return GST_FLOW_ERROR;
if (ret != GST_FLOW_OK)
return ret;
/* Don't need special handling for non-texture-array case */
if (!priv->texture_array_pool)
return ret;
/* Baseclass will hold empty buffer in this case, fill GstMemory */
g_assert (gst_buffer_n_memory (*buffer) == 0);
return gst_d3d11_buffer_pool_fill_buffer (self, *buffer);
}
static void
gst_d3d11_buffer_pool_flush_start (GstBufferPool * pool)
gst_d3d11_buffer_pool_reset_buffer (GstBufferPool * pool, GstBuffer * buffer)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
if (priv->allocator)
gst_d3d11_allocator_set_flushing (priv->allocator, TRUE);
/* if we are using texture array, return memory to allocator, so that
* memory pool allocator can wake up if it's waiting for available memory */
if (priv->texture_array_pool) {
GST_LOG_OBJECT (self, "Returning memory to allocator");
gst_buffer_remove_all_memory (buffer);
}
GST_BUFFER_POOL_CLASS (parent_class)->reset_buffer (pool, buffer);
GST_BUFFER_FLAGS (buffer) = 0;
}
static void
gst_d3d11_buffer_pool_flush_stop (GstBufferPool * pool)
static gboolean
gst_d3d11_buffer_pool_start (GstBufferPool * pool)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
guint i;
gboolean ret;
if (priv->allocator)
gst_d3d11_allocator_set_flushing (priv->allocator, FALSE);
GST_DEBUG_OBJECT (self, "Start");
for (i = 0; i < G_N_ELEMENTS (priv->alloc); i++) {
GstD3D11Allocator *alloc = priv->alloc[i];
if (!alloc)
break;
if (!gst_d3d11_allocator_set_active (alloc, TRUE)) {
GST_ERROR_OBJECT (self, "Failed to activate allocator");
return FALSE;
}
}
ret = GST_BUFFER_POOL_CLASS (parent_class)->start (pool);
if (!ret) {
GST_ERROR_OBJECT (self, "Failed to start");
for (i = 0; i < G_N_ELEMENTS (priv->alloc); i++) {
GstD3D11Allocator *alloc = priv->alloc[i];
if (!alloc)
break;
gst_d3d11_allocator_set_active (alloc, FALSE);
}
return FALSE;
}
return TRUE;
}
static gboolean
gst_d3d11_buffer_pool_stop (GstBufferPool * pool)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
guint i;
GST_DEBUG_OBJECT (self, "Stop");
for (i = 0; i < G_N_ELEMENTS (priv->alloc); i++) {
GstD3D11Allocator *alloc = priv->alloc[i];
if (!alloc)
break;
if (!gst_d3d11_allocator_set_active (alloc, FALSE)) {
GST_ERROR_OBJECT (self, "Failed to deactivate allocator");
return FALSE;
}
}
return GST_BUFFER_POOL_CLASS (parent_class)->stop (pool);
}
/**
@ -457,15 +509,13 @@ GstBufferPool *
gst_d3d11_buffer_pool_new (GstD3D11Device * device)
{
GstD3D11BufferPool *pool;
GstD3D11Allocator *alloc;
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
pool = g_object_new (GST_TYPE_D3D11_BUFFER_POOL, NULL);
alloc = gst_d3d11_allocator_new (device);
gst_object_ref_sink (pool);
pool->priv->device = gst_object_ref (device);
pool->priv->allocator = alloc;
pool->device = gst_object_ref (device);
return GST_BUFFER_POOL_CAST (pool);
}

View file

@ -39,6 +39,8 @@ struct _GstD3D11BufferPool
{
GstBufferPool parent;
GstD3D11Device *device;
/* re-calculated buffer size based on d3d11 pitch and stride */
guint buffer_size;

View file

@ -26,6 +26,7 @@
#include "gstd3d11utils.h"
#include "gstd3d11format.h"
#include "gstd3d11_private.h"
#include "gstd3d11memory.h"
#include <gmodule.h>
#include <windows.h>
@ -165,7 +166,10 @@ gst_d3d11_device_enable_d3d11_debug (void)
g_once_init_leave (&_init, 1);
}
return ! !d3d11_debug_module;
if (d3d11_debug_module)
return TRUE;
return FALSE;
}
static inline GstDebugLevel
@ -257,7 +261,8 @@ gst_d3d11_device_enable_dxgi_debug (void)
if (dxgi_debug_module)
g_module_symbol (dxgi_debug_module,
"DXGIGetDebugInterface", (gpointer *) & GstDXGIGetDebugInterface);
ret = ! !GstDXGIGetDebugInterface;
if (GstDXGIGetDebugInterface)
ret = TRUE;
#elif (GST_D3D11_DXGI_HEADER_VERSION >= 3)
ret = TRUE;
#endif
@ -402,6 +407,8 @@ gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
g_param_spec_int64 ("adapter-luid", "Adapter LUID",
"DXGI Adapter LUID (Locally Unique Identifier) of created device",
0, G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
gst_d3d11_memory_init_once ();
}
static void

File diff suppressed because it is too large Load diff

View file

@ -30,14 +30,35 @@
G_BEGIN_DECLS
#define GST_TYPE_D3D11_ALLOCATION_PARAMS (gst_d3d11_allocation_params_get_type())
#define GST_TYPE_D3D11_MEMORY (gst_d3d11_memory_get_type())
#define GST_D3D11_MEMORY_CAST(obj) ((GstD3D11Memory *)obj)
#define GST_TYPE_D3D11_ALLOCATOR (gst_d3d11_allocator_get_type())
#define GST_D3D11_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_D3D11_ALLOCATOR, GstD3D11Allocator))
#define GST_D3D11_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS((klass), GST_TYPE_D3D11_ALLOCATOR, GstD3D11AllocatorClass))
#define GST_D3D11_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_D3D11_ALLOCATOR, GstD3D11AllocatorClass))
#define GST_IS_D3D11_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_D3D11_ALLOCATOR))
#define GST_IS_D3D11_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_D3D11_ALLOCATOR))
#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)
#define GST_TYPE_D3D11_POOL_ALLOCATOR (gst_d3d11_pool_allocator_get_type())
#define GST_D3D11_POOL_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_D3D11_POOL_ALLOCATOR, GstD3D11PoolAllocator))
#define GST_D3D11_POOL_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_D3D11_POOL_ALLOCATOR, GstD3D11PoolAllocatorClass))
#define GST_IS_D3D11_POOL_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_D3D11_POOL_ALLOCATOR))
#define GST_IS_D3D11_POOL_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_D3D11_POOL_ALLOCATOR))
#define GST_D3D11_POOL_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_D3D11_POOL_ALLOCATOR, GstD3D11PoolAllocatorClass))
#define GST_D3D11_POOL_ALLOCATOR_CAST(obj) ((GstD3D11PoolAllocator *)obj)
/**
* GST_D3D11_MEMORY_NAME:
*
* The name of the Direct3D11 memory
*
* Since: 1.20
*/
#define GST_D3D11_MEMORY_NAME "D3D11Memory"
/**
* GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY:
*
@ -100,11 +121,30 @@ struct _GstD3D11AllocationParams
gpointer _gst_reserved[GST_PADDING_LARGE];
};
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,
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);
struct _GstD3D11Memory
{
GstMemory mem;
/*< public > */
/*< public >*/
GstD3D11Device *device;
/*< private >*/
@ -112,76 +152,26 @@ struct _GstD3D11Memory
gpointer _gst_reserved[GST_PADDING];
};
struct _GstD3D11Allocator
{
GstAllocator parent;
GstD3D11Device *device;
/*< private >*/
GstD3D11AllocatorPrivate *priv;
gpointer _gst_reserved[GST_PADDING];
};
struct _GstD3D11AllocatorClass
{
GstAllocatorClass allocator_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GST_D3D11_API
GType gst_d3d11_memory_get_type (void);
GST_D3D11_API
GType gst_d3d11_allocation_params_get_type (void);
void gst_d3d11_memory_init_once (void);
GST_D3D11_API
GstD3D11AllocationParams * gst_d3d11_allocation_params_new (GstD3D11Device * device,
GstVideoInfo * info,
GstD3D11AllocationFlags flags,
guint bind_flags);
gboolean gst_is_d3d11_memory (GstMemory * mem);
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);
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
gboolean gst_d3d11_memory_get_texture_stride (GstD3D11Memory * mem,
guint * stride);
GST_D3D11_API
guint gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem);
@ -214,6 +204,69 @@ ID3D11VideoProcessorOutputView * gst_d3d11_memory_get_processor_output_view (Gs
ID3D11VideoDevice * video_device,
ID3D11VideoProcessorEnumerator * enumerator);
struct _GstD3D11Allocator
{
GstAllocator allocator;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstD3D11AllocatorClass
{
GstAllocatorClass allocator_class;
gboolean (*set_actvie) (GstD3D11Allocator * allocator,
gboolean active);
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE];
};
GST_D3D11_API
GType gst_d3d11_allocator_get_type (void);
GST_D3D11_API
GstMemory * gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
GstD3D11Device * device,
const D3D11_TEXTURE2D_DESC * desc);
GST_D3D11_API
gboolean gst_d3d11_allocator_set_active (GstD3D11Allocator * allocator,
gboolean active);
struct _GstD3D11PoolAllocator
{
GstD3D11Allocator allocator;
/*< public >*/
GstD3D11Device *device;
/*< private >*/
GstD3D11PoolAllocatorPrivate *priv;
gpointer _gst_reserved[GST_PADDING];
};
struct _GstD3D11PoolAllocatorClass
{
GstD3D11AllocatorClass allocator_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GST_D3D11_API
GType gst_d3d11_pool_allocator_get_type (void);
GST_D3D11_API
GstD3D11PoolAllocator * gst_d3d11_pool_allocator_new (GstD3D11Device * device,
const D3D11_TEXTURE2D_DESC * desc);
GST_D3D11_API
GstFlowReturn gst_d3d11_pool_allocator_acquire_memory (GstD3D11PoolAllocator * allocator,
GstMemory ** memory);
G_END_DECLS
#endif /* __GST_D3D11_MEMORY_H__ */

View file

@ -1531,7 +1531,10 @@ gst_d3d11_compositor_release_pad (GstElement * element, GstPad * pad)
GST_OBJECT_NAME (pad));
gst_clear_buffer (&cpad->fallback_buf);
gst_clear_object (&cpad->fallback_pool);
if (cpad->fallback_pool) {
gst_buffer_pool_set_active (cpad->fallback_pool, FALSE);
gst_clear_object (&cpad->fallback_pool);
}
g_clear_pointer (&cpad->convert, gst_d3d11_converter_free);
GST_D3D11_CLEAR_COM (cpad->blend);

View file

@ -270,7 +270,10 @@ gst_d3d11_decoder_get_property (GObject * object, guint prop_id,
static void
gst_d3d11_decoder_clear_resource (GstD3D11Decoder * self)
{
gst_clear_object (&self->internal_pool);
if (self->internal_pool) {
gst_buffer_pool_set_active (self->internal_pool, FALSE);
gst_clear_object (&self->internal_pool);
}
GST_D3D11_CLEAR_COM (self->decoder_handle);
GST_D3D11_CLEAR_COM (self->staging);
@ -381,7 +384,10 @@ gst_d3d11_decoder_prepare_output_view_pool (GstD3D11Decoder * self)
GstVideoInfo *info = &self->info;
guint pool_size;
gst_clear_object (&self->internal_pool);
if (self->internal_pool) {
gst_buffer_pool_set_active (self->internal_pool, FALSE);
gst_clear_object (&self->internal_pool);
}
if (!self->use_array_of_texture) {
alloc_flags = GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY;

View file

@ -571,78 +571,20 @@ gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
}
#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)
static void
fill_staging_desc (const D3D11_TEXTURE2D_DESC * ref,
D3D11_TEXTURE2D_DESC * staging)
{
GstBuffer *buffer;
guint i;
gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
GstMemory *mem;
memset (staging, 0, sizeof (D3D11_TEXTURE2D_DESC));
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],
(GstD3D11AllocationFlags) 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],
(GstD3D11AllocationFlags) 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;
staging->Width = ref->Width;
staging->Height = ref->Height;
staging->MipLevels = 1;
staging->Format = ref->Format;
staging->SampleDesc.Count = 1;
staging->ArraySize = 1;
staging->Usage = D3D11_USAGE_STAGING;
staging->CPUAccessFlags = (D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
}
GstBuffer *
@ -651,11 +593,14 @@ gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
{
GstD3D11Memory *dmem;
GstD3D11Device *device;
GstD3D11AllocationParams *params = NULL;
GstD3D11Allocator *alloc = NULL;
GstBuffer *staging_buffer = NULL;
D3D11_TEXTURE2D_DESC *desc;
gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
guint i;
gsize size = 0;
const GstD3D11Format *format;
D3D11_TEXTURE2D_DESC desc;
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
@ -669,54 +614,73 @@ gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
device = dmem->device;
params = gst_d3d11_allocation_params_new (device, (GstVideoInfo *) info,
(GstD3D11AllocationFlags) 0, 0);
if (!params) {
GST_WARNING ("Couldn't create alloc params");
goto done;
format = gst_d3d11_device_format_from_gst (device,
GST_VIDEO_INFO_FORMAT (info));
if (!format) {
GST_ERROR ("Unknown d3d11 format");
return NULL;
}
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);
alloc = (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
if (!alloc) {
GST_WARNING ("Couldn't create allocator");
goto done;
GST_ERROR ("D3D11 allocator is not available");
return NULL;
}
staging_buffer = gst_d3d11_allocate_staging_buffer (alloc,
info, params->d3d11_format, params->desc, add_videometa);
staging_buffer = gst_buffer_new ();
for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
D3D11_TEXTURE2D_DESC staging_desc;
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
GstD3D11Memory *new_mem;
if (!staging_buffer)
GST_WARNING ("Couldn't allocate staging buffer");
guint cur_stride = 0;
done:
if (params)
gst_d3d11_allocation_params_free (params);
gst_d3d11_memory_get_texture_desc (mem, &desc);
fill_staging_desc (&desc, &staging_desc);
new_mem = (GstD3D11Memory *)
gst_d3d11_allocator_alloc (alloc, mem->device, &staging_desc);
if (!new_mem) {
GST_ERROR ("Failed to allocate memory");
goto error;
}
if (!gst_d3d11_memory_get_texture_stride (new_mem, &cur_stride) ||
cur_stride < staging_desc.Width) {
GST_ERROR ("Failed to calculate memory size");
gst_memory_unref (GST_MEMORY_CAST (mem));
goto error;
}
offset[i] = size;
stride[i] = cur_stride;
size += GST_MEMORY_CAST (new_mem)->size;
gst_buffer_append_memory (staging_buffer, GST_MEMORY_CAST (new_mem));
}
/* single texture semi-planar formats */
if (format->dxgi_format != DXGI_FORMAT_UNKNOWN &&
GST_VIDEO_INFO_N_PLANES (info) == 2) {
stride[1] = stride[0];
offset[1] = stride[0] * desc.Height;
}
gst_buffer_add_video_meta_full (staging_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);
if (alloc)
gst_object_unref (alloc);
return staging_buffer;
error:
gst_clear_buffer (&staging_buffer);
gst_clear_object (&alloc);
return NULL;
}
static gboolean

View file

@ -77,12 +77,6 @@ const GstDxgiColorSpace * gst_d3d11_find_swap_chain_color_space (GstVideoInfo *
gboolean use_hdr10);
#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 * gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
const GstVideoInfo * info,
gboolean add_videometa);