mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 07:28:53 +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 = \
|
libgstwaylandsink_la_SOURCES = \
|
||||||
gstwaylandsink.c \
|
gstwaylandsink.c \
|
||||||
waylandpool.c \
|
wlshmallocator.c \
|
||||||
wlbuffer.c \
|
wlbuffer.c \
|
||||||
wldisplay.c \
|
wldisplay.c \
|
||||||
wlwindow.c \
|
wlwindow.c \
|
||||||
|
@ -21,7 +21,7 @@ libgstwaylandsink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
gstwaylandsink.h \
|
gstwaylandsink.h \
|
||||||
waylandpool.h \
|
wlshmallocator.h \
|
||||||
wlbuffer.h \
|
wlbuffer.h \
|
||||||
wldisplay.h \
|
wldisplay.h \
|
||||||
wlwindow.h \
|
wlwindow.h \
|
||||||
|
@ -39,7 +39,7 @@ CLEANFILES = scaler-protocol.c scaler-client-protocol.h
|
||||||
|
|
||||||
gstwaylandsink.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
|
wlbuffer.c: scaler-client-protocol.h
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,8 @@
|
||||||
|
|
||||||
#include "gstwaylandsink.h"
|
#include "gstwaylandsink.h"
|
||||||
#include "wlvideoformat.h"
|
#include "wlvideoformat.h"
|
||||||
#include "waylandpool.h"
|
|
||||||
#include "wlbuffer.h"
|
#include "wlbuffer.h"
|
||||||
|
#include "wlshmallocator.h"
|
||||||
|
|
||||||
#include <gst/wayland/wayland.h>
|
#include <gst/wayland/wayland.h>
|
||||||
#include <gst/video/videooverlay.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 */
|
* - see the comment on wlbuffer.c for details */
|
||||||
gst_wl_display_stop (sink->display);
|
gst_wl_display_stop (sink->display);
|
||||||
g_clear_object (&sink->display);
|
g_clear_object (&sink->display);
|
||||||
g_clear_object (&sink->pool);
|
|
||||||
}
|
}
|
||||||
g_mutex_unlock (&sink->display_lock);
|
g_mutex_unlock (&sink->display_lock);
|
||||||
|
g_clear_object (&sink->pool);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -451,7 +451,6 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
GArray *formats;
|
GArray *formats;
|
||||||
gint i;
|
gint i;
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
static GstAllocationParams params = { 0, 0, 0, 15, };
|
|
||||||
|
|
||||||
sink = GST_WAYLAND_SINK (bsink);
|
sink = GST_WAYLAND_SINK (bsink);
|
||||||
|
|
||||||
|
@ -476,13 +475,14 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
goto unsupported_format;
|
goto unsupported_format;
|
||||||
|
|
||||||
/* create a new pool for the new configuration */
|
/* create a new pool for the new configuration */
|
||||||
newpool = gst_wayland_buffer_pool_new (sink->display);
|
newpool = gst_video_buffer_pool_new ();
|
||||||
if (!newpool)
|
if (!newpool)
|
||||||
goto pool_failed;
|
goto pool_failed;
|
||||||
|
|
||||||
structure = gst_buffer_pool_get_config (newpool);
|
structure = gst_buffer_pool_get_config (newpool);
|
||||||
gst_buffer_pool_config_set_params (structure, caps, info.size, 2, 0);
|
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))
|
if (!gst_buffer_pool_set_config (newpool, structure))
|
||||||
goto config_failed;
|
goto config_failed;
|
||||||
|
|
||||||
|
@ -524,76 +524,18 @@ static gboolean
|
||||||
gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
{
|
{
|
||||||
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
|
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
|
||||||
GstBufferPool *pool = NULL;
|
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
GstCaps *caps;
|
guint size, min_bufs, max_bufs;
|
||||||
guint size;
|
|
||||||
gboolean need_pool;
|
|
||||||
|
|
||||||
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)
|
/* we do have a pool for sure (created in set_caps),
|
||||||
goto no_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);
|
||||||
if (sink->pool)
|
gst_query_add_allocation_param (query, gst_wl_shm_allocator_get (), NULL);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
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
|
static GstFlowReturn
|
||||||
|
@ -691,26 +633,63 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
|
|
||||||
wlbuffer = gst_buffer_get_wl_buffer (buffer);
|
wlbuffer = gst_buffer_get_wl_buffer (buffer);
|
||||||
|
|
||||||
if (wlbuffer && wlbuffer->display == sink->display) {
|
if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)) {
|
||||||
GST_LOG_OBJECT (sink, "buffer %p from our pool, writing directly", buffer);
|
GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, "
|
||||||
|
"writing directly", buffer);
|
||||||
to_render = buffer;
|
to_render = buffer;
|
||||||
} else {
|
} else {
|
||||||
GstMapInfo src;
|
GstMemory *mem;
|
||||||
GST_LOG_OBJECT (sink, "buffer %p not from our pool, copying", buffer);
|
struct wl_buffer *wbuf = NULL;
|
||||||
|
|
||||||
if (!sink->pool)
|
GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our "
|
||||||
goto no_pool;
|
"display, creating it", buffer);
|
||||||
|
|
||||||
if (!gst_buffer_pool_set_active (sink->pool, TRUE))
|
mem = gst_buffer_peek_memory (buffer, 0);
|
||||||
goto activate_failed;
|
|
||||||
|
|
||||||
ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
|
if (gst_is_wl_shm_memory (mem)) {
|
||||||
if (ret != GST_FLOW_OK)
|
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
||||||
goto no_buffer;
|
&sink->video_info);
|
||||||
|
}
|
||||||
|
|
||||||
gst_buffer_map (buffer, &src, GST_MAP_READ);
|
if (wbuf) {
|
||||||
gst_buffer_fill (to_render, 0, src.data, src.size);
|
gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
|
||||||
gst_buffer_unmap (buffer, &src);
|
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);
|
gst_buffer_replace (&sink->last_buffer, to_render);
|
||||||
|
@ -730,14 +709,12 @@ no_window_size:
|
||||||
}
|
}
|
||||||
no_buffer:
|
no_buffer:
|
||||||
{
|
{
|
||||||
GST_WARNING_OBJECT (sink, "could not create image");
|
GST_WARNING_OBJECT (sink, "could not create buffer");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
no_pool:
|
no_wl_buffer:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
|
GST_ERROR_OBJECT (sink, "could not create wl_buffer out of wl_shm memory");
|
||||||
("Internal error: can't allocate images"),
|
|
||||||
("We don't have a bufferpool negotiated"));
|
|
||||||
ret = GST_FLOW_ERROR;
|
ret = GST_FLOW_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -887,6 +864,8 @@ plugin_init (GstPlugin * plugin)
|
||||||
GST_DEBUG_CATEGORY_INIT (gstwayland_debug, "waylandsink", 0,
|
GST_DEBUG_CATEGORY_INIT (gstwayland_debug, "waylandsink", 0,
|
||||||
" wayland video sink");
|
" wayland video sink");
|
||||||
|
|
||||||
|
gst_wl_shm_allocator_register ();
|
||||||
|
|
||||||
return gst_element_register (plugin, "waylandsink", GST_RANK_MARGINAL,
|
return gst_element_register (plugin, "waylandsink", GST_RANK_MARGINAL,
|
||||||
GST_TYPE_WAYLAND_SINK);
|
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