mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 13:11:06 +00:00
va: allocator: dmabuf: Use GstVaSurfaceCopy, if possible.
If dmabuf-based buffer to copy contains only one memory, and there are memories available in the allocator's pool, it's possible a fast memory copy using GstVaSurfaceCopy, regardless the drm modifier. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1023>
This commit is contained in:
parent
cf751d54a9
commit
35575e7b11
1 changed files with 91 additions and 2 deletions
|
@ -244,10 +244,13 @@ struct _GstVaDmabufAllocator
|
||||||
GstVaDisplay *display;
|
GstVaDisplay *display;
|
||||||
|
|
||||||
GstMemoryMapFunction parent_map;
|
GstMemoryMapFunction parent_map;
|
||||||
|
GstMemoryCopyFunction parent_copy;
|
||||||
|
|
||||||
GstVideoInfo info;
|
GstVideoInfo info;
|
||||||
guint usage_hint;
|
guint usage_hint;
|
||||||
|
|
||||||
|
GstVaSurfaceCopy *copy;
|
||||||
|
|
||||||
GstVaMemoryPool pool;
|
GstVaMemoryPool pool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,6 +258,84 @@ struct _GstVaDmabufAllocator
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstVaDmabufAllocator, gst_va_dmabuf_allocator,
|
G_DEFINE_TYPE_WITH_CODE (GstVaDmabufAllocator, gst_va_dmabuf_allocator,
|
||||||
GST_TYPE_DMABUF_ALLOCATOR, _init_debug_category ());
|
GST_TYPE_DMABUF_ALLOCATOR, _init_debug_category ());
|
||||||
|
|
||||||
|
/* If a buffer contains multiple memories (dmabuf objects) its very
|
||||||
|
* difficult to provide a realiable way to fast-copy single memories:
|
||||||
|
* While VA API sees surfaces with dependant dmabufs, GStreamer only
|
||||||
|
* copies dmabufs in isolation; trying to solve it while keeping a
|
||||||
|
* reference of the copied buffer and dmabuf index is very fragile. */
|
||||||
|
static GstMemory *
|
||||||
|
gst_va_dmabuf_mem_copy (GstMemory * gmem, gssize offset, gssize size)
|
||||||
|
{
|
||||||
|
GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (gmem->allocator);
|
||||||
|
GstVaBufferSurface *buf;
|
||||||
|
guint64 *drm_mod;
|
||||||
|
gsize mem_size;
|
||||||
|
|
||||||
|
buf = gst_mini_object_get_qdata (GST_MINI_OBJECT (gmem),
|
||||||
|
gst_va_buffer_surface_quark ());
|
||||||
|
|
||||||
|
drm_mod = gst_mini_object_get_qdata (GST_MINI_OBJECT (gmem),
|
||||||
|
gst_va_drm_mod_quark ());
|
||||||
|
|
||||||
|
/* 0 is DRM_FORMAT_MOD_LINEAR, we do not include its header now. */
|
||||||
|
if (buf->n_mems > 1 && *drm_mod != 0) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to copy multi-dmabuf because non-linear "
|
||||||
|
"modifier: %#lx.", *drm_mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if it's full memory copy */
|
||||||
|
mem_size = gst_memory_get_sizes (gmem, NULL, NULL);
|
||||||
|
|
||||||
|
if (size == -1)
|
||||||
|
size = mem_size > offset ? mem_size - offset : 0;
|
||||||
|
|
||||||
|
/* @XXX: if one-memory buffer it's possible to copy */
|
||||||
|
if (offset == 0 && size == mem_size && buf->n_mems == 1) {
|
||||||
|
GstVaBufferSurface *buf_copy;
|
||||||
|
GstMemory *copy;
|
||||||
|
|
||||||
|
GST_VA_MEMORY_POOL_LOCK (&self->pool);
|
||||||
|
copy = gst_va_memory_pool_pop (&self->pool);
|
||||||
|
GST_VA_MEMORY_POOL_UNLOCK (&self->pool);
|
||||||
|
|
||||||
|
if (!copy) {
|
||||||
|
GstBuffer *buffer = gst_buffer_new ();
|
||||||
|
if (!gst_va_dmabuf_allocator_setup_buffer (gmem->allocator, buffer)) {
|
||||||
|
GST_WARNING_OBJECT (self, "Failed to create a new dmabuf memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy = gst_buffer_get_memory (buffer, 0);
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_copy = gst_mini_object_get_qdata (GST_MINI_OBJECT (copy),
|
||||||
|
gst_va_buffer_surface_quark ());
|
||||||
|
g_assert (buf_copy->n_mems == 1);
|
||||||
|
|
||||||
|
if (!self->copy)
|
||||||
|
self->copy = gst_va_surface_copy_new (self->display, &self->info);
|
||||||
|
if (self->copy && gst_va_surface_copy (self->copy, buf_copy->surface,
|
||||||
|
buf->surface))
|
||||||
|
return copy;
|
||||||
|
|
||||||
|
gst_memory_unref (copy);
|
||||||
|
|
||||||
|
/* try system memory */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*drm_mod != 0) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to copy dmabuf because non-linear "
|
||||||
|
"modifier: %#lx.", *drm_mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fallback to system memory */
|
||||||
|
return self->parent_copy (gmem, offset, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
gst_va_dmabuf_mem_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags)
|
gst_va_dmabuf_mem_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags)
|
||||||
{
|
{
|
||||||
|
@ -282,6 +363,7 @@ gst_va_dmabuf_allocator_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (object);
|
GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (object);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->copy, gst_va_surface_copy_free);
|
||||||
gst_va_memory_pool_finalize (&self->pool);
|
gst_va_memory_pool_finalize (&self->pool);
|
||||||
gst_clear_object (&self->display);
|
gst_clear_object (&self->display);
|
||||||
|
|
||||||
|
@ -314,9 +396,14 @@ gst_va_dmabuf_allocator_class_init (GstVaDmabufAllocatorClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_va_dmabuf_allocator_init (GstVaDmabufAllocator * self)
|
gst_va_dmabuf_allocator_init (GstVaDmabufAllocator * self)
|
||||||
{
|
{
|
||||||
|
GstAllocator *allocator = GST_ALLOCATOR (self);
|
||||||
|
|
||||||
|
self->parent_map = allocator->mem_map;
|
||||||
|
allocator->mem_map = gst_va_dmabuf_mem_map;
|
||||||
|
self->parent_copy = allocator->mem_copy;
|
||||||
|
allocator->mem_copy = gst_va_dmabuf_mem_copy;
|
||||||
|
|
||||||
gst_va_memory_pool_init (&self->pool);
|
gst_va_memory_pool_init (&self->pool);
|
||||||
self->parent_map = GST_ALLOCATOR (self)->mem_map;
|
|
||||||
GST_ALLOCATOR (self)->mem_map = gst_va_dmabuf_mem_map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GstAllocator *
|
GstAllocator *
|
||||||
|
@ -673,6 +760,8 @@ gst_va_dmabuf_allocator_set_format (GstAllocator * allocator,
|
||||||
self->usage_hint = usage_hint;
|
self->usage_hint = usage_hint;
|
||||||
self->info = *info;
|
self->info = *info;
|
||||||
|
|
||||||
|
g_clear_pointer (&self->copy, gst_va_surface_copy_free);
|
||||||
|
|
||||||
ret = gst_va_dmabuf_allocator_try (allocator);
|
ret = gst_va_dmabuf_allocator_try (allocator);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
Loading…
Reference in a new issue