added my Recipes
This commit is contained in:
@@ -0,0 +1,954 @@
|
||||
From 3923d3d4c64870a02f6f219c3444fdcb196dca23 Mon Sep 17 00:00:00 2001
|
||||
From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
||||
Date: Wed, 8 Feb 2023 16:50:10 -0500
|
||||
Subject: [PATCH] allocators: Add a DRM Dumb Allocator
|
||||
|
||||
This allow allocating memory from any DRM driver that supports this
|
||||
method. It additionally allow exporting DMABuf. This allocator depends
|
||||
on libdrm and will be stubbed if the dependency is missing. This is derived
|
||||
from kmssink dumb allocator.
|
||||
|
||||
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3801>
|
||||
---
|
||||
gst-libs/gst/allocators/allocators.h | 1 +
|
||||
gst-libs/gst/allocators/gstdrmdumb.c | 755 +++++++++++++++++++++++++++
|
||||
gst-libs/gst/allocators/gstdrmdumb.h | 88 ++++
|
||||
gst-libs/gst/allocators/meson.build | 7 +-
|
||||
meson.build | 7 +
|
||||
meson_options.txt | 1 +
|
||||
6 files changed, 856 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gst-libs/gst/allocators/gstdrmdumb.c
|
||||
create mode 100644 gst-libs/gst/allocators/gstdrmdumb.h
|
||||
|
||||
diff --git a/gst-libs/gst/allocators/allocators.h b/gst-libs/gst/allocators/allocators.h
|
||||
index b616aa2..65e7e81 100644
|
||||
--- a/gst-libs/gst/allocators/allocators.h
|
||||
+++ b/gst-libs/gst/allocators/allocators.h
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
#include <gst/allocators/gstfdmemory.h>
|
||||
#include <gst/allocators/gstphysmemory.h>
|
||||
+#include <gst/allocators/gstdrmdumb.h>
|
||||
|
||||
#endif /* __GST_ALLOCATORS_H__ */
|
||||
|
||||
diff --git a/gst-libs/gst/allocators/gstdrmdumb.c b/gst-libs/gst/allocators/gstdrmdumb.c
|
||||
new file mode 100644
|
||||
index 0000000..c5c4834
|
||||
--- /dev/null
|
||||
+++ b/gst-libs/gst/allocators/gstdrmdumb.c
|
||||
@@ -0,0 +1,755 @@
|
||||
+/* GStreamer
|
||||
+ *
|
||||
+ * Copyright (C) 2023 Collabora
|
||||
+ * Copyright (C) 2016 Igalia
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
|
||||
+ * Javier Martin <javiermartin@by.com.es>
|
||||
+ * Colin Kinloch <colin.kinloch@collabora.com>
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Library General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Library General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Library General Public
|
||||
+ * License along with this library; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
+ * Boston, MA 02110-1301, USA.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include "config.h"
|
||||
+#endif
|
||||
+
|
||||
+#include "gstdrmdumb.h"
|
||||
+#include "gstdmabuf.h"
|
||||
+
|
||||
+/**
|
||||
+ * SECTION:gstdrmdumb
|
||||
+ * @title: GstDRMDumbAllocator
|
||||
+ * @short_description: Memory wrapper for Linux DRM Dumb memory
|
||||
+ * @see_also: #GstMemory
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+#include <fcntl.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include <drm.h>
|
||||
+#include <drm_fourcc.h>
|
||||
+#include <xf86drm.h>
|
||||
+#endif
|
||||
+
|
||||
+#define GST_CAT_DEFAULT drmdumballocator_debug
|
||||
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
+
|
||||
+#define GST_DRM_DUMB_MEMORY_TYPE "DRMDumbMemory"
|
||||
+
|
||||
+typedef struct _GstDRMDumbMemory GstDRMDumbMemory;
|
||||
+struct _GstDRMDumbMemory
|
||||
+{
|
||||
+ GstMemory parent;
|
||||
+
|
||||
+ gpointer ptr;
|
||||
+ gsize size;
|
||||
+ guint32 handle;
|
||||
+ guint refs;
|
||||
+};
|
||||
+
|
||||
+struct _GstDRMDumbAllocator
|
||||
+{
|
||||
+ GstAllocator parent;
|
||||
+
|
||||
+ gint drm_fd;
|
||||
+ gchar *drm_device_path;
|
||||
+
|
||||
+ /* protected by GstDRMDumbAllocator object lock */
|
||||
+ GstAllocator *dmabuf_alloc;
|
||||
+};
|
||||
+
|
||||
+#define parent_class gst_drm_dumb_allocator_parent_class
|
||||
+G_DEFINE_TYPE_WITH_CODE (GstDRMDumbAllocator, gst_drm_dumb_allocator,
|
||||
+ GST_TYPE_ALLOCATOR,
|
||||
+ GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "drmdumballocator", 0,
|
||||
+ "DRM dumb buffer allocator"));
|
||||
+enum
|
||||
+{
|
||||
+ PROP_DRM_FD = 1,
|
||||
+ PROP_DRM_DEVICE_PATH,
|
||||
+ PROP_N,
|
||||
+};
|
||||
+
|
||||
+static GParamSpec *g_props[PROP_N] = { NULL, };
|
||||
+
|
||||
+/**
|
||||
+ * gst_is_drm_dumb_memory:
|
||||
+ * @mem: the memory to be checked
|
||||
+ *
|
||||
+ * Returns: %TRUE if @mem is DRM Dumb memory, otherwise %FALSE
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+gboolean
|
||||
+gst_is_drm_dumb_memory (GstMemory * mem)
|
||||
+{
|
||||
+ return gst_memory_is_type (mem, GST_DRM_DUMB_MEMORY_TYPE);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * gst_drm_dumb_memory_get_handle:
|
||||
+ * @mem: the memory to get the handle from
|
||||
+ *
|
||||
+ * Return the DRM buffer object handle associated with @mem.
|
||||
+ *
|
||||
+ * Returns: the DRM buffer object handle associated with the memory, or 0.
|
||||
+ * The handle is still owned by the GstMemory and cannot be used
|
||||
+ * beyond the lifetime of this GstMemory unless it is being passed
|
||||
+ * to DRM driver, which does handle a refcount internally.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+guint32
|
||||
+gst_drm_dumb_memory_get_handle (GstMemory * mem)
|
||||
+{
|
||||
+ if (!gst_is_drm_dumb_memory (mem))
|
||||
+ return 0;
|
||||
+
|
||||
+ return ((GstDRMDumbMemory *) mem)->handle;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * gst_drm_dumb_memory_export_dmabuf:
|
||||
+ * @mem: the memory to export from
|
||||
+ *
|
||||
+ * Exports a DMABuf from the DRM Bumb buffer object. One can check if this
|
||||
+ * feature is supported using gst_drm_dumb_allocator_has_prime_export();
|
||||
+ *
|
||||
+ * Returns: a #GstMemory from #GstDmaBufAllocator wrapping the exported dma-buf
|
||||
+ * file descriptor.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+GstMemory *
|
||||
+gst_drm_dumb_memory_export_dmabuf (GstMemory * mem)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ GstDRMDumbMemory *drmmem = (GstDRMDumbMemory *) mem;
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (mem->allocator);
|
||||
+ GstMemory *dmamem;
|
||||
+ gint ret;
|
||||
+ gint prime_fd;
|
||||
+
|
||||
+ ret = drmPrimeHandleToFD (alloc->drm_fd, drmmem->handle,
|
||||
+ DRM_CLOEXEC | DRM_RDWR, &prime_fd);
|
||||
+ if (ret)
|
||||
+ goto export_fd_failed;
|
||||
+
|
||||
+ if (G_UNLIKELY (alloc->dmabuf_alloc == NULL))
|
||||
+ alloc->dmabuf_alloc = gst_dmabuf_allocator_new ();
|
||||
+
|
||||
+ dmamem = gst_dmabuf_allocator_alloc (alloc->dmabuf_alloc, prime_fd,
|
||||
+ gst_memory_get_sizes (mem, NULL, NULL));
|
||||
+
|
||||
+ GST_DEBUG_OBJECT (alloc, "Exported bo handle %d as %d", drmmem->handle,
|
||||
+ prime_fd);
|
||||
+
|
||||
+ return dmamem;
|
||||
+
|
||||
+ /* ERRORS */
|
||||
+export_fd_failed:
|
||||
+ {
|
||||
+ GST_ERROR_OBJECT (alloc, "Failed to export bo handle %d: %s (%d)",
|
||||
+ drmmem->handle, g_strerror (errno), ret);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+static guint32
|
||||
+gst_drm_height_from_drm (guint32 drmfmt, guint32 height)
|
||||
+{
|
||||
+ guint32 ret;
|
||||
+
|
||||
+ switch (drmfmt) {
|
||||
+ case DRM_FORMAT_YUV420:
|
||||
+ case DRM_FORMAT_YVU420:
|
||||
+ case DRM_FORMAT_YUV422:
|
||||
+ case DRM_FORMAT_NV12:
|
||||
+ case DRM_FORMAT_NV21:
|
||||
+ case DRM_FORMAT_P010:
|
||||
+ case DRM_FORMAT_P016:
|
||||
+ ret = height * 3 / 2;
|
||||
+ break;
|
||||
+ case DRM_FORMAT_NV16:
|
||||
+ case DRM_FORMAT_NV61:
|
||||
+ ret = height * 2;
|
||||
+ break;
|
||||
+ case DRM_FORMAT_NV24:
|
||||
+ ret = height * 3;
|
||||
+ break;
|
||||
+ default:
|
||||
+ ret = height;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static guint32
|
||||
+gst_drm_bpp_from_drm (guint32 drm_fourcc)
|
||||
+{
|
||||
+ guint32 bpp;
|
||||
+
|
||||
+ switch (drm_fourcc) {
|
||||
+ case DRM_FORMAT_YUV420:
|
||||
+ case DRM_FORMAT_YVU420:
|
||||
+ case DRM_FORMAT_YUV422:
|
||||
+ case DRM_FORMAT_NV12:
|
||||
+ case DRM_FORMAT_NV21:
|
||||
+ case DRM_FORMAT_NV16:
|
||||
+ case DRM_FORMAT_NV61:
|
||||
+ case DRM_FORMAT_NV24:
|
||||
+ bpp = 8;
|
||||
+ break;
|
||||
+ case DRM_FORMAT_P010:
|
||||
+ bpp = 10;
|
||||
+ break;
|
||||
+ case DRM_FORMAT_UYVY:
|
||||
+ case DRM_FORMAT_YUYV:
|
||||
+ case DRM_FORMAT_YVYU:
|
||||
+ case DRM_FORMAT_P016:
|
||||
+ case DRM_FORMAT_RGB565:
|
||||
+ case DRM_FORMAT_BGR565:
|
||||
+ bpp = 16;
|
||||
+ break;
|
||||
+ case DRM_FORMAT_BGR888:
|
||||
+ case DRM_FORMAT_RGB888:
|
||||
+ bpp = 24;
|
||||
+ break;
|
||||
+ default:
|
||||
+ bpp = 32;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return bpp;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+check_drm_fd (GstDRMDumbAllocator * alloc)
|
||||
+{
|
||||
+ return alloc->drm_fd > -1;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_open_device (GstDRMDumbAllocator * alloc,
|
||||
+ const gchar * path)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ gint fd = -1;
|
||||
+
|
||||
+ /* Ignore default constructor call */
|
||||
+ if (path == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ /* construct only */
|
||||
+ g_assert (alloc->drm_fd == -1);
|
||||
+ g_assert (alloc->drm_device_path == NULL);
|
||||
+
|
||||
+ fd = open (path, O_RDWR | O_CLOEXEC);
|
||||
+
|
||||
+ if (fd < 0) {
|
||||
+ GST_WARNING_OBJECT (alloc, "Failed to open DRM device at %s", path);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ alloc->drm_device_path = g_strdup (path);
|
||||
+ alloc->drm_fd = fd;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_set_fd (GstDRMDumbAllocator * alloc, gint fd)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ /* Ignore default constructor call */
|
||||
+ if (fd == -1)
|
||||
+ return;
|
||||
+
|
||||
+ /* construct only */
|
||||
+ g_assert (alloc->drm_fd == -1);
|
||||
+ g_assert (alloc->drm_device_path == NULL);
|
||||
+
|
||||
+ if (fd >= 0) {
|
||||
+ alloc->drm_device_path = drmGetDeviceNameFromFd2 (fd);
|
||||
+ if (!alloc->drm_device_path) {
|
||||
+ GST_WARNING_OBJECT (alloc, "Failed to verify DRM fd.");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ GST_DEBUG_OBJECT (alloc, "Using external FD for %s",
|
||||
+ alloc->drm_device_path);
|
||||
+
|
||||
+ alloc->drm_fd = dup (fd);
|
||||
+ }
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_memory_reset (GstDRMDumbAllocator * alloc,
|
||||
+ GstDRMDumbMemory * mem)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ gint err;
|
||||
+ struct drm_mode_destroy_dumb arg = { 0, };
|
||||
+
|
||||
+ if (!mem->size)
|
||||
+ return;
|
||||
+
|
||||
+ if (!check_drm_fd (alloc))
|
||||
+ return;
|
||||
+
|
||||
+ if (mem->ptr != NULL) {
|
||||
+ GST_WARNING_OBJECT (alloc, "destroying mapped bo (refcount=%d)", mem->refs);
|
||||
+ munmap (mem->ptr, mem->size);
|
||||
+ mem->ptr = NULL;
|
||||
+ }
|
||||
+
|
||||
+ arg.handle = mem->handle;
|
||||
+
|
||||
+ err = drmIoctl (alloc->drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
|
||||
+ if (err)
|
||||
+ GST_WARNING_OBJECT (alloc,
|
||||
+ "Failed to destroy dumb buffer object: %s %d",
|
||||
+ g_strerror (errno), errno);
|
||||
+
|
||||
+ mem->handle = -1;
|
||||
+ mem->size = 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+gst_drm_dumb_allocator_memory_create (GstDRMDumbAllocator * alloc,
|
||||
+ GstDRMDumbMemory * drmmem,
|
||||
+ guint32 drm_fourcc, guint32 width, guint32 height, guint32 * out_pitch)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ gint ret;
|
||||
+ struct drm_mode_create_dumb arg = { 0, };
|
||||
+
|
||||
+ if (drmmem->size)
|
||||
+ return TRUE;
|
||||
+
|
||||
+ if (!check_drm_fd (alloc))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ arg.bpp = gst_drm_bpp_from_drm (drm_fourcc);
|
||||
+ arg.width = width;
|
||||
+ arg.height = gst_drm_height_from_drm (drm_fourcc, height);
|
||||
+
|
||||
+ ret = drmIoctl (alloc->drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
|
||||
+ if (ret)
|
||||
+ goto create_failed;
|
||||
+
|
||||
+ if (!arg.pitch) {
|
||||
+ GST_DEBUG_OBJECT (alloc,
|
||||
+ "DRM dumb buffer pitch not set, no need to modify vinfo");
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ GST_DEBUG_OBJECT (alloc,
|
||||
+ "DRM dumb buffer pitch is set, vinfo modification required");
|
||||
+ *out_pitch = arg.pitch;
|
||||
+
|
||||
+done:
|
||||
+ drmmem->handle = arg.handle;
|
||||
+ /* will be used used as maxsize of GstMemory */
|
||||
+ drmmem->size = arg.size;
|
||||
+
|
||||
+ return TRUE;
|
||||
+
|
||||
+ /* ERRORS */
|
||||
+create_failed:
|
||||
+ {
|
||||
+ GST_ERROR_OBJECT (alloc, "Failed to create buffer object: %s (%d)",
|
||||
+ g_strerror (errno), errno);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+#else
|
||||
+ return FALSE;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_free (GstAllocator * base_alloc, GstMemory * mem)
|
||||
+{
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (base_alloc);
|
||||
+ GstDRMDumbMemory *drmmem;
|
||||
+
|
||||
+ drmmem = (GstDRMDumbMemory *) mem;
|
||||
+
|
||||
+ gst_drm_dumb_allocator_memory_reset (alloc, drmmem);
|
||||
+ g_free (drmmem);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_set_property (GObject * object, guint prop_id,
|
||||
+ const GValue * value, GParamSpec * pspec)
|
||||
+{
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (object);
|
||||
+
|
||||
+ switch (prop_id) {
|
||||
+ case PROP_DRM_FD:
|
||||
+ gst_drm_dumb_allocator_set_fd (alloc, g_value_get_int (value));
|
||||
+ break;
|
||||
+ case PROP_DRM_DEVICE_PATH:
|
||||
+ gst_drm_dumb_allocator_open_device (alloc, g_value_get_string (value));
|
||||
+ break;
|
||||
+ default:
|
||||
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_get_property (GObject * object, guint prop_id,
|
||||
+ GValue * value, GParamSpec * pspec)
|
||||
+{
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (object);
|
||||
+
|
||||
+ switch (prop_id) {
|
||||
+ case PROP_DRM_FD:
|
||||
+ g_value_set_int (value, alloc->drm_fd);
|
||||
+ break;
|
||||
+ case PROP_DRM_DEVICE_PATH:
|
||||
+ g_value_set_string (value, alloc->drm_device_path);
|
||||
+ break;
|
||||
+ default:
|
||||
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_finalize (GObject * obj)
|
||||
+{
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (obj);
|
||||
+
|
||||
+ if (alloc->dmabuf_alloc)
|
||||
+ gst_object_unref (alloc->dmabuf_alloc);
|
||||
+
|
||||
+ g_free (alloc->drm_device_path);
|
||||
+ alloc->drm_device_path = NULL;
|
||||
+
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ if (alloc->drm_fd >= 0) {
|
||||
+ close (alloc->drm_fd);
|
||||
+ alloc->drm_fd = -1;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_class_init (GstDRMDumbAllocatorClass * klass)
|
||||
+{
|
||||
+ GObjectClass *gobject_class;
|
||||
+ GstAllocatorClass *allocator_class;
|
||||
+
|
||||
+ allocator_class = GST_ALLOCATOR_CLASS (klass);
|
||||
+ gobject_class = G_OBJECT_CLASS (klass);
|
||||
+
|
||||
+ allocator_class->free = gst_drm_dumb_allocator_free;
|
||||
+
|
||||
+ gobject_class->set_property = gst_drm_dumb_allocator_set_property;
|
||||
+ gobject_class->get_property = gst_drm_dumb_allocator_get_property;
|
||||
+ gobject_class->finalize = gst_drm_dumb_allocator_finalize;
|
||||
+
|
||||
+ /**
|
||||
+ * GstDRMDumbAllocator:drm-fd:
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+ g_props[PROP_DRM_FD] = g_param_spec_int ("drm-fd", "DRM fd",
|
||||
+ "DRM file descriptor", -1, G_MAXINT, -1,
|
||||
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
+
|
||||
+ /**
|
||||
+ * GstDRMDumbAllocator:drm-device-path:
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+ g_props[PROP_DRM_DEVICE_PATH] = g_param_spec_string ("drm-device-path",
|
||||
+ "DRM device path", "DRM device path", NULL,
|
||||
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
|
||||
+
|
||||
+ g_object_class_install_properties (gobject_class, PROP_N, g_props);
|
||||
+}
|
||||
+
|
||||
+static gpointer
|
||||
+gst_drm_dumb_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (mem->allocator);
|
||||
+ GstDRMDumbMemory *drmmem;
|
||||
+ gint err;
|
||||
+ gpointer out;
|
||||
+ struct drm_mode_map_dumb arg = { 0, };
|
||||
+
|
||||
+
|
||||
+ if (!check_drm_fd (alloc))
|
||||
+ return NULL;
|
||||
+
|
||||
+ drmmem = (GstDRMDumbMemory *) mem;
|
||||
+ if (!drmmem->size)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* Reuse existing buffer object mapping if possible */
|
||||
+ if (drmmem->ptr != NULL) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ arg.handle = drmmem->handle;
|
||||
+
|
||||
+ err = drmIoctl (alloc->drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
|
||||
+ if (err) {
|
||||
+ GST_ERROR_OBJECT (alloc, "Failed to get offset of buffer object: %s %d",
|
||||
+ g_strerror (errno), errno);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ out = mmap (0, drmmem->size,
|
||||
+ PROT_READ | PROT_WRITE, MAP_SHARED, alloc->drm_fd, arg.offset);
|
||||
+ if (out == MAP_FAILED) {
|
||||
+ GST_ERROR_OBJECT (alloc, "Failed to map dumb buffer object: %s %d",
|
||||
+ g_strerror (errno), errno);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ drmmem->ptr = out;
|
||||
+
|
||||
+out:
|
||||
+ g_atomic_int_inc (&drmmem->refs);
|
||||
+ return drmmem->ptr;
|
||||
+
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_memory_unmap (GstMemory * mem)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ GstDRMDumbMemory *drmmem;
|
||||
+
|
||||
+ if (!check_drm_fd ((GstDRMDumbAllocator *) mem->allocator))
|
||||
+ return;
|
||||
+
|
||||
+ drmmem = (GstDRMDumbMemory *) mem;
|
||||
+ if (!drmmem->size)
|
||||
+ return;
|
||||
+
|
||||
+ if (g_atomic_int_dec_and_test (&drmmem->refs)) {
|
||||
+ munmap (drmmem->ptr, drmmem->size);
|
||||
+ drmmem->ptr = NULL;
|
||||
+ }
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+gst_drm_dumb_allocator_init (GstDRMDumbAllocator * alloc)
|
||||
+{
|
||||
+ GstAllocator *base_alloc = GST_ALLOCATOR_CAST (alloc);
|
||||
+
|
||||
+ alloc->drm_fd = -1;
|
||||
+ alloc->drm_device_path = NULL;
|
||||
+
|
||||
+ base_alloc->mem_type = GST_DRM_DUMB_MEMORY_TYPE;
|
||||
+ base_alloc->mem_map = gst_drm_dumb_memory_map;
|
||||
+ base_alloc->mem_unmap = gst_drm_dumb_memory_unmap;
|
||||
+ /* Use the default, fallback copy function */
|
||||
+
|
||||
+ GST_OBJECT_FLAG_SET (alloc, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
|
||||
+}
|
||||
+
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+static gboolean
|
||||
+check_cap (GstDRMDumbAllocator * alloc)
|
||||
+{
|
||||
+ gint ret;
|
||||
+ guint64 has_dumb = 0;
|
||||
+
|
||||
+ if (!alloc)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!check_drm_fd (alloc))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ ret = drmGetCap (alloc->drm_fd, DRM_CAP_DUMB_BUFFER, &has_dumb);
|
||||
+ if (ret)
|
||||
+ GST_WARNING_OBJECT (alloc, "could not get dumb buffer capability");
|
||||
+
|
||||
+ return ! !(has_dumb);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * gst_drm_dumb_allocator_new_with_fd:
|
||||
+ * @drm_fd: file descriptor of the DRM device
|
||||
+ *
|
||||
+ * Creates a new #GstDRMDumbAllocator for the specific file desciptor. This
|
||||
+ * function can fail if the file descriptor is not a DRM device or if
|
||||
+ * the DRM device does not support DUMB allocation.
|
||||
+ *
|
||||
+ * Returns: (transfer full) (nullable): a new DRM Dumb allocator. Use gst_object_unref()
|
||||
+ * to release the allocator after usage.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+
|
||||
+ */
|
||||
+GstAllocator *
|
||||
+gst_drm_dumb_allocator_new_with_fd (gint drm_fd)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ GstDRMDumbAllocator *alloc;
|
||||
+
|
||||
+ alloc = g_object_new (GST_TYPE_DRM_DUMB_ALLOCATOR, "drm-fd", drm_fd, NULL);
|
||||
+ gst_object_ref_sink (alloc);
|
||||
+
|
||||
+ if (!check_drm_fd (alloc))
|
||||
+ g_clear_object (&alloc);
|
||||
+
|
||||
+ if (!check_cap (alloc))
|
||||
+ g_clear_object (&alloc);
|
||||
+
|
||||
+ return alloc ? GST_ALLOCATOR (alloc) : NULL;
|
||||
+
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * gst_drm_dumb_allocator_new_with_device_path:
|
||||
+ * @drm_device_path: path to the DRM device to open
|
||||
+ *
|
||||
+ * Creates a new #GstDRMDumbAllocator for the specific device path. This
|
||||
+ * function can fail if the path does not exist, is not a DRM device or if
|
||||
+ * the DRM device doesnot support DUMB allocation.
|
||||
+ *
|
||||
+ * Returns: (transfer full) (nullable): a new DRM Dumb allocator. Use gst_object_unref()
|
||||
+ * to release the allocator after usage.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+GstAllocator *
|
||||
+gst_drm_dumb_allocator_new_with_device_path (const gchar * drm_device_path)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ GstDRMDumbAllocator *alloc;
|
||||
+
|
||||
+ alloc = g_object_new (GST_TYPE_DRM_DUMB_ALLOCATOR,
|
||||
+ "drm-device-path", drm_device_path, NULL);
|
||||
+ gst_object_ref_sink (alloc);
|
||||
+
|
||||
+ if (!check_drm_fd (alloc))
|
||||
+ g_clear_object (&alloc);
|
||||
+
|
||||
+ if (!check_cap (alloc))
|
||||
+ g_clear_object (&alloc);
|
||||
+
|
||||
+ return alloc ? GST_ALLOCATOR (alloc) : NULL;
|
||||
+
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * gst_drm_dumb_allocator_alloc:
|
||||
+ * @allocator: the allocator instance
|
||||
+ * @drm_fourcc: the DRM format to allocate for
|
||||
+ * @width: padded width for this allocation
|
||||
+ * @height: padded height for this allocation
|
||||
+ * @out_pitch: (out): the pitch as returned by the driver
|
||||
+ *
|
||||
+ * Allocated a DRM buffer object for the specific @drm_fourcc, @width and
|
||||
+ * @height. Note that the DRM Dumb allocation interface is agnostic to the
|
||||
+ * pixel format. This @drm_fourcc is converted into a bpp (bit-per-pixel)
|
||||
+ * number and the height is scaled according to the sub-sampling.
|
||||
+ *
|
||||
+ * Returns: (transfer full): a new DRM Dumb #GstMemory. Use gst_memory_unref()
|
||||
+ * to release the memory after usage.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+GstMemory *
|
||||
+gst_drm_dumb_allocator_alloc (GstAllocator * base_alloc,
|
||||
+ guint32 drm_fourcc, guint32 width, guint32 height, guint32 * out_pitch)
|
||||
+{
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (base_alloc);
|
||||
+ GstDRMDumbMemory *drmmem;
|
||||
+ GstMemory *mem;
|
||||
+
|
||||
+ drmmem = g_new0 (GstDRMDumbMemory, 1);
|
||||
+ mem = GST_MEMORY_CAST (drmmem);
|
||||
+
|
||||
+ if (!gst_drm_dumb_allocator_memory_create (alloc, drmmem,
|
||||
+ drm_fourcc, width, height, out_pitch)) {
|
||||
+ g_free (drmmem);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ gst_memory_init (mem, 0, base_alloc, NULL, drmmem->size, 0, 0, drmmem->size);
|
||||
+ return mem;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * gst_drm_dumb_allocator_has_prime_export:
|
||||
+ * @allocator: the #GstAllocator
|
||||
+ *
|
||||
+ * This function allow verifying if the driver support dma-buf exportation.
|
||||
+ *
|
||||
+ * Returns: %TRUE if the allocator support exporting dma-buf.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+gboolean
|
||||
+gst_drm_dumb_allocator_has_prime_export (GstAllocator * base_alloc)
|
||||
+{
|
||||
+#ifdef HAVE_LIBDRM
|
||||
+ GstDRMDumbAllocator *alloc = GST_DRM_DUMB_ALLOCATOR (base_alloc);
|
||||
+ gint ret;
|
||||
+ guint64 has_prime = 0;
|
||||
+
|
||||
+ if (!check_drm_fd (alloc))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ ret = drmGetCap (alloc->drm_fd, DRM_CAP_PRIME, &has_prime);
|
||||
+ if (ret)
|
||||
+ GST_WARNING_OBJECT (alloc, "could not get prime capability");
|
||||
+
|
||||
+ return ! !(has_prime & DRM_PRIME_CAP_EXPORT);
|
||||
+
|
||||
+#else
|
||||
+ return FALSE;
|
||||
+#endif
|
||||
+}
|
||||
diff --git a/gst-libs/gst/allocators/gstdrmdumb.h b/gst-libs/gst/allocators/gstdrmdumb.h
|
||||
new file mode 100644
|
||||
index 0000000..fa5f5ed
|
||||
--- /dev/null
|
||||
+++ b/gst-libs/gst/allocators/gstdrmdumb.h
|
||||
@@ -0,0 +1,88 @@
|
||||
+/* GStreamer
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Igalia
|
||||
+ * Copyright (C) 2023 Collabora
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
|
||||
+ * Javier Martin <javiermartin@by.com.es>
|
||||
+ * Colin Kinloch <colin.kinloch@collabora.com>
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Library General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Library General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Library General Public
|
||||
+ * License along with this library; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
+ * Boston, MA 02110-1301, USA.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#pragma once
|
||||
+
|
||||
+#include <gst/gst.h>
|
||||
+#include <gst/allocators/allocators-prelude.h>
|
||||
+
|
||||
+G_BEGIN_DECLS
|
||||
+
|
||||
+/**
|
||||
+ * GstDRMDumbAllocator:
|
||||
+ *
|
||||
+ * Private intance object for #GstDRMDumbAllocator.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * GstDRMDumbAllocatorClass.parent_class:
|
||||
+ *
|
||||
+ * Parent Class.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * GST_TYPE_DRM_DUMB_ALLOCATOR:
|
||||
+ *
|
||||
+ * Macro that returns the #GstDRMDumbAllocator type.
|
||||
+ *
|
||||
+ * Since: 1.24
|
||||
+ */
|
||||
+#define GST_TYPE_DRM_DUMB_ALLOCATOR gst_drm_dumb_allocator_get_type ()
|
||||
+GST_ALLOCATORS_API
|
||||
+G_DECLARE_FINAL_TYPE (GstDRMDumbAllocator, gst_drm_dumb_allocator,
|
||||
+ GST, DRM_DUMB_ALLOCATOR, GstAllocator);
|
||||
+
|
||||
+GST_ALLOCATORS_API
|
||||
+gboolean gst_is_drm_dumb_memory (GstMemory * mem);
|
||||
+
|
||||
+GST_ALLOCATORS_API
|
||||
+guint32 gst_drm_dumb_memory_get_handle (GstMemory * mem);
|
||||
+
|
||||
+GST_ALLOCATORS_API
|
||||
+GstMemory* gst_drm_dumb_memory_export_dmabuf (GstMemory * mem);
|
||||
+
|
||||
+GST_ALLOCATORS_API
|
||||
+GstAllocator * gst_drm_dumb_allocator_new_with_fd (gint drm_fd);
|
||||
+
|
||||
+GST_ALLOCATORS_API
|
||||
+GstAllocator * gst_drm_dumb_allocator_new_with_device_path (const gchar *drm_device_path);
|
||||
+
|
||||
+GST_ALLOCATORS_API
|
||||
+GstMemory * gst_drm_dumb_allocator_alloc (GstAllocator * allocator,
|
||||
+ guint32 drm_fourcc,
|
||||
+ guint32 width,
|
||||
+ guint32 height,
|
||||
+ guint32 *out_pitch);
|
||||
+
|
||||
+GST_ALLOCATORS_API
|
||||
+gboolean gst_drm_dumb_allocator_has_prime_export (GstAllocator * allocator);
|
||||
+
|
||||
+G_END_DECLS
|
||||
diff --git a/gst-libs/gst/allocators/meson.build b/gst-libs/gst/allocators/meson.build
|
||||
index 6ee0bfd..879c2fc 100644
|
||||
--- a/gst-libs/gst/allocators/meson.build
|
||||
+++ b/gst-libs/gst/allocators/meson.build
|
||||
@@ -4,10 +4,11 @@ gst_allocators_headers = files([
|
||||
'gstfdmemory.h',
|
||||
'gstphysmemory.h',
|
||||
'gstdmabuf.h',
|
||||
+ 'gstdrmdumb.h',
|
||||
])
|
||||
install_headers(gst_allocators_headers, subdir : 'gstreamer-1.0/gst/allocators/')
|
||||
|
||||
-gst_allocators_sources = files([ 'gstdmabuf.c', 'gstfdmemory.c', 'gstphysmemory.c'])
|
||||
+gst_allocators_sources = files([ 'gstdrmdumb.c', 'gstdmabuf.c', 'gstfdmemory.c', 'gstphysmemory.c'])
|
||||
gstallocators = library('gstallocators-@0@'.format(api_version),
|
||||
gst_allocators_sources,
|
||||
c_args : gst_plugins_base_args + ['-DBUILDING_GST_ALLOCATORS', '-DG_LOG_DOMAIN="GStreamer-Allocators"'],
|
||||
@@ -16,12 +17,12 @@ gstallocators = library('gstallocators-@0@'.format(api_version),
|
||||
soversion : soversion,
|
||||
darwin_versions : osxversion,
|
||||
install : true,
|
||||
- dependencies : [gst_dep],
|
||||
+ dependencies : [libdrm_dep, gst_dep],
|
||||
)
|
||||
|
||||
pkg_name = 'gstreamer-allocators-1.0'
|
||||
pkgconfig.generate(gstallocators,
|
||||
- libraries : [gst_dep],
|
||||
+ libraries : [libdrm_dep, gst_dep],
|
||||
variables : pkgconfig_variables,
|
||||
subdirs : pkgconfig_subdirs,
|
||||
name : pkg_name,
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 19a8347..699af91 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -305,6 +305,13 @@ if get_option('default_library') == 'static'
|
||||
gst_plugins_base_args += ['-DGST_STATIC_COMPILATION']
|
||||
endif
|
||||
|
||||
+libdrm_dep = dependency('libdrm', version : '>= 2.4.98',
|
||||
+ required : get_option('drm'),
|
||||
+ fallback: ['libdrm', 'ext_libdrm']
|
||||
+)
|
||||
+
|
||||
+core_conf.set('HAVE_LIBDRM', libdrm_dep.found())
|
||||
+
|
||||
# X11 checks are for sys/ and tests/
|
||||
x11_dep = dependency('x11', required : get_option('x11'))
|
||||
# GIO is used by the GIO plugin, and by the TCP, SDP, and RTSP plugins
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index 50ec6aa..0db1840 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -36,6 +36,7 @@ option('audiorate', type : 'feature', value : 'auto')
|
||||
option('audioresample', type : 'feature', value : 'auto')
|
||||
option('audiotestsrc', type : 'feature', value : 'auto')
|
||||
option('compositor', type : 'feature', value : 'auto')
|
||||
+option('drm', type : 'feature', value : 'auto')
|
||||
option('encoding', type : 'feature', value : 'auto')
|
||||
option('gio', type : 'feature', value : 'auto')
|
||||
option('gio-typefinder', type : 'feature', value : 'auto')
|
||||
--
|
||||
2.25.1
|
||||
|
||||
Reference in New Issue
Block a user