summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac10
-rw-r--r--sys/Makefile.am10
-rw-r--r--sys/inteldrm/Makefile.am20
-rw-r--r--sys/inteldrm/gstinteldmabufupload.c402
-rw-r--r--sys/inteldrm/gstinteldmabufupload.h69
-rw-r--r--sys/inteldrm/intelbufmgrpool.c222
-rw-r--r--sys/inteldrm/intelbufmgrpool.h56
7 files changed, 787 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index eb6b41f..8dadd65 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2123,6 +2123,14 @@ AG_GST_CHECK_FEATURE(FLUIDSYNTH, [fluidsynth], fluidsynth, [
])
])
+dnl *** inteldrm ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_INTELDRM, true)
+AG_GST_CHECK_FEATURE(INTELDRM, [inteldrm], inteldrm, [
+ PKG_CHECK_MODULES(INTELDRM, libdrm_intel, HAVE_INTELDRM="yes", [
+ HAVE_INTELDRM="no"
+ ])
+])
+
dnl *** kate ***
translit(dnm, m, l) AM_CONDITIONAL(USE_KATE, true)
AG_GST_CHECK_FEATURE(KATE, [Kate], kate, [
@@ -2991,6 +2999,7 @@ AM_CONDITIONAL(USE_FLITE, false)
AM_CONDITIONAL(USE_FLUIDSYNTH, false)
AM_CONDITIONAL(USE_GSM, false)
AM_CONDITIONAL(USE_HLS, false)
+AM_CONDITIONAL(USE_INTELDRM, false)
AM_CONDITIONAL(USE_KATE, false)
AM_CONDITIONAL(USE_TIGER, false)
AM_CONDITIONAL(USE_LADSPA, false)
@@ -3226,6 +3235,7 @@ sys/dshowsrcwrapper/Makefile
sys/dshowvideosink/Makefile
sys/dvb/Makefile
sys/fbdev/Makefile
+sys/inteldrm/Makefile
sys/linsys/Makefile
sys/opensles/Makefile
sys/osxvideo/Makefile
diff --git a/sys/Makefile.am b/sys/Makefile.am
index 28528be..02701f5 100644
--- a/sys/Makefile.am
+++ b/sys/Makefile.am
@@ -76,6 +76,12 @@ else
FBDEV_DIR=
endif
+if USE_INTELDRM
+INTELDRM_DIR=inteldrm
+else
+INTELDRM_DIR=
+endif
+
if USE_DVB
DVB_DIR=dvb
else
@@ -160,9 +166,9 @@ else
UVCH264_DIR=
endif
-SUBDIRS = $(ACM_DIR) $(ANDROID_MEDIA_DIR) $(APPLE_MEDIA_DIR) $(AVC_DIR) $(BLUEZ_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(WINKS_DIR) $(DVB_DIR) $(FBDEV_DIR) $(LINSYS_DIR) $(OPENSLES_DIR) $(OSX_VIDEO_DIR) $(PVR_DIR) $(QT_DIR) $(SHM_DIR) $(UVCH264_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) $(WINSCREENCAP_DIR) $(WASAPI_DIR)
+SUBDIRS = $(ACM_DIR) $(ANDROID_MEDIA_DIR) $(APPLE_MEDIA_DIR) $(AVC_DIR) $(BLUEZ_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(WINKS_DIR) $(DVB_DIR) $(FBDEV_DIR) $(INTELDRM_DIR) $(LINSYS_DIR) $(OPENSLES_DIR) $(OSX_VIDEO_DIR) $(PVR_DIR) $(QT_DIR) $(SHM_DIR) $(UVCH264_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) $(WINSCREENCAP_DIR) $(WASAPI_DIR)
-DIST_SUBDIRS = acmenc acmmp3dec androidmedia applemedia applemedia-nonpublic avc bluez d3dvideosink decklink directdraw directsound dvb linsys fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \
+DIST_SUBDIRS = acmenc acmmp3dec androidmedia applemedia applemedia-nonpublic avc bluez d3dvideosink decklink directdraw directsound dvb linsys fbdev inteldrm dshowdecwrapper dshowsrcwrapper dshowvideosink \
opensles osxvideo pvr2d qtwrapper shm uvch264 vcd vdpau wasapi wininet winks winscreencap
include $(top_srcdir)/common/parallel-subdirs.mak
diff --git a/sys/inteldrm/Makefile.am b/sys/inteldrm/Makefile.am
new file mode 100644
index 0000000..3457a13
--- /dev/null
+++ b/sys/inteldrm/Makefile.am
@@ -0,0 +1,20 @@
+plugin_LTLIBRARIES = libgstinteldrm.la
+
+libgstinteldrm_la_SOURCES = \
+ gstinteldmabufupload.c \
+ intelbufmgrpool.c
+
+libgstinteldrm_la_CFLAGS = $(GST_CFLAGS) \
+ $(GST_PLUGINS_BAD_CFLAGS) \
+ $(INTELDRM_CFLAGS)
+libgstinteldrm_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(INTELDRM_LIBS) \
+ -lgstvideo-$(GST_API_VERSION) \
+ -lgstallocators-$(GST_API_VERSION)
+libgstinteldrm_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstinteldrm_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
+
+noinst_HEADERS = \
+ gstinteldmabufupload.h \
+ intelbufmgrpool.h
diff --git a/sys/inteldrm/gstinteldmabufupload.c b/sys/inteldrm/gstinteldmabufupload.c
new file mode 100644
index 0000000..29e0406
--- /dev/null
+++ b/sys/inteldrm/gstinteldmabufupload.c
@@ -0,0 +1,402 @@
+/*
+ * GStreamer intel dmabuf upload element
+ *
+ * Copyright (C) 2014 Collabora Ltd.
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include "gstinteldmabufupload.h"
+#include "intelbufmgrpool.h"
+#include <gst/allocators/gstdmabuf.h>
+#include <gst/video/video.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+GST_DEBUG_CATEGORY (gstinteldmabufupload_debug);
+#define GST_CAT_DEFAULT gstinteldmabufupload_debug
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
+ ("{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB }"))
+ );
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+ ("memory:" GST_ALLOCATOR_DMABUF,
+ "{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB }"))
+ );
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstIntelBufmgrContext, gst_intel_bufmgr_context);
+
+G_DEFINE_TYPE (GstIntelDmabufUpload, gst_intel_dmabuf_upload,
+ GST_TYPE_BASE_TRANSFORM);
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPERTIES
+};
+
+static void
+gst_intel_bufmgr_context_free (GstIntelBufmgrContext * c)
+{
+ drm_intel_bufmgr_destroy (c->bufmgr);
+ close (c->drm_fd);
+
+ g_slice_free (GstIntelBufmgrContext, c);
+}
+
+static GstIntelBufmgrContext *
+gst_intel_bufmgr_context_new (gint fd, drm_intel_bufmgr * bufmgr)
+{
+ GstIntelBufmgrContext *c;
+
+ c = g_slice_new0 (GstIntelBufmgrContext);
+
+ gst_mini_object_init ((GstMiniObject *) c, 0,
+ gst_intel_bufmgr_context_get_type (), NULL, NULL,
+ (GstMiniObjectFreeFunction) gst_intel_bufmgr_context_free);
+
+ c->drm_fd = fd;
+ c->bufmgr = bufmgr;
+
+ return c;
+}
+
+static void
+gst_intel_dmabuf_upload_finalize (GObject * gobject)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (gobject);
+
+ if (self->device)
+ g_free (self->device);
+
+ G_OBJECT_CLASS (gst_intel_dmabuf_upload_parent_class)->finalize (gobject);
+}
+
+static void
+gst_intel_dmabuf_upload_set_property (GObject * object, guint property_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (object);
+
+ switch (property_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (self);
+ if (self->device)
+ g_free (self->device);
+ self->device = g_value_dup_string (value);
+ GST_OBJECT_UNLOCK (self);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_intel_dmabuf_upload_get_property (GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (object);
+
+ switch (property_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (self);
+ g_value_set_string (value, self->device);
+ GST_OBJECT_UNLOCK (self);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gst_intel_dmabuf_upload_start (GstBaseTransform * trans)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (trans);
+ gint drm_fd;
+ drm_intel_bufmgr *bufmgr;
+
+ gst_base_transform_set_passthrough (trans, TRUE);
+
+ GST_OBJECT_LOCK (self);
+
+ if (!self->device) {
+ GST_ERROR_OBJECT (self, "No suitable device has been found or set");
+ GST_OBJECT_UNLOCK (self);
+ return FALSE;
+ }
+
+ drm_fd = open (self->device, O_RDWR);
+ if (drm_fd < 0) {
+ GST_ERROR_OBJECT (self, "Failed to open device %s", self->device);
+ GST_OBJECT_UNLOCK (self);
+ return FALSE;
+ }
+
+ GST_OBJECT_UNLOCK (self);
+
+ bufmgr = drm_intel_bufmgr_gem_init (drm_fd, 32);
+ if (!bufmgr) {
+ GST_ERROR_OBJECT (self, "Failed to initialize drm_intel_bufmgr");
+ close (drm_fd);
+ return FALSE;
+ }
+
+ self->context = gst_intel_bufmgr_context_new (drm_fd, bufmgr);
+
+ return TRUE;
+}
+
+static gboolean
+gst_intel_dmabuf_upload_stop (GstBaseTransform * trans)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (trans);
+
+ g_clear_object (&self->pool);
+ if (self->context) {
+ gst_mini_object_unref ((GstMiniObject *) self->context);
+ self->context = NULL;
+ }
+
+ return TRUE;
+}
+
+static GstCaps *
+gst_intel_dmabuf_upload_transform_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+{
+ GstCaps *ret = gst_caps_copy (caps);
+ GstCapsFeatures *features;
+ gint i;
+
+ for (i = 0; i < gst_caps_get_size (ret); i++) {
+ if (direction == GST_PAD_SINK) {
+ features = gst_caps_features_new ("memory:" GST_ALLOCATOR_DMABUF, NULL);
+ gst_caps_set_features (ret, i, features);
+ } else {
+ features = gst_caps_get_features (ret, i);
+ if (gst_caps_features_contains (features, "memory:" GST_ALLOCATOR_DMABUF))
+ gst_caps_features_remove (features, "memory:" GST_ALLOCATOR_DMABUF);
+ }
+ }
+
+ return ret;
+}
+
+static gboolean
+gst_intel_dmabuf_upload_set_caps (GstBaseTransform * trans, GstCaps * incaps,
+ GstCaps * outcaps)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (trans);
+ GstVideoInfo info;
+ gsize size;
+ GstBufferPool *pool;
+ GstStructure *config;
+
+ /* extract info from caps */
+ if (!gst_video_info_from_caps (&info, incaps))
+ goto invalid_format;
+
+ size = info.size;
+
+ if (!gst_video_info_from_caps (&info, outcaps) || size != info.size)
+ goto size_mismatch;
+
+ pool = gst_intel_bufmgr_pool_new (self->context);
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_set_params (config, incaps, size, 1, 0);
+ if (!gst_buffer_pool_set_config (pool, config))
+ goto config_failed;
+
+ gst_object_replace ((GstObject **) & self->pool, (GstObject *) pool);
+ gst_object_unref (pool);
+
+ return TRUE;
+
+invalid_format:
+ {
+ GST_WARNING_OBJECT (self,
+ "Could not extract image format from caps %" GST_PTR_FORMAT, incaps);
+ return FALSE;
+ }
+size_mismatch:
+ {
+ GST_WARNING_OBJECT (self,
+ "Frame size mismatch between the input and output caps");
+ return FALSE;
+ }
+config_failed:
+ {
+ GST_WARNING_OBJECT (self, "Failed to set buffer pool config");
+ gst_object_unref (pool);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_intel_dmabuf_upload_propose_allocation (GstBaseTransform * trans,
+ GstQuery * decide_query, GstQuery * query)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (trans);
+ GstStructure *config;
+ guint size, min_bufs, max_bufs;
+
+ config = gst_buffer_pool_get_config (self->pool);
+ gst_buffer_pool_config_get_params (config, NULL, &size, &min_bufs, &max_bufs);
+
+ gst_query_add_allocation_pool (query, self->pool, size, min_bufs, max_bufs);
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_intel_dmabuf_upload_prepare_output_buffer (GstBaseTransform * trans,
+ GstBuffer * inbuf, GstBuffer ** outbuf)
+{
+ GstIntelDmabufUpload *self = GST_INTEL_DMABUF_UPLOAD (trans);
+ gint i, n = gst_buffer_n_memory (inbuf);
+
+ /* if upstream has used our pool, we can passthrough 100%
+ * otherwise, we need to copy to a buffer from our pool */
+ for (i = 0; i < n; i++) {
+ if (!gst_is_dmabuf_memory (gst_buffer_peek_memory (inbuf, i))) {
+
+ if (!gst_buffer_pool_is_active (self->pool) &&
+ !gst_buffer_pool_set_active (self->pool, TRUE)) {
+ GST_ERROR_OBJECT (trans, "failed to activate buffer pool");
+ return GST_FLOW_ERROR;
+ }
+
+ gst_buffer_pool_acquire_buffer (self->pool, outbuf, NULL);
+ return GST_FLOW_OK;
+ }
+ }
+
+ GST_LOG_OBJECT (trans, "passthrough: reusing input buffer");
+ *outbuf = inbuf;
+ return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_intel_dmabuf_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
+ GstBuffer * outbuf)
+{
+ if (inbuf != outbuf) {
+ GstMapInfo src;
+
+ GST_LOG_OBJECT (trans, "Copying buffer contents from %p to %p", inbuf,
+ outbuf);
+
+ if (!gst_buffer_map (inbuf, &src, GST_MAP_READ)) {
+ GST_ERROR_OBJECT (trans, "Failed to map incoming buffer");
+ return GST_FLOW_ERROR;
+ }
+ gst_buffer_fill (outbuf, 0, src.data, src.size);
+ gst_buffer_unmap (inbuf, &src);
+ }
+
+ return GST_FLOW_OK;
+}
+
+static void
+gst_intel_dmabuf_upload_class_init (GstIntelDmabufUploadClass * klass)
+{
+ GstBaseTransformClass *transform_class = (GstBaseTransformClass *) klass;
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstElementClass *gstelement_class = (GstElementClass *) klass;
+
+ transform_class->start = GST_DEBUG_FUNCPTR (gst_intel_dmabuf_upload_start);
+ transform_class->stop = GST_DEBUG_FUNCPTR (gst_intel_dmabuf_upload_stop);
+
+ transform_class->transform_caps =
+ GST_DEBUG_FUNCPTR (gst_intel_dmabuf_upload_transform_caps);
+ transform_class->set_caps =
+ GST_DEBUG_FUNCPTR (gst_intel_dmabuf_upload_set_caps);
+ transform_class->propose_allocation =
+ GST_DEBUG_FUNCPTR (gst_intel_dmabuf_upload_propose_allocation);
+
+ transform_class->prepare_output_buffer =
+ GST_DEBUG_FUNCPTR (gst_intel_dmabuf_upload_prepare_output_buffer);
+ transform_class->transform =
+ GST_DEBUG_FUNCPTR (gst_intel_dmabuf_upload_transform);
+
+ gobject_class->finalize = gst_intel_dmabuf_upload_finalize;
+ gobject_class->set_property = gst_intel_dmabuf_upload_set_property;
+ gobject_class->get_property = gst_intel_dmabuf_upload_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "The render dri device used for buffer allocation",
+ NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&sink_template));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_template));
+
+ gst_element_class_set_static_metadata (gstelement_class,
+ "intel dmabuf upload", "Filter/Converter/Video",
+ "Upload buffers to intel prime dmabuf objects",
+ "George Kiagiadakis <george.kiagiadakis@collabora.com>");
+
+}
+
+static void
+gst_intel_dmabuf_upload_init (GstIntelDmabufUpload * self)
+{
+ GDir *dir;
+ const gchar *filename;
+
+ /* Find some /dev/dri/renderD* device. This won't work with card0 as we need
+ * to be authenticated; instead, boot with drm.rnodes=1 and use that */
+ dir = g_dir_open ("/dev/dri", 0, NULL);
+ if (dir) {
+ while ((filename = g_dir_read_name (dir))) {
+ if (g_str_has_prefix (filename, "renderD")) {
+ self->device = g_strdup_printf ("/dev/dri/%s", filename);
+ break;
+ }
+ }
+
+ g_dir_close (dir);
+ }
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ GST_DEBUG_CATEGORY_INIT (gstinteldmabufupload_debug, "inteldmabufupload", 0,
+ "intel dmabuf upload");
+
+ return gst_element_register (plugin, "inteldmabufupload", GST_RANK_MARGINAL,
+ GST_TYPE_INTEL_DMABUF_UPLOAD);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, inteldrm,
+ "Intel DRM DMA-BUF/PRIME Utilities",
+ plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/inteldrm/gstinteldmabufupload.h b/sys/inteldrm/gstinteldmabufupload.h
new file mode 100644
index 0000000..f3230b6
--- /dev/null
+++ b/sys/inteldrm/gstinteldmabufupload.h
@@ -0,0 +1,69 @@
+/*
+ * GStreamer intel dmabuf upload element
+ *
+ * Copyright (C) 2014 Collabora Ltd.
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GST_INTEL_DMABUF_UPLOAD_H__
+#define __GST_INTEL_DMABUF_UPLOAD_H__
+
+#include <gst/base/base.h>
+#include <libdrm/intel_bufmgr.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_INTEL_DMABUF_UPLOAD (gst_intel_dmabuf_upload_get_type ())
+#define GST_INTEL_DMABUF_UPLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INTEL_DMABUF_UPLOAD, GstIntelDmabufUpload))
+#define GST_IS_INTEL_DMABUF_UPLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INTEL_DMABUF_UPLOAD))
+#define GST_INTEL_DMABUF_UPLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INTEL_DMABUF_UPLOAD, GstIntelDmabufUploadClass))
+#define GST_IS_INTEL_DMABUF_UPLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INTEL_DMABUF_UPLOAD))
+#define GST_INTEL_DMABUF_UPLOAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_INTEL_DMABUF_UPLOAD, GstIntelDmabufUploadClass))
+
+typedef struct _GstIntelBufmgrContext GstIntelBufmgrContext;
+typedef struct _GstIntelDmabufUpload GstIntelDmabufUpload;
+typedef struct _GstIntelDmabufUploadClass GstIntelDmabufUploadClass;
+
+struct _GstIntelBufmgrContext
+{
+ GstMiniObject parent_instance;
+
+ int drm_fd;
+ drm_intel_bufmgr *bufmgr;
+};
+
+struct _GstIntelDmabufUpload
+{
+ GstBaseTransform parent_instance;
+
+ gchar *device;
+
+ GstBufferPool *pool;
+ GstIntelBufmgrContext *context;
+};
+
+struct _GstIntelDmabufUploadClass
+{
+ GstBaseTransformClass parent_class;
+};
+
+GType gst_intel_bufmgr_context_get_type (void);
+GType gst_intel_dmabuf_upload_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_INTEL_DMABUF_UPLOAD_H__ */
diff --git a/sys/inteldrm/intelbufmgrpool.c b/sys/inteldrm/intelbufmgrpool.c
new file mode 100644
index 0000000..c380397
--- /dev/null
+++ b/sys/inteldrm/intelbufmgrpool.c
@@ -0,0 +1,222 @@
+/*
+ * GStreamer intel bufmgr upload element
+ *
+ * Copyright (C) 2014 Collabora Ltd.
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include "intelbufmgrpool.h"
+
+#include <libdrm/i915_drm.h>
+
+GST_DEBUG_CATEGORY_EXTERN (gstinteldmabufupload_debug);
+#define GST_CAT_DEFAULT gstinteldmabufupload_debug
+
+#define parent_class gst_intel_bufmgr_pool_parent_class
+G_DEFINE_TYPE (GstIntelBufmgrPool, gst_intel_bufmgr_pool, GST_TYPE_BUFFER_POOL);
+
+static G_DEFINE_QUARK (GstIntelBufmgrBoQDataQuark, gst_intel_bufmgr_bo_qdata);
+
+static GstFlowReturn gst_intel_bufmgr_pool_alloc_buffer (GstBufferPool * pool,
+ GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
+
+static gpointer
+gst_intel_bufmgr_mem_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
+{
+ drm_intel_bo *bo;
+
+ /* make memory sharing work, theoretically */
+ if (mem->parent)
+ return gst_intel_bufmgr_mem_map (mem->parent, maxsize, flags);
+
+ bo = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
+ gst_intel_bufmgr_bo_qdata_quark ());
+
+ if (drm_intel_gem_bo_map_gtt (bo) != 0) {
+ GST_ERROR ("failed to map drm_intel_bo");
+ return NULL;
+ }
+
+ return bo->virtual;
+}
+
+static void
+gst_intel_bufmgr_mem_unmap (GstMemory * mem)
+{
+ drm_intel_bo *bo;
+
+ /* make memory sharing work, theoretically */
+ if (mem->parent) {
+ gst_intel_bufmgr_mem_unmap (mem->parent);
+ return;
+ }
+
+ bo = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
+ gst_intel_bufmgr_bo_qdata_quark ());
+
+ drm_intel_gem_bo_unmap_gtt (bo);
+}
+
+static gboolean
+gst_intel_bufmgr_pool_set_config (GstBufferPool * pool, GstStructure * config)
+{
+ GstIntelBufmgrPool *self = GST_INTEL_BUFMGR_POOL (pool);
+ GstVideoInfo info;
+ GstCaps *caps;
+ GstBuffer *tmp;
+ guint size, min_bufs, max_bufs;
+ gboolean ret;
+
+ if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_bufs,
+ &max_bufs))
+ goto wrong_config;
+
+ if (caps == NULL)
+ goto no_caps;
+
+ /* now parse the caps from the config */
+ if (!gst_video_info_from_caps (&info, caps))
+ goto wrong_caps;
+
+ self->info = info;
+
+ /* Acquire a buffer and configure the size in the base class.
+ * This is necessary to allow buffers to be reused in GstBufferPool,
+ * because if the size does not match, GstBufferPool thinks that the
+ * buffer has been modified and it discards it instead of reusing it.
+ * Unfortunately, the size is determined by the downstream drm_intel_bo
+ * allocator and not by us, so we have to allocate a buffer to find
+ * out what its size ends up being.
+ */
+ if (gst_intel_bufmgr_pool_alloc_buffer (pool, &tmp, NULL) != GST_FLOW_OK)
+ return FALSE;
+
+ size = gst_buffer_get_size (tmp);
+ gst_buffer_pool_config_set_params (config, caps, size, min_bufs, max_bufs);
+
+ ret = GST_CALL_PARENT_WITH_DEFAULT
+ (GST_BUFFER_POOL_CLASS, set_config, (pool, config), TRUE);
+
+ gst_buffer_unref (tmp);
+
+ return ret;
+
+ /* ERRORS */
+wrong_config:
+ {
+ GST_WARNING_OBJECT (pool, "invalid config");
+ return FALSE;
+ }
+no_caps:
+ {
+ GST_WARNING_OBJECT (pool, "no caps in config");
+ return FALSE;
+ }
+wrong_caps:
+ {
+ GST_WARNING_OBJECT (pool,
+ "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+}
+
+static GstFlowReturn
+gst_intel_bufmgr_pool_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
+ GstBufferPoolAcquireParams * params)
+{
+ GstIntelBufmgrPool *self = GST_INTEL_BUFMGR_POOL (pool);
+ GstMemory *mem;
+ drm_intel_bo *bo;
+ gint dmabuf_fd;
+ uint32_t tiling = I915_TILING_NONE;
+ gulong stride;
+
+ bo = drm_intel_bo_alloc_tiled (self->context->bufmgr, "gst", self->info.width,
+ self->info.height, self->info.finfo->pixel_stride[0], &tiling, &stride,
+ 0);
+
+ if (!bo) {
+ GST_ERROR_OBJECT (pool, "Allocating a drm_intel_bo failed");
+ return GST_FLOW_ERROR;
+ }
+
+ if (drm_intel_bo_gem_export_to_prime (bo, &dmabuf_fd) != 0) {
+ GST_ERROR_OBJECT (pool, "Failed to export drm_intel_bo to a dmabuf");
+ drm_intel_bo_unreference (bo);
+ return GST_FLOW_ERROR;
+ }
+
+ mem = gst_dmabuf_allocator_alloc (self->allocator, dmabuf_fd, bo->size);
+ gst_mini_object_set_qdata (GST_MINI_OBJECT (mem),
+ gst_intel_bufmgr_bo_qdata_quark (), bo,
+ (GDestroyNotify) drm_intel_bo_unreference);
+
+ *buffer = gst_buffer_new ();
+ gst_buffer_append_memory (*buffer, mem);
+
+ self->info.stride[0] = stride;
+ (void) gst_buffer_add_video_meta_full (*buffer, 0, self->info.finfo->format,
+ self->info.width, self->info.height, self->info.finfo->n_planes,
+ self->info.offset, self->info.stride);
+
+ GST_DEBUG_OBJECT (pool, "Allocated buffer. width %d, height %d, format %s, "
+ "stride %d", self->info.width, self->info.height,
+ gst_video_format_to_string (self->info.finfo->format),
+ self->info.stride[0]);
+
+ return GST_FLOW_OK;
+}
+
+static void
+gst_intel_bufmgr_pool_finalize (GObject * object)
+{
+ GstIntelBufmgrPool *self = GST_INTEL_BUFMGR_POOL (object);
+
+ g_object_unref (self->allocator);
+ gst_mini_object_unref ((GstMiniObject *) self->context);
+}
+
+static void
+gst_intel_bufmgr_pool_class_init (GstIntelBufmgrPoolClass * klass)
+{
+ GstBufferPoolClass *bpool_class = (GstBufferPoolClass *) klass;
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ bpool_class->set_config =
+ GST_DEBUG_FUNCPTR (gst_intel_bufmgr_pool_set_config);
+ bpool_class->alloc_buffer =
+ GST_DEBUG_FUNCPTR (gst_intel_bufmgr_pool_alloc_buffer);
+
+ object_class->finalize = GST_DEBUG_FUNCPTR (gst_intel_bufmgr_pool_finalize);
+}
+
+static void
+gst_intel_bufmgr_pool_init (GstIntelBufmgrPool * self)
+{
+ self->allocator = gst_dmabuf_allocator_new ();
+ self->allocator->mem_map = gst_intel_bufmgr_mem_map;
+ self->allocator->mem_unmap = gst_intel_bufmgr_mem_unmap;
+}
+
+GstBufferPool *
+gst_intel_bufmgr_pool_new (GstIntelBufmgrContext * context)
+{
+ GstIntelBufmgrPool *self = g_object_new (GST_TYPE_INTEL_BUFMGR_POOL, NULL);
+ self->context =
+ (GstIntelBufmgrContext *) gst_mini_object_ref ((GstMiniObject *) context);
+ return (GstBufferPool *) self;
+}
diff --git a/sys/inteldrm/intelbufmgrpool.h b/sys/inteldrm/intelbufmgrpool.h
new file mode 100644
index 0000000..1eed15d
--- /dev/null
+++ b/sys/inteldrm/intelbufmgrpool.h
@@ -0,0 +1,56 @@
+/*
+ * GStreamer intel dmabuf upload element
+ *
+ * Copyright (C) 2014 Collabora Ltd.
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GST_INTEL_BUFMGR_POOL_H__
+#define __GST_INTEL_BUFMGR_POOL_H__
+
+#include "gstinteldmabufupload.h"
+#include <gst/allocators/allocators.h>
+#include <gst/video/video.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_INTEL_BUFMGR_POOL (gst_intel_bufmgr_pool_get_type ())
+#define GST_INTEL_BUFMGR_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INTEL_BUFMGR_POOL, GstIntelBufmgrPool))
+
+typedef struct _GstIntelBufmgrPool GstIntelBufmgrPool;
+typedef struct _GstIntelBufmgrPoolClass GstIntelBufmgrPoolClass;
+
+struct _GstIntelBufmgrPool
+{
+ GstBufferPool parent_instance;
+ GstAllocator *allocator;
+ GstVideoInfo info;
+ GstIntelBufmgrContext *context;
+};
+
+struct _GstIntelBufmgrPoolClass
+{
+ GstBufferPoolClass parent_class;
+};
+
+GType gst_intel_bufmgr_pool_get_type (void);
+
+GstBufferPool * gst_intel_bufmgr_pool_new (GstIntelBufmgrContext *context);
+
+G_END_DECLS
+
+#endif /* __GST_INTEL_BUFMGR_POOL_H__ */