summaryrefslogtreecommitdiff
path: root/gst-libs/gst/d3d11/gstd3d11bufferpool.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst-libs/gst/d3d11/gstd3d11bufferpool.c')
-rw-r--r--gst-libs/gst/d3d11/gstd3d11bufferpool.c398
1 files changed, 224 insertions, 174 deletions
diff --git a/gst-libs/gst/d3d11/gstd3d11bufferpool.c b/gst-libs/gst/d3d11/gstd3d11bufferpool.c
index be0f675ae..f4b2874c7 100644
--- a/gst-libs/gst/d3d11/gstd3d11bufferpool.c
+++ b/gst-libs/gst/d3d11/gstd3d11bufferpool.c
@@ -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");
@@ -94,17 +98,28 @@ gst_d3d11_buffer_pool_init (GstD3D11BufferPool * 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_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);
- }
+ gst_d3d11_buffer_pool_clear_allocator (self);
- 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;
}
- }
-
- staging_buffer = allocate_staging_buffer (priv->allocator,
- &info, priv->d3d11_params->d3d11_format, priv->d3d11_params->desc, TRUE);
- if (!staging_buffer) {
- GST_ERROR_OBJECT (pool, "Couldn't allocated staging buffer");
- return FALSE;
+ priv->texture_array_pool = TRUE;
} else {
- GstVideoMeta *meta = gst_buffer_get_video_meta (staging_buffer);
+ priv->texture_array_pool = FALSE;
+ }
- if (!meta) {
- GST_ERROR_OBJECT (pool, "Buffer doesn't have video meta");
- gst_buffer_unref (staging_buffer);
+ 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 (desc[i].Format == DXGI_FORMAT_UNKNOWN)
+ break;
+
+ 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);
+ 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;
+ }
- priv->size[i] = gst_memory_get_sizes (mem, NULL, NULL);
+ 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;
}
- memcpy (priv->offset, meta->offset, sizeof (priv->offset));
- memcpy (priv->stride, meta->stride, sizeof (priv->stride));
+ priv->stride[i] = stride;
+ priv->offset[i] = offset;
+ offset += mem->size;
+
+ priv->alloc[i] = alloc;
+
+ gst_memory_unref (mem);
+ }
+
+ 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 = gst_buffer_get_size (staging_buffer);
- gst_buffer_unref (staging_buffer);
+ 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;
+}
+
+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;
-error:
- gst_buffer_unref (buf);
+ ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (pool,
+ buffer, params);
- GST_ERROR_OBJECT (self, "cannot create texture memory");
+ if (ret != GST_FLOW_OK)
+ return ret;
- return GST_FLOW_ERROR;
+ /* 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;
+
+ 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;
+ }
+ }
- if (priv->allocator)
- gst_d3d11_allocator_set_flushing (priv->allocator, 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);
}