mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
kms: Export DMABuf from Dumb buffer when possible
https://bugzilla.gnome.org/show_bug.cgi?id=787593
This commit is contained in:
parent
9d5a524547
commit
922031b0f9
5 changed files with 86 additions and 2 deletions
|
@ -27,6 +27,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -37,6 +38,8 @@
|
|||
/* it needs to be below because is internal to libdrm */
|
||||
#include <drm.h>
|
||||
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
|
||||
#include "gstkmsallocator.h"
|
||||
#include "gstkmsutils.h"
|
||||
|
||||
|
@ -58,6 +61,7 @@ struct _GstKMSAllocatorPrivate
|
|||
int fd;
|
||||
/* protected by GstKMSAllocator object lock */
|
||||
GList *mem_cache;
|
||||
GstAllocator *dmabuf_alloc;
|
||||
};
|
||||
|
||||
#define parent_class gst_kms_allocator_parent_class
|
||||
|
@ -297,6 +301,9 @@ gst_kms_allocator_finalize (GObject * obj)
|
|||
|
||||
gst_kms_allocator_clear_cache (GST_ALLOCATOR (alloc));
|
||||
|
||||
if (alloc->priv->dmabuf_alloc)
|
||||
gst_object_unref (alloc->priv->dmabuf_alloc);
|
||||
|
||||
if (check_fd (alloc))
|
||||
close (alloc->priv->fd);
|
||||
|
||||
|
@ -555,6 +562,48 @@ failed:
|
|||
}
|
||||
}
|
||||
|
||||
GstMemory *
|
||||
gst_kms_allocator_dmabuf_export (GstAllocator * allocator, GstMemory * _kmsmem)
|
||||
{
|
||||
GstKMSMemory *kmsmem = (GstKMSMemory *) _kmsmem;
|
||||
GstKMSAllocator *alloc = GST_KMS_ALLOCATOR (allocator);
|
||||
GstMemory *mem;
|
||||
gint ret;
|
||||
gint prime_fd;
|
||||
|
||||
/* We can only export DUMB buffers */
|
||||
g_return_val_if_fail (kmsmem->bo, NULL);
|
||||
|
||||
|
||||
ret = drmPrimeHandleToFD (alloc->priv->fd, kmsmem->bo->handle,
|
||||
DRM_CLOEXEC | DRM_RDWR, &prime_fd);
|
||||
if (ret)
|
||||
goto export_fd_failed;
|
||||
|
||||
if (G_UNLIKELY (alloc->priv->dmabuf_alloc == NULL))
|
||||
alloc->priv->dmabuf_alloc = gst_dmabuf_allocator_new ();
|
||||
|
||||
mem = gst_dmabuf_allocator_alloc (alloc->priv->dmabuf_alloc, prime_fd,
|
||||
gst_memory_get_sizes (_kmsmem, NULL, NULL));
|
||||
|
||||
/* Populate the cache so KMSSink can find the kmsmem back when it receives
|
||||
* one of these DMABuf. This call takes ownership of the kmsmem. */
|
||||
gst_kms_allocator_cache (allocator, mem, _kmsmem);
|
||||
|
||||
GST_DEBUG_OBJECT (alloc, "Exported bo handle %d as %d", kmsmem->bo->handle,
|
||||
prime_fd);
|
||||
|
||||
return mem;
|
||||
|
||||
/* ERRORS */
|
||||
export_fd_failed:
|
||||
{
|
||||
GST_ERROR_OBJECT (alloc, "Failed to export bo handle %d: %s (%d)",
|
||||
kmsmem->bo->handle, g_strerror (errno), ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME, using gdata for caching on upstream memory is not tee safe */
|
||||
GstMemory *
|
||||
gst_kms_allocator_get_cached (GstMemory * mem)
|
||||
|
|
|
@ -86,6 +86,9 @@ GstKMSMemory* gst_kms_allocator_dmabuf_import (GstAllocator *allocator,
|
|||
gsize offsets[GST_VIDEO_MAX_PLANES],
|
||||
GstVideoInfo *vinfo);
|
||||
|
||||
GstMemory* gst_kms_allocator_dmabuf_export (GstAllocator *allocator,
|
||||
GstMemory *kmsmem);
|
||||
|
||||
GstMemory * gst_kms_allocator_get_cached (GstMemory * mem);
|
||||
|
||||
void gst_kms_allocator_clear_cache (GstAllocator * allocator);
|
||||
|
|
|
@ -40,6 +40,7 @@ struct _GstKMSBufferPoolPrivate
|
|||
GstVideoInfo vinfo;
|
||||
GstAllocator *allocator;
|
||||
gboolean add_videometa;
|
||||
gboolean has_prime_export;
|
||||
};
|
||||
|
||||
#define parent_class gst_kms_buffer_pool_parent_class
|
||||
|
@ -52,7 +53,9 @@ static const gchar **
|
|||
gst_kms_buffer_pool_get_options (GstBufferPool * pool)
|
||||
{
|
||||
static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META,
|
||||
GST_BUFFER_POOL_OPTION_KMS_BUFFER, NULL
|
||||
GST_BUFFER_POOL_OPTION_KMS_BUFFER,
|
||||
GST_BUFFER_POOL_OPTION_KMS_PRIME_EXPORT,
|
||||
NULL
|
||||
};
|
||||
return options;
|
||||
}
|
||||
|
@ -97,6 +100,8 @@ gst_kms_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
|
|||
/* enable metadata based on config of the pool */
|
||||
priv->add_videometa = gst_buffer_pool_config_has_option (config,
|
||||
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
priv->has_prime_export = gst_buffer_pool_config_has_option (config,
|
||||
GST_BUFFER_POOL_OPTION_KMS_PRIME_EXPORT);
|
||||
|
||||
return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
|
||||
|
||||
|
@ -141,6 +146,16 @@ gst_kms_buffer_pool_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
|
|||
if (!mem)
|
||||
goto no_memory;
|
||||
|
||||
if (vpool->priv->has_prime_export) {
|
||||
GstMemory *dmabufmem;
|
||||
|
||||
dmabufmem = gst_kms_allocator_dmabuf_export (priv->allocator, mem);
|
||||
if (dmabufmem)
|
||||
mem = dmabufmem;
|
||||
else
|
||||
GST_WARNING_OBJECT (pool, "Failed to export DMABuf from Dumb buffer.");
|
||||
}
|
||||
|
||||
*buffer = gst_buffer_new ();
|
||||
gst_buffer_append_memory (*buffer, mem);
|
||||
|
||||
|
|
|
@ -37,10 +37,19 @@ G_BEGIN_DECLS
|
|||
* GST_BUFFER_POOL_OPTION_KMS_BUFFER:
|
||||
*
|
||||
* An option that can be activated on buffer pool to request KMS
|
||||
* buffers.
|
||||
* buffers. NOT IMPLEMENTED
|
||||
*/
|
||||
#define GST_BUFFER_POOL_OPTION_KMS_BUFFER "GstBufferPoolOptionKMSBuffer"
|
||||
|
||||
/**
|
||||
* GST_BUFFER_POOL_OPTION_KMS_PRIME_EXPORT:
|
||||
*
|
||||
* An option that can be activated on buffer pool to request DMABuf
|
||||
* buffers. Callers are responsible to check if this is supported. Dumb buffers
|
||||
* will be returned if not supported.
|
||||
*/
|
||||
#define GST_BUFFER_POOL_OPTION_KMS_PRIME_EXPORT "GstBufferPoolOptionKMSPrimeExport"
|
||||
|
||||
/* video bufferpool */
|
||||
typedef struct _GstKMSBufferPool GstKMSBufferPool;
|
||||
typedef struct _GstKMSBufferPoolClass GstKMSBufferPoolClass;
|
||||
|
|
|
@ -932,6 +932,14 @@ gst_kms_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
|||
pool = gst_kms_sink_create_pool (self, caps, size, 0);
|
||||
if (!pool)
|
||||
goto no_pool;
|
||||
|
||||
/* Only export for pool used upstream */
|
||||
if (self->has_prime_export) {
|
||||
GstStructure *config = gst_buffer_pool_get_config (pool);
|
||||
gst_buffer_pool_config_add_option (config,
|
||||
GST_BUFFER_POOL_OPTION_KMS_PRIME_EXPORT);
|
||||
gst_buffer_pool_set_config (pool, config);
|
||||
}
|
||||
}
|
||||
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
|
|
Loading…
Reference in a new issue