mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 08:41:07 +00:00
waylandsink: replace the custom buffer pool with an allocator
This reduces the complexity of having a custom buffer pool, as we don't really need it. We only need the custom allocation part. And since the wl_buffer is no longer saved in a GstMeta, we can create it and add it on the buffers in the sink's render() function, which removes the reference cycle caused by the pool holding a reference to the display and also allows more generic scenarios (the allocator being used in another pool, or buffers being allocated without a pool [if anything stupid does that]). This commit also simplifies the propose_allocation() function, which doesn't really need to do all these complicated checks, since there is always a correct buffer pool available, created in set_caps(). The other side effect of this commit is that a new wl_shm_pool is now created for every GstMemory, which means that we use as much shm memory as we actually need and no more. Previously, the created wl_shm_pool would allocate space for 15 buffers, no matter if they were being used or not.
This commit is contained in:
parent
9807d58b01
commit
d7bddb0c51
6 changed files with 326 additions and 415 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -43,8 +43,8 @@
|
|||
|
||||
#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>
|
||||
|
@ -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,27 +633,64 @@ 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 {
|
||||
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);
|
||||
|
||||
mem = gst_buffer_peek_memory (buffer, 0);
|
||||
|
||||
if (gst_is_wl_shm_memory (mem)) {
|
||||
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
||||
&sink->video_info);
|
||||
}
|
||||
|
||||
if (wbuf) {
|
||||
gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
|
||||
to_render = buffer;
|
||||
} else {
|
||||
GstMapInfo src;
|
||||
GST_LOG_OBJECT (sink, "buffer %p not from our pool, copying", buffer);
|
||||
/* 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... */
|
||||
|
||||
if (!sink->pool)
|
||||
goto no_pool;
|
||||
GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, "
|
||||
"copying to wl_shm memory", buffer);
|
||||
|
||||
if (!gst_buffer_pool_set_active (sink->pool, TRUE))
|
||||
/* 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);
|
||||
render_last_buffer (sink);
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,257 +0,0 @@
|
|||
/* 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);
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/* 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__*/
|
181
ext/wayland/wlshmallocator.c
Normal file
181
ext/wayland/wlshmallocator.c
Normal file
|
@ -0,0 +1,181 @@
|
|||
/* 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;
|
||||
}
|
74
ext/wayland/wlshmallocator.h
Normal file
74
ext/wayland/wlshmallocator.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* 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__ */
|
Loading…
Reference in a new issue