diff --git a/sys/d3d11/gstd3d11_fwd.h b/sys/d3d11/gstd3d11_fwd.h index 5445355745..1f977ef432 100644 --- a/sys/d3d11/gstd3d11_fwd.h +++ b/sys/d3d11/gstd3d11_fwd.h @@ -63,6 +63,7 @@ typedef struct _GstD3D11AllocationParams GstD3D11AllocationParams; typedef struct _GstD3D11Memory GstD3D11Memory; typedef struct _GstD3D11Allocator GstD3D11Allocator; typedef struct _GstD3D11AllocatorClass GstD3D11AllocatorClass; +typedef struct _GstD3D11AllocatorPrivate GstD3D11AllocatorPrivate; typedef struct _GstD3D11BufferPool GstD3D11BufferPool; typedef struct _GstD3D11BufferPoolClass GstD3D11BufferPoolClass; diff --git a/sys/d3d11/gstd3d11bufferpool.c b/sys/d3d11/gstd3d11bufferpool.c index d844164397..1f415382e2 100644 --- a/sys/d3d11/gstd3d11bufferpool.c +++ b/sys/d3d11/gstd3d11bufferpool.c @@ -50,6 +50,8 @@ static gboolean gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config); static GstFlowReturn gst_d3d11_buffer_pool_alloc (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 void gst_d3d11_buffer_pool_class_init (GstD3D11BufferPoolClass * klass) @@ -62,6 +64,8 @@ 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; GST_DEBUG_CATEGORY_INIT (gst_d3d11_buffer_pool_debug, "d3d11bufferpool", 0, "d3d11bufferpool object"); @@ -311,6 +315,26 @@ error: return GST_FLOW_ERROR; } +static void +gst_d3d11_buffer_pool_flush_start (GstBufferPool * pool) +{ + GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool); + GstD3D11BufferPoolPrivate *priv = self->priv; + + if (priv->allocator) + gst_d3d11_allocator_set_flushing (priv->allocator, TRUE); +} + +static void +gst_d3d11_buffer_pool_flush_stop (GstBufferPool * pool) +{ + GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool); + GstD3D11BufferPoolPrivate *priv = self->priv; + + if (priv->allocator) + gst_d3d11_allocator_set_flushing (priv->allocator, FALSE); +} + GstBufferPool * gst_d3d11_buffer_pool_new (GstD3D11Device * device) { diff --git a/sys/d3d11/gstd3d11memory.c b/sys/d3d11/gstd3d11memory.c index 1b74ee61d2..79f39e6dc8 100644 --- a/sys/d3d11/gstd3d11memory.c +++ b/sys/d3d11/gstd3d11memory.c @@ -146,8 +146,21 @@ G_DEFINE_BOXED_TYPE_WITH_CODE (GstD3D11AllocationParams, (GBoxedFreeFunc) gst_d3d11_allocation_params_free, _init_alloc_params (g_define_type_id)); +struct _GstD3D11AllocatorPrivate +{ + /* parent textrure when array typed memory is used */ + ID3D11Texture2D *texture; + guint8 array_in_use[D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION]; + + GMutex lock; + GCond cond; + + gboolean flushing; +}; + #define gst_d3d11_allocator_parent_class parent_class -G_DEFINE_TYPE (GstD3D11Allocator, gst_d3d11_allocator, GST_TYPE_ALLOCATOR); +G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Allocator, + gst_d3d11_allocator, GST_TYPE_ALLOCATOR); static inline D3D11_MAP gst_map_flags_to_d3d11 (GstMapFlags flags) @@ -337,9 +350,16 @@ gst_d3d11_allocator_dummy_alloc (GstAllocator * allocator, gsize size, static void gst_d3d11_allocator_free (GstAllocator * allocator, GstMemory * mem) { + GstD3D11Allocator *self = GST_D3D11_ALLOCATOR (allocator); + GstD3D11AllocatorPrivate *priv = self->priv; GstD3D11Memory *dmem = (GstD3D11Memory *) mem; gint i; + g_mutex_lock (&priv->lock); + priv->array_in_use[dmem->subresource_index] = 0; + g_cond_broadcast (&priv->cond); + g_mutex_unlock (&priv->lock); + for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { if (dmem->render_target_view[i]) ID3D11RenderTargetView_Release (dmem->render_target_view[i]); @@ -366,10 +386,11 @@ static void gst_d3d11_allocator_dispose (GObject * object) { GstD3D11Allocator *alloc = GST_D3D11_ALLOCATOR (object); + GstD3D11AllocatorPrivate *priv = alloc->priv; - if (alloc->device && alloc->texture) { - gst_d3d11_device_release_texture (alloc->device, alloc->texture); - alloc->texture = NULL; + if (alloc->device && priv->texture) { + gst_d3d11_device_release_texture (alloc->device, priv->texture); + priv->texture = NULL; } gst_clear_object (&alloc->device); @@ -377,6 +398,18 @@ gst_d3d11_allocator_dispose (GObject * object) G_OBJECT_CLASS (parent_class)->dispose (object); } +static void +gst_d3d11_allocator_finalize (GObject * object) +{ + GstD3D11Allocator *alloc = GST_D3D11_ALLOCATOR (object); + GstD3D11AllocatorPrivate *priv = alloc->priv; + + g_mutex_clear (&priv->lock); + g_cond_clear (&priv->cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static void gst_d3d11_allocator_class_init (GstD3D11AllocatorClass * klass) { @@ -384,6 +417,7 @@ gst_d3d11_allocator_class_init (GstD3D11AllocatorClass * klass) GstAllocatorClass *allocator_class = GST_ALLOCATOR_CLASS (klass); gobject_class->dispose = gst_d3d11_allocator_dispose; + gobject_class->finalize = gst_d3d11_allocator_finalize; allocator_class->alloc = gst_d3d11_allocator_dummy_alloc; allocator_class->free = gst_d3d11_allocator_free; @@ -396,6 +430,7 @@ static void gst_d3d11_allocator_init (GstD3D11Allocator * allocator) { GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); + GstD3D11AllocatorPrivate *priv; alloc->mem_type = GST_D3D11_MEMORY_NAME; alloc->mem_map = gst_d3d11_memory_map; @@ -404,6 +439,12 @@ gst_d3d11_allocator_init (GstD3D11Allocator * allocator) /* fallback copy */ GST_OBJECT_FLAG_SET (alloc, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); + + priv = gst_d3d11_allocator_get_instance_private (allocator); + g_mutex_init (&priv->lock); + g_cond_init (&priv->cond); + + allocator->priv = priv; } GstD3D11Allocator * @@ -614,11 +655,13 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator, gsize *size; gboolean is_first = FALSE; guint index_to_use = 0; + GstD3D11AllocatorPrivate *priv; GstD3D11MemoryType type = GST_D3D11_MEMORY_TYPE_TEXTURE; g_return_val_if_fail (GST_IS_D3D11_ALLOCATOR (allocator), NULL); g_return_val_if_fail (params != NULL, NULL); + priv = allocator->priv; device = allocator->device; desc = ¶ms->desc[params->plane]; size = ¶ms->size[params->plane]; @@ -628,28 +671,44 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator, if ((params->flags & GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY)) { gint i; + + do_again: + g_mutex_lock (&priv->lock); + if (priv->flushing) { + GST_DEBUG_OBJECT (allocator, "we are flushing"); + g_mutex_unlock (&priv->lock); + + return NULL; + } + for (i = 0; i < desc->ArraySize; i++) { - if (allocator->array_in_use[i] == 0) { + if (priv->array_in_use[i] == 0) { index_to_use = i; break; } } if (i == desc->ArraySize) { - GST_ERROR_OBJECT (allocator, "All elements in array are used now"); - goto error; + GST_DEBUG_OBJECT (allocator, "All elements in array are used now"); + g_cond_wait (&priv->cond, &priv->lock); + g_mutex_unlock (&priv->lock); + goto do_again; } - if (!allocator->texture) { - allocator->texture = gst_d3d11_device_create_texture (device, desc, NULL); - if (!allocator->texture) { + priv->array_in_use[index_to_use] = 1; + + g_mutex_unlock (&priv->lock); + + if (!priv->texture) { + priv->texture = gst_d3d11_device_create_texture (device, desc, NULL); + if (!priv->texture) { GST_ERROR_OBJECT (allocator, "Couldn't create texture"); goto error; } } - ID3D11Texture2D_AddRef (allocator->texture); - texture = allocator->texture; + ID3D11Texture2D_AddRef (priv->texture); + texture = priv->texture; type = GST_D3D11_MEMORY_TYPE_ARRAY; } else { @@ -701,8 +760,6 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator, mem->device = gst_object_ref (device); mem->type = type; mem->subresource_index = index_to_use; - if (type == GST_D3D11_MEMORY_TYPE_ARRAY) - allocator->array_in_use[index_to_use] = 1; if (staging) GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); @@ -719,6 +776,22 @@ error: return NULL; } +void +gst_d3d11_allocator_set_flushing (GstD3D11Allocator * allocator, + gboolean flushing) +{ + GstD3D11AllocatorPrivate *priv; + + g_return_if_fail (GST_IS_D3D11_ALLOCATOR (allocator)); + + priv = allocator->priv; + + g_mutex_lock (&priv->lock); + priv->flushing = flushing; + g_cond_broadcast (&priv->cond); + g_mutex_unlock (&priv->lock); +} + gboolean gst_is_d3d11_memory (GstMemory * mem) { diff --git a/sys/d3d11/gstd3d11memory.h b/sys/d3d11/gstd3d11memory.h index e7dd0e7e20..f63618be89 100644 --- a/sys/d3d11/gstd3d11memory.h +++ b/sys/d3d11/gstd3d11memory.h @@ -140,11 +140,8 @@ struct _GstD3D11Allocator GstD3D11Device *device; - /* parent textrure when array typed memory is used */ - ID3D11Texture2D *texture; - guint8 array_in_use [D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION]; - /*< private >*/ + GstD3D11AllocatorPrivate *priv; gpointer _gst_reserved[GST_PADDING]; }; @@ -174,6 +171,9 @@ GstD3D11Allocator * gst_d3d11_allocator_new (GstD3D11Device *device); GstMemory * gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator, GstD3D11AllocationParams * params); +void gst_d3d11_allocator_set_flushing (GstD3D11Allocator * allocator, + gboolean flushing); + gboolean gst_is_d3d11_memory (GstMemory * mem); gboolean gst_d3d11_memory_ensure_shader_resource_view (GstD3D11Memory * mem);