From ae6aebd9d5561954d19d6a61d0bd346b751adeed Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Thu, 13 Feb 2014 11:59:45 +0100 Subject: [PATCH] waylandsink: split window-related code out to a new GstWlWindow class GstWlWindow also has API ready to support subsurfaces. --- ext/wayland/Makefile.am | 7 +- ext/wayland/gstwaylandsink.c | 91 +++-------------------- ext/wayland/gstwaylandsink.h | 11 +-- ext/wayland/wlwindow.c | 167 +++++++++++++++++++++++++++++++++++++++++++ ext/wayland/wlwindow.h | 65 +++++++++++++++++ 5 files changed, 249 insertions(+), 92 deletions(-) create mode 100644 ext/wayland/wlwindow.c create mode 100644 ext/wayland/wlwindow.h diff --git a/ext/wayland/Makefile.am b/ext/wayland/Makefile.am index 60cbf7e..ffc13ef 100644 --- a/ext/wayland/Makefile.am +++ b/ext/wayland/Makefile.am @@ -1,7 +1,7 @@ plugin_LTLIBRARIES = libgstwaylandsink.la -libgstwaylandsink_la_SOURCES = gstwaylandsink.c waylandpool.c wldisplay.c \ - wlvideoformat.c +libgstwaylandsink_la_SOURCES = gstwaylandsink.c waylandpool.c \ + wldisplay.c wlwindow.c wlvideoformat.c libgstwaylandsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ $(WAYLAND_CFLAGS) libgstwaylandsink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ @@ -10,4 +10,5 @@ libgstwaylandsink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ libgstwaylandsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstwaylandsink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) -noinst_HEADERS = gstwaylandsink.h waylandpool.h wldisplay.h wlvideoformat.h +noinst_HEADERS = gstwaylandsink.h waylandpool.h \ + wldisplay.h wlwindow.h wlvideoformat.h diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c index 0767a0e..6c12c35 100644 --- a/ext/wayland/gstwaylandsink.c +++ b/ext/wayland/gstwaylandsink.c @@ -94,8 +94,6 @@ static gboolean gst_wayland_sink_render (GstBaseSink * bsink, static void frame_redraw_callback (void *data, struct wl_callback *callback, uint32_t time); -static void create_window (GstWaylandSink * sink, GstWlDisplay * display, - int width, int height); static void gst_wayland_sink_class_init (GstWaylandSinkClass * klass) @@ -177,18 +175,6 @@ gst_wayland_sink_set_property (GObject * object, } static void -destroy_window (struct window *window) -{ - if (window->shell_surface) - wl_shell_surface_destroy (window->shell_surface); - - if (window->surface) - wl_surface_destroy (window->surface); - - free (window); -} - -static void gst_wayland_sink_finalize (GObject * object) { GstWaylandSink *sink = GST_WAYLAND_SINK (object); @@ -196,7 +182,7 @@ gst_wayland_sink_finalize (GObject * object) GST_DEBUG_OBJECT (sink, "Finalizing the sink.."); if (sink->window) - destroy_window (sink->window); + g_object_unref (sink->window); if (sink->display) g_object_unref (sink->display); @@ -289,62 +275,6 @@ config_failed: } } -static void -handle_ping (void *data, struct wl_shell_surface *shell_surface, - uint32_t serial) -{ - wl_shell_surface_pong (shell_surface, serial); -} - -static void -handle_configure (void *data, struct wl_shell_surface *shell_surface, - uint32_t edges, int32_t width, int32_t height) -{ -} - -static void -handle_popup_done (void *data, struct wl_shell_surface *shell_surface) -{ -} - -static const struct wl_shell_surface_listener shell_surface_listener = { - handle_ping, - handle_configure, - handle_popup_done -}; - -static void -create_window (GstWaylandSink * sink, GstWlDisplay * display, int width, - int height) -{ - struct window *window; - - if (sink->window) - return; - - g_mutex_lock (&sink->wayland_lock); - - window = malloc (sizeof *window); - window->width = width; - window->height = height; - - window->surface = wl_compositor_create_surface (display->compositor); - - window->shell_surface = wl_shell_get_shell_surface (display->shell, - window->surface); - - g_return_if_fail (window->shell_surface); - - wl_shell_surface_add_listener (window->shell_surface, - &shell_surface_listener, window); - - wl_shell_surface_set_toplevel (window->shell_surface); - - sink->window = window; - - g_mutex_unlock (&sink->wayland_lock); -} - static gboolean gst_wayland_sink_start (GstBaseSink * bsink) { @@ -471,14 +401,13 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer) GstBuffer *to_render; GstWlMeta *meta; GstFlowReturn ret; - struct window *window; + struct wl_surface *surface; struct wl_callback *callback; GST_LOG_OBJECT (sink, "render buffer %p", buffer); if (!sink->window) - create_window (sink, sink->display, sink->video_width, sink->video_height); - - window = sink->window; + sink->window = gst_wl_window_new_toplevel (sink->display, sink->video_width, + sink->video_height); meta = gst_buffer_get_wl_meta (buffer); @@ -513,11 +442,13 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer) gst_video_sink_center_rect (src, dst, &res, FALSE); - wl_surface_attach (sink->window->surface, meta->wbuffer, 0, 0); - wl_surface_damage (sink->window->surface, 0, 0, res.w, res.h); - callback = wl_surface_frame (window->surface); - wl_callback_add_listener (callback, &frame_callback_listener, window); - wl_surface_commit (window->surface); + surface = gst_wl_window_get_wl_surface (sink->window); + + wl_surface_attach (surface, meta->wbuffer, 0, 0); + wl_surface_damage (surface, 0, 0, res.w, res.h); + callback = wl_surface_frame (surface); + wl_callback_add_listener (callback, &frame_callback_listener, NULL); + wl_surface_commit (surface); wl_display_flush (sink->display->display); if (buffer != to_render) diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h index 9dfddbd..c72b54c 100644 --- a/ext/wayland/gstwaylandsink.h +++ b/ext/wayland/gstwaylandsink.h @@ -43,6 +43,7 @@ #include #include "wldisplay.h" +#include "wlwindow.h" G_BEGIN_DECLS @@ -59,13 +60,6 @@ G_BEGIN_DECLS #define GST_WAYLAND_SINK_GET_CLASS(inst) \ (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_WAYLAND_SINK, GstWaylandSinkClass)) -struct window -{ - int width, height; - struct wl_surface *surface; - struct wl_shell_surface *shell_surface; -}; - typedef struct _GstWaylandSink GstWaylandSink; typedef struct _GstWaylandSinkClass GstWaylandSinkClass; @@ -78,8 +72,7 @@ struct _GstWaylandSink GstVideoSink parent; GstWlDisplay *display; - struct window *window; - + GstWlWindow *window; GstBufferPool *pool; GMutex wayland_lock; diff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c new file mode 100644 index 0000000..97107ef --- /dev/null +++ b/ext/wayland/wlwindow.c @@ -0,0 +1,167 @@ +/* GStreamer Wayland video sink + * + * Copyright (C) 2011 Intel Corporation + * Copyright (C) 2011 Sreerenj Balachandran + * Copyright (C) 2014 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include "wlwindow.h" + +G_DEFINE_TYPE (GstWlWindow, gst_wl_window, G_TYPE_OBJECT); + +static void gst_wl_window_finalize (GObject * gobject); + +static void +handle_ping (void *data, struct wl_shell_surface *shell_surface, + uint32_t serial) +{ + wl_shell_surface_pong (shell_surface, serial); +} + +static void +handle_configure (void *data, struct wl_shell_surface *shell_surface, + uint32_t edges, int32_t width, int32_t height) +{ +} + +static void +handle_popup_done (void *data, struct wl_shell_surface *shell_surface) +{ +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + handle_ping, + handle_configure, + handle_popup_done +}; + +static void +gst_wl_window_class_init (GstWlWindowClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gst_wl_window_finalize; +} + +static void +gst_wl_window_init (GstWlWindow * self) +{ +} + +static void +gst_wl_window_finalize (GObject * gobject) +{ + GstWlWindow *self = GST_WL_WINDOW (gobject); + + if (self->shell_surface) { + wl_shell_surface_destroy (self->shell_surface); + } + + if (self->own_surface) { + wl_surface_destroy (self->surface); + } + + g_clear_object (&self->display); + + G_OBJECT_CLASS (gst_wl_window_parent_class)->finalize (gobject); +} + +GstWlWindow * +gst_wl_window_new_toplevel (GstWlDisplay * display, gint width, gint height) +{ + GstWlWindow *window; + + window = g_object_new (GST_TYPE_WL_WINDOW, NULL); + window->display = g_object_ref (display); + window->width = width; + window->height = height; + + window->surface = wl_compositor_create_surface (display->compositor); + window->own_surface = TRUE; + + window->shell_surface = wl_shell_get_shell_surface (display->shell, + window->surface); + + if (window->shell_surface) { + wl_shell_surface_add_listener (window->shell_surface, + &shell_surface_listener, window); + wl_shell_surface_set_toplevel (window->shell_surface); + } else { + GST_ERROR ("Unable to get wl_shell_surface"); + + g_object_unref (window); + return NULL; + } + + return window; +} + +GstWlWindow * +gst_wl_window_new_from_surface (GstWlDisplay * display, + struct wl_surface * surface, gint width, gint height) +{ + GstWlWindow *window; + + g_return_val_if_fail (surface != NULL, NULL); + + window = g_object_new (GST_TYPE_WL_WINDOW, NULL); + window->display = g_object_ref (display); + window->width = width; + window->height = height; + + window->surface = surface; + window->own_surface = FALSE; + + return window; +} + +GstWlDisplay * +gst_wl_window_get_display (GstWlWindow * window) +{ + g_return_val_if_fail (window != NULL, NULL); + + return g_object_ref (window->display); +} + +struct wl_surface * +gst_wl_window_get_wl_surface (GstWlWindow * window) +{ + g_return_val_if_fail (window != NULL, NULL); + + return window->surface; +} + +void +gst_wl_window_get_size (GstWlWindow * window, gint * w, gint * h) +{ + g_return_if_fail (window != NULL); + + if (w) + *w = window->width; + + if (h) + *h = window->height; +} + +void +gst_wl_window_set_size (GstWlWindow * window, gint w, gint h) +{ + g_return_if_fail (window != NULL); + + window->width = w; + window->height = h; +} diff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h new file mode 100644 index 0000000..8ba6a91 --- /dev/null +++ b/ext/wayland/wlwindow.h @@ -0,0 +1,65 @@ +/* GStreamer Wayland video sink + * + * 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 Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __GST_WL_WINDOW_H__ +#define __GST_WL_WINDOW_H__ + +#include "wldisplay.h" + +#define GST_TYPE_WL_WINDOW (gst_wl_window_get_type ()) +#define GST_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_WINDOW, GstWlWindow)) +#define GST_IS_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_WINDOW)) +#define GST_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_WINDOW, GstWlWindowClass)) +#define GST_IS_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_WINDOW)) +#define GST_WL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_WINDOW, GstWlWindowClass)) + +typedef struct _GstWlWindow GstWlWindow; +typedef struct _GstWlWindowClass GstWlWindowClass; + +struct _GstWlWindow +{ + GObject parent_instance; + + GstWlDisplay *display; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + gint width, height; + gboolean own_surface; +}; + +struct _GstWlWindowClass +{ + GObjectClass parent_class; +}; + +GType gst_wl_window_get_type (void); + +GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display, + gint width, gint height); +GstWlWindow *gst_wl_window_new_from_surface (GstWlDisplay * display, + struct wl_surface * surface, gint width, gint height); + +GstWlDisplay *gst_wl_window_get_display (GstWlWindow * window); +struct wl_surface *gst_wl_window_get_wl_surface (GstWlWindow * window); + +void gst_wl_window_get_size (GstWlWindow * window, gint * w, gint * h); +void gst_wl_window_set_size (GstWlWindow * window, gint w, gint h); + +#endif /* __GST_WL_WINDOW_H__ */ -- 2.7.4