libgstwaylandsink_la_SOURCES = \
gstwaylandsink.c \
- waylandpool.c \
+ wlshmallocator.c \
wlbuffer.c \
wldisplay.c \
wlwindow.c \
noinst_HEADERS = \
gstwaylandsink.h \
- waylandpool.h \
+ wlshmallocator.h \
wlbuffer.h \
wldisplay.h \
wlwindow.h \
gstwaylandsink.c: scaler-client-protocol.h
-waylandpool.c: scaler-client-protocol.h
+wlshmallocator.c: scaler-client-protocol.h
wlbuffer.c: scaler-client-protocol.h
#include "gstwaylandsink.h"
#include "wlvideoformat.h"
-#include "waylandpool.h"
#include "wlbuffer.h"
+#include "wlshmallocator.h"
#include <gst/wayland/wayland.h>
#include <gst/video/videooverlay.h>
* - see the comment on wlbuffer.c for details */
gst_wl_display_stop (sink->display);
g_clear_object (&sink->display);
- g_clear_object (&sink->pool);
}
g_mutex_unlock (&sink->display_lock);
+ g_clear_object (&sink->pool);
break;
default:
break;
GArray *formats;
gint i;
GstStructure *structure;
- static GstAllocationParams params = { 0, 0, 0, 15, };
sink = GST_WAYLAND_SINK (bsink);
goto unsupported_format;
/* create a new pool for the new configuration */
- newpool = gst_wayland_buffer_pool_new (sink->display);
+ newpool = gst_video_buffer_pool_new ();
if (!newpool)
goto pool_failed;
structure = gst_buffer_pool_get_config (newpool);
gst_buffer_pool_config_set_params (structure, caps, info.size, 2, 0);
- gst_buffer_pool_config_set_allocator (structure, NULL, ¶ms);
+ gst_buffer_pool_config_set_allocator (structure, gst_wl_shm_allocator_get (),
+ NULL);
if (!gst_buffer_pool_set_config (newpool, structure))
goto config_failed;
gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
{
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
- GstBufferPool *pool = NULL;
GstStructure *config;
- GstCaps *caps;
- guint size;
- gboolean need_pool;
-
- gst_query_parse_allocation (query, &caps, &need_pool);
-
- if (caps == NULL)
- goto no_caps;
-
- if (sink->pool)
- pool = gst_object_ref (sink->pool);
+ guint size, min_bufs, max_bufs;
- if (pool != NULL) {
- GstCaps *pcaps;
-
- /* we had a pool, check caps */
- config = gst_buffer_pool_get_config (pool);
- gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL);
-
- if (!gst_caps_is_equal (caps, pcaps)) {
- /* different caps, we can't use this pool */
- gst_object_unref (pool);
- pool = NULL;
- }
- gst_structure_free (config);
- }
+ config = gst_buffer_pool_get_config (sink->pool);
+ gst_buffer_pool_config_get_params (config, NULL, &size, &min_bufs, &max_bufs);
- if (pool == NULL && need_pool) {
- GstVideoInfo info;
-
- if (!gst_video_info_from_caps (&info, caps))
- goto invalid_caps;
-
- GST_DEBUG_OBJECT (sink, "create new pool");
- pool = gst_wayland_buffer_pool_new (sink->display);
-
- /* the normal size of a frame */
- size = info.size;
-
- config = gst_buffer_pool_get_config (pool);
- gst_buffer_pool_config_set_params (config, caps, size, 2, 0);
- if (!gst_buffer_pool_set_config (pool, config))
- goto config_failed;
- }
- if (pool) {
- gst_query_add_allocation_pool (query, pool, size, 2, 0);
- gst_object_unref (pool);
- }
+ /* we do have a pool for sure (created in set_caps),
+ * so let's propose it anyway, but also propose the allocator on its own */
+ gst_query_add_allocation_pool (query, sink->pool, size, min_bufs, max_bufs);
+ gst_query_add_allocation_param (query, gst_wl_shm_allocator_get (), NULL);
return TRUE;
-
- /* ERRORS */
-no_caps:
- {
- GST_DEBUG_OBJECT (bsink, "no caps specified");
- return FALSE;
- }
-invalid_caps:
- {
- GST_DEBUG_OBJECT (bsink, "invalid caps specified");
- return FALSE;
- }
-config_failed:
- {
- GST_DEBUG_OBJECT (bsink, "failed setting config");
- gst_object_unref (pool);
- return FALSE;
- }
}
static GstFlowReturn
wlbuffer = gst_buffer_get_wl_buffer (buffer);
- if (wlbuffer && wlbuffer->display == sink->display) {
- GST_LOG_OBJECT (sink, "buffer %p from our pool, writing directly", buffer);
+ if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)) {
+ GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, "
+ "writing directly", buffer);
to_render = buffer;
} else {
- GstMapInfo src;
- GST_LOG_OBJECT (sink, "buffer %p not from our pool, copying", buffer);
+ GstMemory *mem;
+ struct wl_buffer *wbuf = NULL;
+
+ GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our "
+ "display, creating it", buffer);
- if (!sink->pool)
- goto no_pool;
+ mem = gst_buffer_peek_memory (buffer, 0);
- if (!gst_buffer_pool_set_active (sink->pool, TRUE))
- goto activate_failed;
+ if (gst_is_wl_shm_memory (mem)) {
+ wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ }
- ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
- if (ret != GST_FLOW_OK)
- goto no_buffer;
+ if (wbuf) {
+ gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
+ to_render = buffer;
+ } else {
+ GstMapInfo src;
+ /* we don't know how to create a wl_buffer directly from the provided
+ * memory, so we have to copy the data to a memory that we know how
+ * to handle... */
+
+ GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, "
+ "copying to wl_shm memory", buffer);
+
+ /* sink->pool always exists (created in set_caps), but it may not
+ * be active if upstream is not using it */
+ if (!gst_buffer_pool_is_active (sink->pool) &&
+ !gst_buffer_pool_set_active (sink->pool, TRUE))
+ goto activate_failed;
+
+ ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
+ if (ret != GST_FLOW_OK)
+ goto no_buffer;
+
+ /* the first time we acquire a buffer,
+ * we need to attach a wl_buffer on it */
+ wlbuffer = gst_buffer_get_wl_buffer (buffer);
+ if (G_UNLIKELY (!wlbuffer)) {
+ mem = gst_buffer_peek_memory (to_render, 0);
+ wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ if (G_UNLIKELY (!wbuf))
+ goto no_wl_buffer;
+
+ gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
+ }
- gst_buffer_map (buffer, &src, GST_MAP_READ);
- gst_buffer_fill (to_render, 0, src.data, src.size);
- gst_buffer_unmap (buffer, &src);
+ gst_buffer_map (buffer, &src, GST_MAP_READ);
+ gst_buffer_fill (to_render, 0, src.data, src.size);
+ gst_buffer_unmap (buffer, &src);
+ }
}
gst_buffer_replace (&sink->last_buffer, to_render);
}
no_buffer:
{
- GST_WARNING_OBJECT (sink, "could not create image");
+ GST_WARNING_OBJECT (sink, "could not create buffer");
goto done;
}
-no_pool:
+no_wl_buffer:
{
- GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
- ("Internal error: can't allocate images"),
- ("We don't have a bufferpool negotiated"));
+ GST_ERROR_OBJECT (sink, "could not create wl_buffer out of wl_shm memory");
ret = GST_FLOW_ERROR;
goto done;
}
GST_DEBUG_CATEGORY_INIT (gstwayland_debug, "waylandsink", 0,
" wayland video sink");
+ gst_wl_shm_allocator_register ();
+
return gst_element_register (plugin, "waylandsink", GST_RANK_MARGINAL,
GST_TYPE_WAYLAND_SINK);
}
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2012 Intel Corporation
- * Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
- * 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 St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "waylandpool.h"
-#include "wldisplay.h"
-#include "wlvideoformat.h"
-#include "wlbuffer.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-
-GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
-#define GST_CAT_DEFAULT gstwayland_debug
-
-/* bufferpool */
-static void gst_wayland_buffer_pool_finalize (GObject * object);
-static gboolean gst_wayland_buffer_pool_set_config (GstBufferPool * pool,
- GstStructure * config);
-static gboolean gst_wayland_buffer_pool_start (GstBufferPool * pool);
-static gboolean gst_wayland_buffer_pool_stop (GstBufferPool * pool);
-static GstFlowReturn gst_wayland_buffer_pool_alloc (GstBufferPool * pool,
- GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
-
-#define gst_wayland_buffer_pool_parent_class parent_class
-G_DEFINE_TYPE (GstWaylandBufferPool, gst_wayland_buffer_pool,
- GST_TYPE_BUFFER_POOL);
-
-static void
-gst_wayland_buffer_pool_class_init (GstWaylandBufferPoolClass * klass)
-{
- GObjectClass *gobject_class = (GObjectClass *) klass;
- GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
-
- gobject_class->finalize = gst_wayland_buffer_pool_finalize;
-
- gstbufferpool_class->set_config = gst_wayland_buffer_pool_set_config;
- gstbufferpool_class->start = gst_wayland_buffer_pool_start;
- gstbufferpool_class->stop = gst_wayland_buffer_pool_stop;
- gstbufferpool_class->alloc_buffer = gst_wayland_buffer_pool_alloc;
-}
-
-static void
-gst_wayland_buffer_pool_init (GstWaylandBufferPool * self)
-{
- gst_video_info_init (&self->info);
-}
-
-static void
-gst_wayland_buffer_pool_finalize (GObject * object)
-{
- GstWaylandBufferPool *pool = GST_WAYLAND_BUFFER_POOL_CAST (object);
-
- if (pool->wl_pool)
- gst_wayland_buffer_pool_stop (GST_BUFFER_POOL (pool));
-
- g_object_unref (pool->display);
-
- G_OBJECT_CLASS (gst_wayland_buffer_pool_parent_class)->finalize (object);
-}
-
-static gboolean
-gst_wayland_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
-{
- GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
- GstCaps *caps;
-
- if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
- goto wrong_config;
-
- if (caps == NULL)
- goto no_caps;
-
- /* now parse the caps from the config */
- if (!gst_video_info_from_caps (&self->info, caps))
- goto wrong_caps;
-
- GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT,
- GST_VIDEO_INFO_WIDTH (&self->info), GST_VIDEO_INFO_HEIGHT (&self->info),
- caps);
-
- /*Fixme: Enable metadata checking handling based on the config of pool */
-
- return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
- /* 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 gboolean
-gst_wayland_buffer_pool_start (GstBufferPool * pool)
-{
- GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
- guint size = 0;
- int fd;
- char filename[1024];
- static int init = 0;
-
- GST_DEBUG_OBJECT (self, "Initializing wayland buffer pool");
-
- /* configure */
- size = GST_VIDEO_INFO_SIZE (&self->info) * 15;
-
- /* allocate shm pool */
- snprintf (filename, 1024, "%s/%s-%d-%s", g_get_user_runtime_dir (),
- "wayland-shm", init++, "XXXXXX");
-
- fd = mkstemp (filename);
- if (fd < 0) {
- GST_ERROR_OBJECT (pool, "opening temp file %s failed: %s", filename,
- strerror (errno));
- return FALSE;
- }
- if (ftruncate (fd, size) < 0) {
- GST_ERROR_OBJECT (pool, "ftruncate failed: %s", strerror (errno));
- close (fd);
- return FALSE;
- }
-
- self->data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (self->data == MAP_FAILED) {
- GST_ERROR_OBJECT (pool, "mmap failed: %s", strerror (errno));
- close (fd);
- return FALSE;
- }
-
- self->wl_pool = wl_shm_create_pool (self->display->shm, fd, size);
- unlink (filename);
- close (fd);
-
- self->size = size;
- self->used = 0;
-
- return GST_BUFFER_POOL_CLASS (parent_class)->start (pool);
-}
-
-static gboolean
-gst_wayland_buffer_pool_stop (GstBufferPool * pool)
-{
- GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
-
- GST_DEBUG_OBJECT (self, "Stopping wayland buffer pool");
-
- munmap (self->data, self->size);
- wl_shm_pool_destroy (self->wl_pool);
-
- self->wl_pool = NULL;
- self->size = 0;
- self->used = 0;
-
- return GST_BUFFER_POOL_CLASS (parent_class)->stop (pool);
-}
-
-static GstFlowReturn
-gst_wayland_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
- GstBufferPoolAcquireParams * params)
-{
- GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
- gint width, height, stride;
- gsize size;
- enum wl_shm_format format;
- gint offset;
- void *data;
- struct wl_buffer *wbuffer;
-
- width = GST_VIDEO_INFO_WIDTH (&self->info);
- height = GST_VIDEO_INFO_HEIGHT (&self->info);
- stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0);
- size = GST_VIDEO_INFO_SIZE (&self->info);
- format =
- gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT (&self->info));
-
- GST_DEBUG_OBJECT (self, "Allocating buffer of size %" G_GSSIZE_FORMAT
- " (%d x %d, stride %d), format %s", size, width, height, stride,
- gst_wayland_format_to_string (format));
-
- /* try to reserve another memory block from the shm pool */
- if (self->used + size > self->size)
- goto no_buffer;
-
- offset = self->used;
- self->used += size;
- data = ((gchar *) self->data) + offset;
-
- *buffer = gst_buffer_new ();
-
- /* add the allocated memory on the GstBuffer */
- gst_buffer_append_memory (*buffer,
- gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
- size, 0, size, NULL, NULL));
-
- /* create wl_buffer and attach it on the GstBuffer via GstWlBuffer */
- wbuffer = wl_shm_pool_create_buffer (self->wl_pool, offset, width, height,
- stride, format);
- gst_buffer_add_wl_buffer (*buffer, wbuffer, self->display);
-
- return GST_FLOW_OK;
-
- /* ERROR */
-no_buffer:
- {
- GST_WARNING_OBJECT (pool, "can't create buffer");
- return GST_FLOW_ERROR;
- }
-}
-
-GstBufferPool *
-gst_wayland_buffer_pool_new (GstWlDisplay * display)
-{
- GstWaylandBufferPool *pool;
-
- g_return_val_if_fail (GST_IS_WL_DISPLAY (display), NULL);
- pool = g_object_new (GST_TYPE_WAYLAND_BUFFER_POOL, NULL);
- pool->display = g_object_ref (display);
-
- return GST_BUFFER_POOL_CAST (pool);
-}
+++ /dev/null
-/* GStreamer Wayland buffer pool
- * Copyright (C) 2012 Intel Corporation
- * Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
- * 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 St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_WAYLAND_BUFFER_POOL_H__
-#define __GST_WAYLAND_BUFFER_POOL_H__
-
-#include <gst/video/video.h>
-
-#include "wldisplay.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_WAYLAND_BUFFER_POOL (gst_wayland_buffer_pool_get_type())
-#define GST_IS_WAYLAND_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WAYLAND_BUFFER_POOL))
-#define GST_WAYLAND_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WAYLAND_BUFFER_POOL, GstWaylandBufferPool))
-#define GST_WAYLAND_BUFFER_POOL_CAST(obj) ((GstWaylandBufferPool*)(obj))
-
-typedef struct _GstWaylandBufferPool GstWaylandBufferPool;
-typedef struct _GstWaylandBufferPoolClass GstWaylandBufferPoolClass;
-
-/* buffer pool */
-struct _GstWaylandBufferPool
-{
- GstBufferPool bufferpool;
- GstWlDisplay *display;
-
- /* external configuration */
- GstVideoInfo info;
-
- /* allocation data */
- struct wl_shm_pool *wl_pool;
- size_t size;
- size_t used;
- void *data;
-};
-
-struct _GstWaylandBufferPoolClass
-{
- GstBufferPoolClass parent_class;
-};
-
-GType gst_wayland_buffer_pool_get_type (void);
-
-GstBufferPool *gst_wayland_buffer_pool_new (GstWlDisplay * display);
-
-G_END_DECLS
-
-#endif /*__GST_WAYLAND_BUFFER_POOL_H__*/
--- /dev/null
+/* GStreamer Wayland video sink
+ *
+ * Copyright (C) 2012 Intel Corporation
+ * Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
+ * 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 St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "wlshmallocator.h"
+#include "wlvideoformat.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
+#define GST_CAT_DEFAULT gstwayland_debug
+
+G_DEFINE_TYPE (GstWlShmAllocator, gst_wl_shm_allocator, GST_TYPE_ALLOCATOR);
+
+static GstMemory *
+gst_wl_shm_allocator_alloc (GstAllocator * allocator, gsize size,
+ GstAllocationParams * params)
+{
+ GstWlShmAllocator *self = GST_WL_SHM_ALLOCATOR (allocator);
+ char filename[1024];
+ static int init = 0;
+ int fd;
+ gpointer data;
+ GstWlShmMemory *mem;
+
+ /* TODO: make use of the allocation params, if necessary */
+
+ /* allocate shm pool */
+ snprintf (filename, 1024, "%s/%s-%d-%s", g_get_user_runtime_dir (),
+ "wayland-shm", init++, "XXXXXX");
+
+ fd = mkstemp (filename);
+ if (fd < 0) {
+ GST_ERROR_OBJECT (self, "opening temp file %s failed: %s", filename,
+ strerror (errno));
+ return NULL;
+ }
+ if (ftruncate (fd, size) < 0) {
+ GST_ERROR_OBJECT (self, "ftruncate failed: %s", strerror (errno));
+ close (fd);
+ return NULL;
+ }
+
+ data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED) {
+ GST_ERROR_OBJECT (self, "mmap failed: %s", strerror (errno));
+ close (fd);
+ return NULL;
+ }
+
+ unlink (filename);
+
+ mem = g_slice_new0 (GstWlShmMemory);
+ gst_memory_init ((GstMemory *) mem, GST_MEMORY_FLAG_NO_SHARE, allocator, NULL,
+ size, 0, 0, size);
+ mem->data = data;
+ mem->fd = fd;
+
+ return (GstMemory *) mem;
+}
+
+static void
+gst_wl_shm_allocator_free (GstAllocator * allocator, GstMemory * memory)
+{
+ GstWlShmMemory *shm_mem = (GstWlShmMemory *) memory;
+
+ if (shm_mem->fd != -1)
+ close (shm_mem->fd);
+ munmap (shm_mem->data, memory->maxsize);
+
+ g_slice_free (GstWlShmMemory, shm_mem);
+}
+
+static gpointer
+gst_wl_shm_mem_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
+{
+ return ((GstWlShmMemory *) mem)->data;
+}
+
+static void
+gst_wl_shm_mem_unmap (GstMemory * mem)
+{
+}
+
+static void
+gst_wl_shm_allocator_class_init (GstWlShmAllocatorClass * klass)
+{
+ GstAllocatorClass *alloc_class = (GstAllocatorClass *) klass;
+
+ alloc_class->alloc = GST_DEBUG_FUNCPTR (gst_wl_shm_allocator_alloc);
+ alloc_class->free = GST_DEBUG_FUNCPTR (gst_wl_shm_allocator_free);
+}
+
+static void
+gst_wl_shm_allocator_init (GstWlShmAllocator * self)
+{
+ self->parent_instance.mem_type = GST_ALLOCATOR_WL_SHM;
+ self->parent_instance.mem_map = gst_wl_shm_mem_map;
+ self->parent_instance.mem_unmap = gst_wl_shm_mem_unmap;
+
+ GST_OBJECT_FLAG_SET (self, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
+}
+
+void
+gst_wl_shm_allocator_register (void)
+{
+ gst_allocator_register (GST_ALLOCATOR_WL_SHM,
+ g_object_new (GST_TYPE_WL_SHM_ALLOCATOR, NULL));
+}
+
+GstAllocator *
+gst_wl_shm_allocator_get (void)
+{
+ return gst_allocator_find (GST_ALLOCATOR_WL_SHM);
+}
+
+gboolean
+gst_is_wl_shm_memory (GstMemory * mem)
+{
+ return gst_memory_is_type (mem, GST_ALLOCATOR_WL_SHM);
+}
+
+struct wl_buffer *
+gst_wl_shm_memory_construct_wl_buffer (GstMemory * mem, GstWlDisplay * display,
+ const GstVideoInfo * info)
+{
+ GstWlShmMemory *shm_mem = (GstWlShmMemory *) mem;
+ gint width, height, stride;
+ gsize size;
+ enum wl_shm_format format;
+ struct wl_shm_pool *wl_pool;
+ struct wl_buffer *wbuffer;
+
+ width = GST_VIDEO_INFO_WIDTH (info);
+ height = GST_VIDEO_INFO_HEIGHT (info);
+ stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 0);
+ size = GST_VIDEO_INFO_SIZE (info);
+ format = gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT (info));
+
+ g_return_val_if_fail (gst_is_wl_shm_memory (mem), NULL);
+ g_return_val_if_fail (size <= mem->size, NULL);
+ g_return_val_if_fail (shm_mem->fd != -1, NULL);
+
+ GST_DEBUG_OBJECT (mem->allocator, "Creating wl_buffer of size %"
+ G_GSSIZE_FORMAT " (%d x %d, stride %d), format %s", size, width, height,
+ stride, gst_wayland_format_to_string (format));
+
+ wl_pool = wl_shm_create_pool (display->shm, shm_mem->fd, mem->size);
+ wbuffer = wl_shm_pool_create_buffer (wl_pool, 0, width, height, stride,
+ format);
+
+ close (shm_mem->fd);
+ shm_mem->fd = -1;
+ wl_shm_pool_destroy (wl_pool);
+
+ return wbuffer;
+}
--- /dev/null
+/* GStreamer Wayland video sink
+ *
+ * Copyright (C) 2012 Intel Corporation
+ * Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
+ * 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 St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_WL_SHM_ALLOCATOR_H__
+#define __GST_WL_SHM_ALLOCATOR_H__
+
+#include <gst/video/video.h>
+#include <wayland-client-protocol.h>
+#include "wldisplay.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_WL_SHM_ALLOCATOR (gst_wl_shm_allocator_get_type ())
+#define GST_WL_SHM_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_SHM_ALLOCATOR, GstWlShmAllocator))
+#define GST_IS_WL_SHM_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_SHM_ALLOCATOR))
+#define GST_WL_SHM_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_SHM_ALLOCATOR, GstWlShmAllocatorClass))
+#define GST_IS_WL_SHM_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_SHM_ALLOCATOR))
+#define GST_WL_SHM_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_SHM_ALLOCATOR, GstWlShmAllocatorClass))
+
+#define GST_ALLOCATOR_WL_SHM "wl_shm"
+
+typedef struct _GstWlShmMemory GstWlShmMemory;
+typedef struct _GstWlShmAllocator GstWlShmAllocator;
+typedef struct _GstWlShmAllocatorClass GstWlShmAllocatorClass;
+
+struct _GstWlShmMemory
+{
+ GstMemory parent;
+
+ gpointer data;
+ gint fd;
+};
+
+struct _GstWlShmAllocator
+{
+ GstAllocator parent_instance;
+};
+
+struct _GstWlShmAllocatorClass
+{
+ GstAllocatorClass parent_class;
+};
+
+GType gst_wl_shm_allocator_get_type (void);
+
+void gst_wl_shm_allocator_register (void);
+GstAllocator * gst_wl_shm_allocator_get (void);
+
+gboolean gst_is_wl_shm_memory (GstMemory * mem);
+struct wl_buffer * gst_wl_shm_memory_construct_wl_buffer (GstMemory * mem,
+ GstWlDisplay * display, const GstVideoInfo * info);
+
+G_END_DECLS
+
+#endif /* __GST_WL_SHM_ALLOCATOR_H__ */