mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
wayland: More fixes based on wayland-0.95.0 and gstreamer-1.0 apis
- bump wayland version to 0.95.0 which will lead to stable 1.0 release - avoid memcopy and use propose_allocation for GstBufferPool allocation - using WaylandBufferPool - shm: Allocate shm buffers through new wl_shm_pool interface (the shm buffer allocation is a two step process now: first allocate a wl_shm_pool, then allocate a buffer from the pool) https://bugzilla.gnome.org/show_bug.cgi?id=681453
This commit is contained in:
parent
38c749ca2f
commit
c803ca4af5
6 changed files with 628 additions and 170 deletions
|
@ -898,7 +898,7 @@ AG_GST_CHECK_FEATURE(DIRECTFB, [directfb], dfbvideosink , [
|
||||||
dnl **** Wayland ****
|
dnl **** Wayland ****
|
||||||
translit(dnm, m, l) AM_CONDITIONAL(USE_WAYLAND, true)
|
translit(dnm, m, l) AM_CONDITIONAL(USE_WAYLAND, true)
|
||||||
AG_GST_CHECK_FEATURE(WAYLAND, [wayland sink], wayland , [
|
AG_GST_CHECK_FEATURE(WAYLAND, [wayland sink], wayland , [
|
||||||
PKG_CHECK_MODULES(WAYLAND, wayland-server <= 0.85.0 wayland-client <= 0.85.0, [
|
PKG_CHECK_MODULES(WAYLAND, wayland-server >= 0.95.0 wayland-client >= 0.95.0, [
|
||||||
AC_CHECK_HEADER(wayland-client.h, HAVE_WAYLAND_CLIENT="yes", HAVE_WAYLAND_CLIENT="no")
|
AC_CHECK_HEADER(wayland-client.h, HAVE_WAYLAND_CLIENT="yes", HAVE_WAYLAND_CLIENT="no")
|
||||||
AC_CHECK_HEADER(wayland-client-protocol.h, HAVE_WAYLAND_CLIENT_PROTOCOL="yes", HAVE_WAYLAND_CLIENT_PROTOCOL="no")
|
AC_CHECK_HEADER(wayland-client-protocol.h, HAVE_WAYLAND_CLIENT_PROTOCOL="yes", HAVE_WAYLAND_CLIENT_PROTOCOL="no")
|
||||||
if test "x$HAVE_WAYLAND_CLIENT" = "xno"; then
|
if test "x$HAVE_WAYLAND_CLIENT" = "xno"; then
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
plugin_LTLIBRARIES = libgstwaylandsink.la
|
plugin_LTLIBRARIES = libgstwaylandsink.la
|
||||||
|
|
||||||
libgstwaylandsink_la_SOURCES = gstwaylandsink.c
|
libgstwaylandsink_la_SOURCES = gstwaylandsink.c waylandpool.c
|
||||||
libgstwaylandsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
|
libgstwaylandsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
|
||||||
$(WAYLAND_CFLAGS)
|
$(WAYLAND_CFLAGS)
|
||||||
libgstwaylandsink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
|
libgstwaylandsink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
|
||||||
|
@ -9,4 +9,4 @@ libgstwaylandsink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
|
||||||
libgstwaylandsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
libgstwaylandsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
libgstwaylandsink_la_LIBTOOLFLAGS = --tag=disable-static
|
libgstwaylandsink_la_LIBTOOLFLAGS = --tag=disable-static
|
||||||
|
|
||||||
noinst_HEADERS = gstwaylandsink.h
|
noinst_HEADERS = gstwaylandsink.h waylandpool.h
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/*
|
/* GStreamer Wayland video sink
|
||||||
* GStreamer Wayland video sink
|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Intel Corporation
|
* Copyright (C) 2011 Intel Corporation
|
||||||
* Copyright (C) 2011 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
|
* Copyright (C) 2011 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
|
||||||
|
@ -47,7 +46,6 @@
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SIGNAL_0,
|
SIGNAL_0,
|
||||||
SIGNAL_FRAME_READY,
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,44 +71,6 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
#define gst_wayland_sink_parent_class parent_class
|
#define gst_wayland_sink_parent_class parent_class
|
||||||
G_DEFINE_TYPE (GstWaylandSink, gst_wayland_sink, GST_TYPE_VIDEO_SINK);
|
G_DEFINE_TYPE (GstWaylandSink, gst_wayland_sink, GST_TYPE_VIDEO_SINK);
|
||||||
|
|
||||||
/* wl metadata */
|
|
||||||
GType
|
|
||||||
gst_wl_meta_api_get_type (void)
|
|
||||||
{
|
|
||||||
static volatile GType type;
|
|
||||||
static const gchar *tags[] =
|
|
||||||
{ "memory", "size", "colorspace", "orientation", NULL };
|
|
||||||
|
|
||||||
if (g_once_init_enter (&type)) {
|
|
||||||
GType _type = gst_meta_api_type_register ("GstWlMetaAPI", tags);
|
|
||||||
g_once_init_leave (&type, _type);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_wl_meta_free (GstWlMeta * meta, GstBuffer * buffer)
|
|
||||||
{
|
|
||||||
gst_object_unref (meta->sink);
|
|
||||||
munmap (meta->data, meta->size);
|
|
||||||
wl_buffer_destroy (meta->wbuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
const GstMetaInfo *
|
|
||||||
gst_wl_meta_get_info (void)
|
|
||||||
{
|
|
||||||
static const GstMetaInfo *wl_meta_info = NULL;
|
|
||||||
|
|
||||||
if (wl_meta_info == NULL) {
|
|
||||||
wl_meta_info =
|
|
||||||
gst_meta_register (GST_WL_META_API_TYPE, "GstWlMeta",
|
|
||||||
sizeof (GstWlMeta), (GstMetaInitFunction) NULL,
|
|
||||||
(GstMetaFreeFunction) gst_wl_meta_free,
|
|
||||||
(GstMetaTransformFunction) NULL);
|
|
||||||
}
|
|
||||||
return wl_meta_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gst_wayland_sink_get_property (GObject * object,
|
static void gst_wayland_sink_get_property (GObject * object,
|
||||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||||
static void gst_wayland_sink_set_property (GObject * object,
|
static void gst_wayland_sink_set_property (GObject * object,
|
||||||
|
@ -123,6 +83,8 @@ static gboolean gst_wayland_sink_start (GstBaseSink * bsink);
|
||||||
static gboolean gst_wayland_sink_stop (GstBaseSink * bsink);
|
static gboolean gst_wayland_sink_stop (GstBaseSink * bsink);
|
||||||
static gboolean gst_wayland_sink_preroll (GstBaseSink * bsink,
|
static gboolean gst_wayland_sink_preroll (GstBaseSink * bsink,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
|
static gboolean
|
||||||
|
gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query);
|
||||||
static gboolean gst_wayland_sink_render (GstBaseSink * bsink,
|
static gboolean gst_wayland_sink_render (GstBaseSink * bsink,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
|
|
||||||
|
@ -130,9 +92,11 @@ static int event_mask_update (uint32_t mask, void *data);
|
||||||
static struct display *create_display (void);
|
static struct display *create_display (void);
|
||||||
static void display_handle_global (struct wl_display *display, uint32_t id,
|
static void display_handle_global (struct wl_display *display, uint32_t id,
|
||||||
const char *interface, uint32_t version, void *data);
|
const char *interface, uint32_t version, void *data);
|
||||||
static void redraw (void *data, struct wl_callback *callback, uint32_t time);
|
static void frame_redraw_callback (void *data, struct wl_callback *callback,
|
||||||
|
uint32_t time);
|
||||||
static void create_window (GstWaylandSink * sink, struct display *display,
|
static void create_window (GstWaylandSink * sink, struct display *display,
|
||||||
int width, int height);
|
int width, int height);
|
||||||
|
static void shm_pool_destroy (struct shm_pool *pool);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
|
gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
|
||||||
|
@ -162,6 +126,8 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
|
||||||
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_wayland_sink_start);
|
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_wayland_sink_start);
|
||||||
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_wayland_sink_stop);
|
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_wayland_sink_stop);
|
||||||
gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_wayland_sink_preroll);
|
gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_wayland_sink_preroll);
|
||||||
|
gstbasesink_class->propose_allocation =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_wayland_sink_propose_allocation);
|
||||||
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_wayland_sink_render);
|
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_wayland_sink_render);
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_WAYLAND_DISPLAY,
|
g_object_class_install_property (gobject_class, PROP_WAYLAND_DISPLAY,
|
||||||
|
@ -173,9 +139,10 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_wayland_sink_init (GstWaylandSink * sink)
|
gst_wayland_sink_init (GstWaylandSink * sink)
|
||||||
{
|
{
|
||||||
sink->render_busy = FALSE;
|
|
||||||
sink->display = NULL;
|
sink->display = NULL;
|
||||||
sink->window = NULL;
|
sink->window = NULL;
|
||||||
|
sink->shm_pool = NULL;
|
||||||
|
sink->pool = NULL;
|
||||||
|
|
||||||
g_mutex_init (&sink->wayland_lock);
|
g_mutex_init (&sink->wayland_lock);
|
||||||
}
|
}
|
||||||
|
@ -225,20 +192,36 @@ destroy_display (struct display *display)
|
||||||
wl_compositor_destroy (display->compositor);
|
wl_compositor_destroy (display->compositor);
|
||||||
|
|
||||||
wl_display_flush (display->display);
|
wl_display_flush (display->display);
|
||||||
wl_display_destroy (display->display);
|
wl_display_disconnect (display->display);
|
||||||
free (display);
|
free (display);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_window (struct window *window)
|
destroy_window (struct window *window)
|
||||||
{
|
{
|
||||||
|
if (window->callback)
|
||||||
|
wl_callback_destroy (window->callback);
|
||||||
|
|
||||||
|
if (window->buffer)
|
||||||
|
wl_buffer_destroy (window->buffer);
|
||||||
|
|
||||||
if (window->shell_surface)
|
if (window->shell_surface)
|
||||||
wl_shell_surface_destroy (window->shell_surface);
|
wl_shell_surface_destroy (window->shell_surface);
|
||||||
|
|
||||||
if (window->surface)
|
if (window->surface)
|
||||||
wl_surface_destroy (window->surface);
|
wl_surface_destroy (window->surface);
|
||||||
|
|
||||||
free (window);
|
free (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shm_pool_destroy (struct shm_pool *pool)
|
||||||
|
{
|
||||||
|
munmap (pool->data, pool->size);
|
||||||
|
wl_shm_pool_destroy (pool->pool);
|
||||||
|
free (pool);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_wayland_sink_finalize (GObject * object)
|
gst_wayland_sink_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
|
@ -250,6 +233,8 @@ gst_wayland_sink_finalize (GObject * object)
|
||||||
destroy_window (sink->window);
|
destroy_window (sink->window);
|
||||||
if (sink->display)
|
if (sink->display)
|
||||||
destroy_display (sink->display);
|
destroy_display (sink->display);
|
||||||
|
if (sink->shm_pool)
|
||||||
|
shm_pool_destroy (sink->shm_pool);
|
||||||
|
|
||||||
g_mutex_clear (&sink->wayland_lock);
|
g_mutex_clear (&sink->wayland_lock);
|
||||||
|
|
||||||
|
@ -259,7 +244,21 @@ gst_wayland_sink_finalize (GObject * object)
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
|
gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
|
||||||
{
|
{
|
||||||
return gst_static_pad_template_get_caps (&sink_template);
|
GstWaylandSink *sink;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
sink = GST_WAYLAND_SINK (bsink);
|
||||||
|
|
||||||
|
caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
|
||||||
|
if (filter) {
|
||||||
|
GstCaps *intersection;
|
||||||
|
|
||||||
|
intersection =
|
||||||
|
gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
caps = intersection;
|
||||||
|
}
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -308,7 +307,7 @@ create_display (void)
|
||||||
|
|
||||||
display = malloc (sizeof *display);
|
display = malloc (sizeof *display);
|
||||||
display->display = wl_display_connect (NULL);
|
display->display = wl_display_connect (NULL);
|
||||||
assert (display->display);
|
g_return_val_if_fail (display->display, NULL);
|
||||||
|
|
||||||
wl_display_add_global_listener (display->display,
|
wl_display_add_global_listener (display->display,
|
||||||
display_handle_global, display);
|
display_handle_global, display);
|
||||||
|
@ -326,92 +325,62 @@ create_display (void)
|
||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstBuffer *
|
|
||||||
wayland_buffer_create (GstWaylandSink * sink)
|
|
||||||
{
|
|
||||||
char filename[1024];
|
|
||||||
int fd, size, stride;
|
|
||||||
static void *data;
|
|
||||||
static int init = 0;
|
|
||||||
GstBuffer *buffer;
|
|
||||||
GstWlMeta *wmeta;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (sink, "Creating wayland-shm buffers");
|
|
||||||
|
|
||||||
snprintf (filename, 256, "%s-%d-%s", "/tmp/wayland-shm", init++, "XXXXXX");
|
|
||||||
|
|
||||||
fd = mkstemp (filename);
|
|
||||||
if (fd < 0) {
|
|
||||||
GST_ERROR_OBJECT (sink, "open %s failed:", filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
stride = sink->video_width * 4;
|
|
||||||
size = stride * sink->video_height;
|
|
||||||
|
|
||||||
if (ftruncate (fd, size) < 0) {
|
|
||||||
GST_ERROR_OBJECT (sink, "ftruncate failed:");
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
unlink (filename);
|
|
||||||
if (data == MAP_FAILED) {
|
|
||||||
GST_ELEMENT_ERROR (sink, LIBRARY, SHUTDOWN, (NULL),
|
|
||||||
("mmap() failed: %s", strerror (errno)));
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = gst_buffer_new ();
|
|
||||||
|
|
||||||
wmeta = (GstWlMeta *) gst_buffer_add_meta (buffer, GST_WL_META_INFO, NULL);
|
|
||||||
wmeta->sink = gst_object_ref (sink);
|
|
||||||
wmeta->wbuffer = wl_shm_create_buffer (sink->display->shm, fd,
|
|
||||||
sink->video_width, sink->video_height, stride, WL_SHM_FORMAT_XRGB8888);
|
|
||||||
wmeta->data = data;
|
|
||||||
wmeta->size = size;
|
|
||||||
|
|
||||||
close (fd);
|
|
||||||
|
|
||||||
gst_buffer_append_memory (buffer,
|
|
||||||
gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
|
|
||||||
size, 0, size, NULL, NULL));
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
|
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
|
||||||
const GstStructure *structure;
|
GstBufferPool *newpool, *oldpool;
|
||||||
gboolean ret = TRUE;
|
GstVideoInfo info;
|
||||||
|
GstStructure *structure;
|
||||||
|
static GstAllocationParams params = { 0, 0, 0, 15, };
|
||||||
|
guint size;
|
||||||
|
|
||||||
|
sink = GST_WAYLAND_SINK (bsink);
|
||||||
|
|
||||||
GST_LOG_OBJECT (sink, "set caps %" GST_PTR_FORMAT, caps);
|
GST_LOG_OBJECT (sink, "set caps %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
if (!gst_video_info_from_caps (&info, caps))
|
||||||
|
goto invalid_format;
|
||||||
|
|
||||||
ret &= gst_structure_get_int (structure, "width", &sink->video_width);
|
sink->video_width = info.width;
|
||||||
ret &= gst_structure_get_int (structure, "height", &sink->video_height);
|
sink->video_height = info.height;
|
||||||
|
size = info.size;
|
||||||
|
|
||||||
if (!ret)
|
/* create a new pool for the new configuration */
|
||||||
|
newpool = gst_wayland_buffer_pool_new (sink);
|
||||||
|
|
||||||
|
if (!newpool) {
|
||||||
|
GST_DEBUG_OBJECT (sink, "Failed to create new pool");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
structure = gst_buffer_pool_get_config (newpool);
|
||||||
|
gst_buffer_pool_config_set_params (structure, caps, size, 2, 0);
|
||||||
|
gst_buffer_pool_config_set_allocator (structure, NULL, ¶ms);
|
||||||
|
if (!gst_buffer_pool_set_config (newpool, structure))
|
||||||
|
goto config_failed;
|
||||||
|
|
||||||
|
oldpool = sink->pool;
|
||||||
|
sink->pool = newpool;
|
||||||
|
if (oldpool)
|
||||||
|
gst_object_unref (oldpool);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
invalid_format:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (sink,
|
||||||
|
"Could not locate image format from caps %" GST_PTR_FORMAT, caps);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
config_failed:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (bsink, "failed setting config");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener;
|
static const struct wl_callback_listener frame_callback_listener;
|
||||||
|
|
||||||
static void
|
|
||||||
redraw (void *data, struct wl_callback *callback, uint32_t time)
|
|
||||||
{
|
|
||||||
|
|
||||||
GstWaylandSink *sink = (GstWaylandSink *) data;
|
|
||||||
|
|
||||||
sink->render_busy = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_window (GstWaylandSink * sink, struct display *display, int width,
|
create_window (GstWaylandSink * sink, struct display *display, int width,
|
||||||
|
@ -428,15 +397,15 @@ create_window (GstWaylandSink * sink, struct display *display, int width,
|
||||||
window->display = display;
|
window->display = display;
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->height = height;
|
window->height = height;
|
||||||
|
window->redraw_pending = FALSE;
|
||||||
|
|
||||||
window->surface = wl_compositor_create_surface (display->compositor);
|
window->surface = wl_compositor_create_surface (display->compositor);
|
||||||
|
|
||||||
window->shell_surface = wl_shell_get_shell_surface (display->shell,
|
window->shell_surface = wl_shell_get_shell_surface (display->shell,
|
||||||
window->surface);
|
window->surface);
|
||||||
/* wl_shell_surface_set_toplevel (window->shell_surface); */
|
wl_shell_surface_set_toplevel (window->shell_surface);
|
||||||
#ifdef WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT
|
|
||||||
wl_shell_surface_set_fullscreen (window->shell_surface,
|
wl_shell_surface_set_fullscreen (window->shell_surface,
|
||||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL);
|
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
sink->window = window;
|
sink->window = window;
|
||||||
|
|
||||||
|
@ -467,6 +436,84 @@ gst_wayland_sink_stop (GstBaseSink * bsink)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
|
{
|
||||||
|
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
|
||||||
|
GstBufferPool *pool;
|
||||||
|
GstStructure *config;
|
||||||
|
GstCaps *caps;
|
||||||
|
guint size;
|
||||||
|
gboolean need_pool;
|
||||||
|
|
||||||
|
gst_query_parse_allocation (query, &caps, &need_pool);
|
||||||
|
|
||||||
|
if (caps == NULL)
|
||||||
|
goto no_caps;
|
||||||
|
|
||||||
|
g_mutex_lock (&sink->wayland_lock);
|
||||||
|
if ((pool = sink->pool))
|
||||||
|
gst_object_ref (pool);
|
||||||
|
g_mutex_unlock (&sink->wayland_lock);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* 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
|
||||||
gst_wayland_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
|
gst_wayland_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
@ -474,6 +521,18 @@ gst_wayland_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
return gst_wayland_sink_render (bsink, buffer);
|
return gst_wayland_sink_render (bsink, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
frame_redraw_callback (void *data, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
struct window *window = (struct window *) data;
|
||||||
|
window->redraw_pending = FALSE;
|
||||||
|
wl_callback_destroy (callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_callback_listener frame_callback_listener = {
|
||||||
|
frame_redraw_callback
|
||||||
|
};
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
@ -481,14 +540,21 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
GstVideoRectangle src, dst, res;
|
GstVideoRectangle src, dst, res;
|
||||||
GstBuffer *to_render;
|
GstBuffer *to_render;
|
||||||
GstWlMeta *meta;
|
GstWlMeta *meta;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
struct window *window;
|
||||||
|
struct display *display;
|
||||||
|
|
||||||
GST_LOG_OBJECT (sink, "render buffer %p", buffer);
|
GST_LOG_OBJECT (sink, "render buffer %p", buffer);
|
||||||
|
|
||||||
if (!sink->window)
|
if (!sink->window)
|
||||||
create_window (sink, sink->display, sink->video_width, sink->video_height);
|
create_window (sink, sink->display, sink->video_width, sink->video_height);
|
||||||
|
|
||||||
if (sink->render_busy)
|
window = sink->window;
|
||||||
goto was_busy;
|
display = sink->display;
|
||||||
|
|
||||||
|
/* Wait for the previous frame to complete redraw */
|
||||||
|
if (window->redraw_pending) {
|
||||||
|
wl_display_iterate (display->display, WL_DISPLAY_READABLE);
|
||||||
|
}
|
||||||
|
|
||||||
meta = gst_buffer_get_wl_meta (buffer);
|
meta = gst_buffer_get_wl_meta (buffer);
|
||||||
|
|
||||||
|
@ -497,10 +563,17 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
to_render = buffer;
|
to_render = buffer;
|
||||||
} else {
|
} else {
|
||||||
GstMapInfo src;
|
GstMapInfo src;
|
||||||
|
|
||||||
GST_LOG_OBJECT (sink, "buffer %p not from our pool, copying", buffer);
|
GST_LOG_OBJECT (sink, "buffer %p not from our pool, copying", buffer);
|
||||||
|
|
||||||
to_render = wayland_buffer_create (sink);
|
if (!sink->pool)
|
||||||
|
goto no_pool;
|
||||||
|
|
||||||
|
if (!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;
|
||||||
|
|
||||||
gst_buffer_map (buffer, &src, GST_MAP_READ);
|
gst_buffer_map (buffer, &src, GST_MAP_READ);
|
||||||
gst_buffer_fill (to_render, 0, src.data, src.size);
|
gst_buffer_fill (to_render, 0, src.data, src.size);
|
||||||
|
@ -516,36 +589,37 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
|
|
||||||
gst_video_sink_center_rect (src, dst, &res, FALSE);
|
gst_video_sink_center_rect (src, dst, &res, FALSE);
|
||||||
|
|
||||||
sink->render_busy = TRUE;
|
|
||||||
|
|
||||||
wl_buffer_damage (meta->wbuffer, 0, 0, res.w, res.h);
|
|
||||||
wl_surface_attach (sink->window->surface, meta->wbuffer, 0, 0);
|
wl_surface_attach (sink->window->surface, meta->wbuffer, 0, 0);
|
||||||
wl_surface_damage (sink->window->surface, 0, 0, res.w, res.h);
|
wl_surface_damage (sink->window->surface, 0, 0, res.w, res.h);
|
||||||
|
wl_display_iterate (display->display, WL_DISPLAY_WRITABLE);
|
||||||
if (sink->callback)
|
window->redraw_pending = TRUE;
|
||||||
wl_callback_destroy (sink->callback);
|
window->callback = wl_surface_frame (window->surface);
|
||||||
|
wl_callback_add_listener (window->callback, &frame_callback_listener, window);
|
||||||
sink->callback = wl_surface_frame (sink->window->surface);
|
|
||||||
wl_callback_add_listener (sink->callback, &frame_listener, sink);
|
|
||||||
wl_display_iterate (sink->display->display, sink->display->mask);
|
|
||||||
|
|
||||||
if (buffer != to_render)
|
if (buffer != to_render)
|
||||||
gst_buffer_unref (to_render);
|
gst_buffer_unref (to_render);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
was_busy:
|
no_buffer:
|
||||||
{
|
{
|
||||||
GST_LOG_OBJECT (sink,
|
GST_WARNING_OBJECT (sink, "could not create image");
|
||||||
"Waiting to get the signal from compositor to render the next frame..");
|
return ret;
|
||||||
return GST_FLOW_OK;
|
}
|
||||||
|
no_pool:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
|
||||||
|
("Internal error: can't allocate images"),
|
||||||
|
("We don't have a bufferpool negotiated"));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
activate_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (sink, "failed to activate bufferpool.");
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener = {
|
|
||||||
redraw
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GstPlugin * plugin)
|
plugin_init (GstPlugin * plugin)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
#include <gst/video/gstvideosink.h>
|
#include <gst/video/gstvideosink.h>
|
||||||
|
#include <gst/video/gstvideometa.h>
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
@ -70,29 +71,23 @@ struct window
|
||||||
int width, height;
|
int width, height;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct wl_shell_surface *shell_surface;
|
struct wl_shell_surface *shell_surface;
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
struct wl_callback *callback;
|
||||||
|
guint redraw_pending :1;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shm_pool {
|
||||||
|
struct wl_shm_pool *pool;
|
||||||
|
size_t size;
|
||||||
|
size_t used;
|
||||||
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _GstWaylandSink GstWaylandSink;
|
typedef struct _GstWaylandSink GstWaylandSink;
|
||||||
typedef struct _GstWaylandSinkClass GstWaylandSinkClass;
|
typedef struct _GstWaylandSinkClass GstWaylandSinkClass;
|
||||||
|
|
||||||
typedef struct _GstWlMeta GstWlMeta;
|
#include "waylandpool.h"
|
||||||
|
|
||||||
GType gst_wl_meta_api_get_type (void);
|
|
||||||
#define GST_WL_META_API_TYPE (gst_wl_meta_api_get_type())
|
|
||||||
const GstMetaInfo * gst_wl_meta_get_info (void);
|
|
||||||
#define GST_WL_META_INFO (gst_wl_meta_get_info())
|
|
||||||
|
|
||||||
#define gst_buffer_get_wl_meta(b) ((GstWlMeta*)gst_buffer_get_meta((b),GST_WL_META_API_TYPE))
|
|
||||||
|
|
||||||
struct _GstWlMeta {
|
|
||||||
GstMeta meta;
|
|
||||||
|
|
||||||
GstWaylandSink *sink;
|
|
||||||
|
|
||||||
struct wl_buffer *wbuffer;
|
|
||||||
void *data;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstWaylandSink
|
struct _GstWaylandSink
|
||||||
{
|
{
|
||||||
|
@ -100,15 +95,14 @@ struct _GstWaylandSink
|
||||||
|
|
||||||
struct display *display;
|
struct display *display;
|
||||||
struct window *window;
|
struct window *window;
|
||||||
struct wl_callback *callback;
|
struct shm_pool *shm_pool;
|
||||||
|
|
||||||
|
GstBufferPool *pool;
|
||||||
|
|
||||||
GMutex wayland_lock;
|
GMutex wayland_lock;
|
||||||
|
|
||||||
gint video_width;
|
gint video_width;
|
||||||
gint video_height;
|
gint video_height;
|
||||||
guint bpp;
|
|
||||||
|
|
||||||
gboolean render_busy;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstWaylandSinkClass
|
struct _GstWaylandSinkClass
|
||||||
|
|
311
ext/wayland/waylandpool.c
Normal file
311
ext/wayland/waylandpool.c
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 2012 Intel Corporation
|
||||||
|
* Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
|
||||||
|
|
||||||
|
* 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., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Object header */
|
||||||
|
#include "gstwaylandsink.h"
|
||||||
|
|
||||||
|
/* Debugging category */
|
||||||
|
#include <gst/gstinfo.h>
|
||||||
|
|
||||||
|
/* Helper functions */
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/gstvideometa.h>
|
||||||
|
#include <gst/video/gstvideopool.h>
|
||||||
|
|
||||||
|
/* wl metadata */
|
||||||
|
GType
|
||||||
|
gst_wl_meta_api_get_type (void)
|
||||||
|
{
|
||||||
|
static volatile GType type;
|
||||||
|
static const gchar *tags[] =
|
||||||
|
{ "memory", "size", "colorspace", "orientation", NULL };
|
||||||
|
|
||||||
|
if (g_once_init_enter (&type)) {
|
||||||
|
GType _type = gst_meta_api_type_register ("GstWlMetaAPI", tags);
|
||||||
|
g_once_init_leave (&type, _type);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_wl_meta_free (GstWlMeta * meta, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
gst_object_unref (meta->sink);
|
||||||
|
munmap (meta->data, meta->size);
|
||||||
|
wl_buffer_destroy (meta->wbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GstMetaInfo *
|
||||||
|
gst_wl_meta_get_info (void)
|
||||||
|
{
|
||||||
|
static const GstMetaInfo *wl_meta_info = NULL;
|
||||||
|
|
||||||
|
if (wl_meta_info == NULL) {
|
||||||
|
wl_meta_info =
|
||||||
|
gst_meta_register (GST_WL_META_API_TYPE, "GstWlMeta",
|
||||||
|
sizeof (GstWlMeta), (GstMetaInitFunction) NULL,
|
||||||
|
(GstMetaFreeFunction) gst_wl_meta_free,
|
||||||
|
(GstMetaTransformFunction) NULL);
|
||||||
|
}
|
||||||
|
return wl_meta_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bufferpool */
|
||||||
|
static void gst_wayland_buffer_pool_finalize (GObject * object);
|
||||||
|
|
||||||
|
#define gst_wayland_buffer_pool_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE (GstWaylandBufferPool, gst_wayland_buffer_pool,
|
||||||
|
GST_TYPE_BUFFER_POOL);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
wayland_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
|
||||||
|
{
|
||||||
|
GstWaylandBufferPool *wpool = GST_WAYLAND_BUFFER_POOL_CAST (pool);
|
||||||
|
GstVideoInfo info;
|
||||||
|
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 (&info, caps))
|
||||||
|
goto wrong_caps;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height,
|
||||||
|
caps);
|
||||||
|
|
||||||
|
/*Fixme: Enable metadata checking handling based on the config of pool */
|
||||||
|
|
||||||
|
wpool->caps = gst_caps_ref (caps);
|
||||||
|
wpool->info = info;
|
||||||
|
wpool->width = info.width;
|
||||||
|
wpool->height = info.height;
|
||||||
|
|
||||||
|
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 struct wl_shm_pool *
|
||||||
|
make_shm_pool (struct display *display, int size, void **data)
|
||||||
|
{
|
||||||
|
struct wl_shm_pool *pool;
|
||||||
|
int fd;
|
||||||
|
char filename[1024];
|
||||||
|
static int init = 0;
|
||||||
|
|
||||||
|
snprintf (filename, 256, "%s-%d-%s", "/tmp/wayland-shm", init++, "XXXXXX");
|
||||||
|
|
||||||
|
fd = mkstemp (filename);
|
||||||
|
if (fd < 0) {
|
||||||
|
GST_ERROR ("open %s failed:", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (ftruncate (fd, size) < 0) {
|
||||||
|
GST_ERROR ("ftruncate failed:..!");
|
||||||
|
close (fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (*data == MAP_FAILED) {
|
||||||
|
GST_ERROR ("mmap failed: ");
|
||||||
|
close (fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = wl_shm_create_pool (display->shm, fd, size);
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct shm_pool *
|
||||||
|
shm_pool_create (struct display *display, size_t size)
|
||||||
|
{
|
||||||
|
struct shm_pool *pool = malloc (sizeof *pool);
|
||||||
|
|
||||||
|
if (!pool)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pool->pool = make_shm_pool (display, size, &pool->data);
|
||||||
|
if (!pool->pool) {
|
||||||
|
free (pool);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool->size = size;
|
||||||
|
pool->used = 0;
|
||||||
|
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
shm_pool_allocate (struct shm_pool *pool, size_t size, int *offset)
|
||||||
|
{
|
||||||
|
if (pool->used + size > pool->size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*offset = pool->used;
|
||||||
|
pool->used += size;
|
||||||
|
|
||||||
|
return (char *) pool->data + *offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start allocating from the beginning of the pool again */
|
||||||
|
static void
|
||||||
|
shm_pool_reset (struct shm_pool *pool)
|
||||||
|
{
|
||||||
|
pool->used = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstWlMeta *
|
||||||
|
gst_buffer_add_wayland_meta (GstBuffer * buffer, GstWaylandBufferPool * wpool)
|
||||||
|
{
|
||||||
|
GstWlMeta *wmeta;
|
||||||
|
GstWaylandSink *sink;
|
||||||
|
void *data;
|
||||||
|
gint offset;
|
||||||
|
guint stride = 0;
|
||||||
|
guint size = 0;
|
||||||
|
|
||||||
|
sink = wpool->sink;
|
||||||
|
stride = wpool->width * 4;
|
||||||
|
size = stride * wpool->height;
|
||||||
|
|
||||||
|
wmeta = (GstWlMeta *) gst_buffer_add_meta (buffer, GST_WL_META_INFO, NULL);
|
||||||
|
wmeta->sink = gst_object_ref (sink);
|
||||||
|
|
||||||
|
/*Fixme: size calculation should be more grcefull, have to consider the padding */
|
||||||
|
if (!sink->shm_pool) {
|
||||||
|
sink->shm_pool = shm_pool_create (sink->display, size * 15);
|
||||||
|
shm_pool_reset (sink->shm_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sink->shm_pool) {
|
||||||
|
GST_ERROR ("Failed to create shm_pool");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = shm_pool_allocate (sink->shm_pool, size, &offset);
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wmeta->wbuffer = wl_shm_pool_create_buffer (sink->shm_pool->pool, offset,
|
||||||
|
sink->video_width, sink->video_height, stride, WL_SHM_FORMAT_XRGB8888);
|
||||||
|
|
||||||
|
wmeta->data = data;
|
||||||
|
wmeta->size = size;
|
||||||
|
|
||||||
|
gst_buffer_append_memory (buffer,
|
||||||
|
gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
|
||||||
|
size, 0, size, NULL, NULL));
|
||||||
|
|
||||||
|
|
||||||
|
return wmeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
wayland_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
|
||||||
|
GstBufferPoolAcquireParams * params)
|
||||||
|
{
|
||||||
|
GstWaylandBufferPool *w_pool = GST_WAYLAND_BUFFER_POOL_CAST (pool);
|
||||||
|
GstBuffer *w_buffer;
|
||||||
|
GstWlMeta *meta;
|
||||||
|
|
||||||
|
w_buffer = gst_buffer_new ();
|
||||||
|
meta = gst_buffer_add_wayland_meta (w_buffer, w_pool);
|
||||||
|
if (meta == NULL) {
|
||||||
|
gst_buffer_unref (w_buffer);
|
||||||
|
goto no_buffer;
|
||||||
|
}
|
||||||
|
*buffer = w_buffer;
|
||||||
|
|
||||||
|
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 (GstWaylandSink * waylandsink)
|
||||||
|
{
|
||||||
|
GstWaylandBufferPool *pool;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_WAYLAND_SINK (waylandsink), NULL);
|
||||||
|
pool = g_object_new (GST_TYPE_WAYLAND_BUFFER_POOL, NULL);
|
||||||
|
pool->sink = gst_object_ref (waylandsink);
|
||||||
|
|
||||||
|
return GST_BUFFER_POOL_CAST (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 = wayland_buffer_pool_set_config;
|
||||||
|
gstbufferpool_class->alloc_buffer = wayland_buffer_pool_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_wayland_buffer_pool_init (GstWaylandBufferPool * pool)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_wayland_buffer_pool_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstWaylandBufferPool *pool = GST_WAYLAND_BUFFER_POOL_CAST (object);
|
||||||
|
|
||||||
|
gst_object_unref (pool->sink);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_wayland_buffer_pool_parent_class)->finalize (object);
|
||||||
|
}
|
79
ext/wayland/waylandpool.h
Normal file
79
ext/wayland/waylandpool.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/* GStreamer Wayland buffer pool
|
||||||
|
* Copyright (C) 2012 Intel Corporation
|
||||||
|
* Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_WAYLAND_BUFFER_POOL_H__
|
||||||
|
#define __GST_WAYLAND_BUFFER_POOL_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#include "gstwaylandsink.h"
|
||||||
|
typedef struct _GstWlMeta GstWlMeta;
|
||||||
|
|
||||||
|
typedef struct _GstWaylandBufferPool GstWaylandBufferPool;
|
||||||
|
typedef struct _GstWaylandBufferPoolClass GstWaylandBufferPoolClass;
|
||||||
|
|
||||||
|
GType gst_wl_meta_api_get_type (void);
|
||||||
|
#define GST_WL_META_API_TYPE (gst_wl_meta_api_get_type())
|
||||||
|
const GstMetaInfo * gst_wl_meta_get_info (void);
|
||||||
|
#define GST_WL_META_INFO (gst_wl_meta_get_info())
|
||||||
|
|
||||||
|
#define gst_buffer_get_wl_meta(b) ((GstWlMeta*)gst_buffer_get_meta((b),GST_WL_META_API_TYPE))
|
||||||
|
|
||||||
|
struct _GstWlMeta {
|
||||||
|
GstMeta meta;
|
||||||
|
|
||||||
|
GstWaylandSink *sink;
|
||||||
|
|
||||||
|
struct wl_buffer *wbuffer;
|
||||||
|
void *data;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* buffer pool functions */
|
||||||
|
#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))
|
||||||
|
|
||||||
|
struct _GstWaylandBufferPool
|
||||||
|
{
|
||||||
|
GstBufferPool bufferpool;
|
||||||
|
|
||||||
|
GstWaylandSink *sink;
|
||||||
|
|
||||||
|
/*Fixme: keep all these in GstWaylandBufferPoolPrivate*/
|
||||||
|
GstCaps *caps;
|
||||||
|
GstVideoInfo info;
|
||||||
|
guint width;
|
||||||
|
guint height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstWaylandBufferPoolClass
|
||||||
|
{
|
||||||
|
GstBufferPoolClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_wayland_buffer_pool_get_type (void);
|
||||||
|
|
||||||
|
GstBufferPool *gst_wayland_buffer_pool_new (GstWaylandSink * waylandsink);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /*__GST_WAYLAND_BUFFER_POOL_H__*/
|
Loading…
Reference in a new issue