diff --git a/ext/wayland/Makefile.am b/ext/wayland/Makefile.am index 73aae2cd4b..e12d99a8f1 100644 --- a/ext/wayland/Makefile.am +++ b/ext/wayland/Makefile.am @@ -2,7 +2,7 @@ plugin_LTLIBRARIES = libgstwaylandsink.la libgstwaylandsink_la_SOURCES = \ gstwaylandsink.c \ - waylandpool.c \ + wlshmallocator.c \ wlbuffer.c \ wldisplay.c \ wlwindow.c \ @@ -21,7 +21,7 @@ libgstwaylandsink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) noinst_HEADERS = \ gstwaylandsink.h \ - waylandpool.h \ + wlshmallocator.h \ wlbuffer.h \ wldisplay.h \ wlwindow.h \ @@ -39,7 +39,7 @@ CLEANFILES = scaler-protocol.c scaler-client-protocol.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 diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c index 1e2c11ddd3..e081280fa7 100644 --- a/ext/wayland/gstwaylandsink.c +++ b/ext/wayland/gstwaylandsink.c @@ -43,8 +43,8 @@ #include "gstwaylandsink.h" #include "wlvideoformat.h" -#include "waylandpool.h" #include "wlbuffer.h" +#include "wlshmallocator.h" #include #include @@ -362,9 +362,9 @@ gst_wayland_sink_change_state (GstElement * element, GstStateChange transition) * - 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; @@ -451,7 +451,6 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) GArray *formats; gint i; GstStructure *structure; - static GstAllocationParams params = { 0, 0, 0, 15, }; sink = GST_WAYLAND_SINK (bsink); @@ -476,13 +475,14 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) 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; @@ -524,76 +524,18 @@ static gboolean 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; + guint size, min_bufs, max_bufs; - gst_query_parse_allocation (query, &caps, &need_pool); + config = gst_buffer_pool_get_config (sink->pool); + gst_buffer_pool_config_get_params (config, NULL, &size, &min_bufs, &max_bufs); - if (caps == NULL) - goto no_caps; - - if (sink->pool) - pool = gst_object_ref (sink->pool); - - 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); - } - - 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 @@ -691,26 +633,63 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer) 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; - if (!sink->pool) - goto no_pool; + GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our " + "display, creating it", buffer); - if (!gst_buffer_pool_set_active (sink->pool, TRUE)) - goto activate_failed; + mem = gst_buffer_peek_memory (buffer, 0); - ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL); - if (ret != GST_FLOW_OK) - goto no_buffer; + if (gst_is_wl_shm_memory (mem)) { + wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display, + &sink->video_info); + } - gst_buffer_map (buffer, &src, GST_MAP_READ); - gst_buffer_fill (to_render, 0, src.data, src.size); - gst_buffer_unmap (buffer, &src); + 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_replace (&sink->last_buffer, to_render); @@ -730,14 +709,12 @@ no_window_size: } 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; } @@ -887,6 +864,8 @@ plugin_init (GstPlugin * plugin) 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); } diff --git a/ext/wayland/waylandpool.c b/ext/wayland/waylandpool.c deleted file mode 100644 index 94758c8f35..0000000000 --- a/ext/wayland/waylandpool.c +++ /dev/null @@ -1,257 +0,0 @@ -/* GStreamer - * Copyright (C) 2012 Intel Corporation - * Copyright (C) 2012 Sreerenj Balachandran - * 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 -#include -#include -#include -#include -#include -#include - -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); -} diff --git a/ext/wayland/waylandpool.h b/ext/wayland/waylandpool.h deleted file mode 100644 index e0944d0252..0000000000 --- a/ext/wayland/waylandpool.h +++ /dev/null @@ -1,66 +0,0 @@ -/* GStreamer Wayland buffer pool - * Copyright (C) 2012 Intel Corporation - * Copyright (C) 2012 Sreerenj Balachandran - * 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 - -#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__*/ diff --git a/ext/wayland/wlshmallocator.c b/ext/wayland/wlshmallocator.c new file mode 100644 index 0000000000..78d6334931 --- /dev/null +++ b/ext/wayland/wlshmallocator.c @@ -0,0 +1,181 @@ +/* GStreamer Wayland video sink + * + * Copyright (C) 2012 Intel Corporation + * Copyright (C) 2012 Sreerenj Balachandran + * 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 +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/ext/wayland/wlshmallocator.h b/ext/wayland/wlshmallocator.h new file mode 100644 index 0000000000..f12882cbc8 --- /dev/null +++ b/ext/wayland/wlshmallocator.h @@ -0,0 +1,74 @@ +/* GStreamer Wayland video sink + * + * Copyright (C) 2012 Intel Corporation + * Copyright (C) 2012 Sreerenj Balachandran + * 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 +#include +#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__ */