2 * Copyright (C) 2012 Intel Corporation
3 * Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include "waylandpool.h"
26 #include "wldisplay.h"
27 #include "wlvideoformat.h"
35 #include <sys/types.h>
37 GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
38 #define GST_CAT_DEFAULT gstwayland_debug
42 gst_wl_meta_api_get_type (void)
44 static volatile GType type;
45 static const gchar *tags[] =
46 { "memory", "size", "colorspace", "orientation", NULL };
48 if (g_once_init_enter (&type)) {
49 GType _type = gst_meta_api_type_register ("GstWlMetaAPI", tags);
50 g_once_init_leave (&type, _type);
56 gst_wl_meta_free (GstWlMeta * meta, GstBuffer * buffer)
58 gst_object_unref (meta->sink);
59 munmap (meta->data, meta->size);
60 wl_buffer_destroy (meta->wbuffer);
64 gst_wl_meta_get_info (void)
66 static const GstMetaInfo *wl_meta_info = NULL;
68 if (g_once_init_enter (&wl_meta_info)) {
69 const GstMetaInfo *meta =
70 gst_meta_register (GST_WL_META_API_TYPE, "GstWlMeta",
71 sizeof (GstWlMeta), (GstMetaInitFunction) NULL,
72 (GstMetaFreeFunction) gst_wl_meta_free,
73 (GstMetaTransformFunction) NULL);
74 g_once_init_leave (&wl_meta_info, meta);
80 static void gst_wayland_buffer_pool_finalize (GObject * object);
81 static gboolean gst_wayland_buffer_pool_set_config (GstBufferPool * pool,
82 GstStructure * config);
83 static gboolean gst_wayland_buffer_pool_start (GstBufferPool * pool);
84 static gboolean gst_wayland_buffer_pool_stop (GstBufferPool * pool);
85 static GstFlowReturn gst_wayland_buffer_pool_alloc (GstBufferPool * pool,
86 GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
88 #define gst_wayland_buffer_pool_parent_class parent_class
89 G_DEFINE_TYPE (GstWaylandBufferPool, gst_wayland_buffer_pool,
90 GST_TYPE_BUFFER_POOL);
93 gst_wayland_buffer_pool_class_init (GstWaylandBufferPoolClass * klass)
95 GObjectClass *gobject_class = (GObjectClass *) klass;
96 GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
98 gobject_class->finalize = gst_wayland_buffer_pool_finalize;
100 gstbufferpool_class->set_config = gst_wayland_buffer_pool_set_config;
101 gstbufferpool_class->start = gst_wayland_buffer_pool_start;
102 gstbufferpool_class->stop = gst_wayland_buffer_pool_stop;
103 gstbufferpool_class->alloc_buffer = gst_wayland_buffer_pool_alloc;
107 gst_wayland_buffer_pool_init (GstWaylandBufferPool * self)
109 gst_video_info_init (&self->info);
113 gst_wayland_buffer_pool_finalize (GObject * object)
115 GstWaylandBufferPool *pool = GST_WAYLAND_BUFFER_POOL_CAST (object);
118 gst_wayland_buffer_pool_stop (GST_BUFFER_POOL (pool));
120 gst_object_unref (pool->sink);
122 G_OBJECT_CLASS (gst_wayland_buffer_pool_parent_class)->finalize (object);
126 gst_wayland_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
128 GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
131 if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
137 /* now parse the caps from the config */
138 if (!gst_video_info_from_caps (&self->info, caps))
141 GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT,
142 GST_VIDEO_INFO_WIDTH (&self->info), GST_VIDEO_INFO_HEIGHT (&self->info),
145 /*Fixme: Enable metadata checking handling based on the config of pool */
147 return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
151 GST_WARNING_OBJECT (pool, "invalid config");
156 GST_WARNING_OBJECT (pool, "no caps in config");
161 GST_WARNING_OBJECT (pool,
162 "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
168 gst_wayland_buffer_pool_start (GstBufferPool * pool)
170 GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
176 GST_DEBUG_OBJECT (self, "Initializing wayland buffer pool");
179 size = GST_VIDEO_INFO_SIZE (&self->info) * 15;
181 /* allocate shm pool */
182 snprintf (filename, 1024, "%s/%s-%d-%s", g_get_user_runtime_dir (),
183 "wayland-shm", init++, "XXXXXX");
185 fd = mkstemp (filename);
187 GST_ERROR_OBJECT (pool, "opening temp file %s failed: %s", filename,
191 if (ftruncate (fd, size) < 0) {
192 GST_ERROR_OBJECT (pool, "ftruncate failed: %s", strerror (errno));
197 self->data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
198 if (self->data == MAP_FAILED) {
199 GST_ERROR_OBJECT (pool, "mmap failed: %s", strerror (errno));
205 wl_shm_create_pool (self->sink->display->shm,
216 gst_wayland_buffer_pool_stop (GstBufferPool * pool)
218 GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
220 GST_DEBUG_OBJECT (self, "Stopping wayland buffer pool");
222 munmap (self->data, self->size);
223 wl_shm_pool_destroy (self->wl_pool);
225 self->wl_pool = NULL;
233 gst_wayland_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
234 GstBufferPoolAcquireParams * params)
236 GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
237 gint width, height, stride;
239 enum wl_shm_format format;
244 width = GST_VIDEO_INFO_WIDTH (&self->info);
245 height = GST_VIDEO_INFO_HEIGHT (&self->info);
246 stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0);
247 size = GST_VIDEO_INFO_SIZE (&self->info);
249 gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT (&self->info));
251 GST_DEBUG_OBJECT (self, "Allocating buffer of size %" G_GSSIZE_FORMAT
252 " (%d x %d, stride %d), format %s", size, width, height, stride,
253 gst_wayland_format_to_string (format));
255 /* try to reserve another memory block from the shm pool */
256 if (self->used + size > self->size)
261 data = ((gchar *) self->data) + offset;
263 /* create buffer and its metadata object */
264 *buffer = gst_buffer_new ();
265 meta = (GstWlMeta *) gst_buffer_add_meta (*buffer, GST_WL_META_INFO, NULL);
266 meta->sink = gst_object_ref (self->sink);
267 meta->wbuffer = wl_shm_pool_create_buffer (self->wl_pool, offset,
268 width, height, stride, format);
272 /* add the allocated memory on the GstBuffer */
273 gst_buffer_append_memory (*buffer,
274 gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
275 size, 0, size, NULL, NULL));
282 GST_WARNING_OBJECT (pool, "can't create buffer");
283 return GST_FLOW_ERROR;
288 gst_wayland_buffer_pool_new (GstWaylandSink * waylandsink)
290 GstWaylandBufferPool *pool;
292 g_return_val_if_fail (GST_IS_WAYLAND_SINK (waylandsink), NULL);
293 pool = g_object_new (GST_TYPE_WAYLAND_BUFFER_POOL, NULL);
294 pool->sink = gst_object_ref (waylandsink);
296 return GST_BUFFER_POOL_CAST (pool);