diff --git a/sys/kms/gstkmsallocator.c b/sys/kms/gstkmsallocator.c index 4c6b0d9ae9..dd5f230d1c 100644 --- a/sys/kms/gstkmsallocator.c +++ b/sys/kms/gstkmsallocator.c @@ -27,6 +27,7 @@ #include "config.h" #endif +#include #include #include #include @@ -37,6 +38,8 @@ /* it needs to be below because is internal to libdrm */ #include +#include + #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) diff --git a/sys/kms/gstkmsallocator.h b/sys/kms/gstkmsallocator.h index d36e34951a..9d001266ba 100644 --- a/sys/kms/gstkmsallocator.h +++ b/sys/kms/gstkmsallocator.h @@ -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); diff --git a/sys/kms/gstkmsbufferpool.c b/sys/kms/gstkmsbufferpool.c index 57f032839d..7c02aa21f6 100644 --- a/sys/kms/gstkmsbufferpool.c +++ b/sys/kms/gstkmsbufferpool.c @@ -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); diff --git a/sys/kms/gstkmsbufferpool.h b/sys/kms/gstkmsbufferpool.h index 1ed9884ffa..33f3487ea8 100644 --- a/sys/kms/gstkmsbufferpool.h +++ b/sys/kms/gstkmsbufferpool.h @@ -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; diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c index 84e37c02d0..8c19f796e7 100644 --- a/sys/kms/gstkmssink.c +++ b/sys/kms/gstkmssink.c @@ -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 */