From a8f8d1b03250d22da22ec0ffa7b14fbe096e794f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 14 Aug 2015 17:13:39 +0200 Subject: [PATCH] playback/player: player: Refactor video rendering API There's a GstPlayerVideoRenderer interface now, which defines how video rendering happens in GstPlayer. Included is an implementation for the GstVideoOverlay interface, and inside the GTK example application one for gtksink/gtkglsink. --- playback/player/gst-play/gst-play.c | 2 +- playback/player/gtk/Makefile.am | 4 +- playback/player/gtk/gtk-play.c | 44 +++--- playback/player/gtk/gtk-video-renderer.c | 178 +++++++++++++++++++++++ playback/player/gtk/gtk-video-renderer.h | 49 +++++++ 5 files changed, 249 insertions(+), 28 deletions(-) create mode 100644 playback/player/gtk/gtk-video-renderer.c create mode 100644 playback/player/gtk/gtk-video-renderer.h diff --git a/playback/player/gst-play/gst-play.c b/playback/player/gst-play/gst-play.c index 368b814e8a..84176690ed 100644 --- a/playback/player/gst-play/gst-play.c +++ b/playback/player/gst-play/gst-play.c @@ -352,7 +352,7 @@ play_new (gchar ** uris, gdouble initial_volume) play->cur_idx = -1; play->player = - gst_player_new_full (gst_player_g_main_context_signal_dispatcher_new + gst_player_new_full (NULL, gst_player_g_main_context_signal_dispatcher_new (NULL)); g_signal_connect (play->player, "position-updated", diff --git a/playback/player/gtk/Makefile.am b/playback/player/gtk/Makefile.am index f7e6d0f58b..8e2331a983 100644 --- a/playback/player/gtk/Makefile.am +++ b/playback/player/gtk/Makefile.am @@ -26,11 +26,11 @@ gtk-play-resources.h: resources/gresources.xml \ BUILT_SOURCES: gtk-play-resources.c gtk-play-resources.h -gtk_play_SOURCES = gtk-play.c gtk-play-resources.c +gtk_play_SOURCES = gtk-play.c gtk-play-resources.c gtk-video-renderer.c LDADD = $(top_builddir)/lib/gst/player/.libs/libgstplayer-@GST_PLAYER_API_VERSION@.la \ $(GSTREAMER_LIBS) $(GTK_LIBS) $(GTK_X11_LIBS) $(GLIB_LIBS) $(LIBM) $(GMODULE_LIBS) AM_CFLAGS = -I$(top_srcdir)/lib -I$(top_builddir)/lib $(GSTREAMER_CFLAGS) $(GTK_CFLAGS) $(GTK_X11_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) -noinst_HEADERS = gtk-play-resources.h +noinst_HEADERS = gtk-play-resources.h gtk-video-renderer.h diff --git a/playback/player/gtk/gtk-play.c b/playback/player/gtk/gtk-play.c index c601f32a81..906a672bab 100644 --- a/playback/player/gtk/gtk-play.c +++ b/playback/player/gtk/gtk-play.c @@ -39,6 +39,7 @@ #include #include +#include "gtk-video-renderer.h" #define APP_NAME "gtk-play" @@ -58,6 +59,7 @@ typedef struct GtkApplicationWindow parent; GstPlayer *player; + GstPlayerVideoRenderer *renderer; gchar *uri; GList *uris; @@ -182,7 +184,8 @@ video_area_realize_cb (GtkWidget * widget, GtkPlay * play) #elif defined (GDK_WINDOWING_X11) window_handle = GDK_WINDOW_XID (window); #endif - g_object_set (play->player, "window-handle", (gpointer) window_handle, NULL); + g_object_set (play->renderer, "window-handle", (gpointer) window_handle, + NULL); } static void @@ -1413,24 +1416,14 @@ create_ui (GtkPlay * play) gtk_application_add_window (GTK_APPLICATION (g_application_get_default ()), GTK_WINDOW (play)); - if ((gtk_sink = gst_element_factory_make ("gtkglsink", NULL))) { - GstElement *video_sink; - - g_object_get (gtk_sink, "widget", &play->video_area, NULL); - - video_sink = gst_element_factory_make ("glsinkbin", NULL); - g_object_set (video_sink, "sink", gtk_sink, NULL); - - playbin = gst_player_get_pipeline (play->player); - g_object_set (playbin, "video-sink", video_sink, NULL); - gst_object_unref (playbin); - } else if ((gtk_sink = gst_element_factory_make ("gtksink", NULL))) { - g_object_get (gtk_sink, "widget", &play->video_area, NULL); - - playbin = gst_player_get_pipeline (play->player); - g_object_set (playbin, "video-sink", gtk_sink, NULL); - gst_object_unref (playbin); + play->renderer = gst_player_gtk_video_renderer_new (); + if (play->renderer) { + play->video_area = + gst_player_gtk_video_renderer_get_widget (GST_PLAYER_GTK_VIDEO_RENDERER + (play->renderer)); } else { + play->renderer = gst_player_video_overlay_video_renderer_new (NULL); + play->video_area = gtk_drawing_area_new (); g_signal_connect (play->video_area, "realize", G_CALLBACK (video_area_realize_cb), play); @@ -1506,10 +1499,6 @@ create_ui (GtkPlay * play) if (play->fullscreen) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (play->fullscreen_button), TRUE); - - /* enable visualization (by default laybin uses goom) */ - /* if visualization is enabled then use the first element */ - gst_player_set_visualization_enabled (play->player, TRUE); } static void @@ -1730,9 +1719,6 @@ gtk_play_constructor (GType type, guint n_construct_params, (GtkPlay *) G_OBJECT_CLASS (gtk_play_parent_class)->constructor (type, n_construct_params, construct_params); - self->player = - gst_player_new_full (gst_player_g_main_context_signal_dispatcher_new - (NULL)); self->playing = TRUE; if (self->inhibit_cookie) @@ -1744,6 +1730,10 @@ gtk_play_constructor (GType type, guint n_construct_params, create_ui (self); + self->player = + gst_player_new_full (self->renderer, + gst_player_g_main_context_signal_dispatcher_new (NULL)); + g_signal_connect (self->player, "position-updated", G_CALLBACK (position_updated_cb), self); g_signal_connect (self->player, "duration-changed", @@ -1754,6 +1744,10 @@ gtk_play_constructor (GType type, guint n_construct_params, g_signal_connect (self->player, "volume-changed", G_CALLBACK (player_volume_changed_cb), self); + /* enable visualization (by default playbin uses goom) */ + /* if visualization is enabled then use the first element */ + gst_player_set_visualization_enabled (self->player, TRUE); + g_signal_connect (G_OBJECT (self), "show", G_CALLBACK (show_cb), NULL); return G_OBJECT (self); diff --git a/playback/player/gtk/gtk-video-renderer.c b/playback/player/gtk/gtk-video-renderer.c new file mode 100644 index 0000000000..6ff568efc6 --- /dev/null +++ b/playback/player/gtk/gtk-video-renderer.c @@ -0,0 +1,178 @@ +/* GStreamer + * + * Copyright (C) 2015 Sebastian Dröge + * + * 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 "gtk-video-renderer.h" + +struct _GstPlayerGtkVideoRenderer +{ + GObject parent; + + GstElement *sink; + GtkWidget *widget; +}; + +struct _GstPlayerGtkVideoRendererClass +{ + GObjectClass parent_class; +}; + +static void + gst_player_gtk_video_renderer_interface_init + (GstPlayerVideoRendererInterface * iface); + +enum +{ + GTK_VIDEO_RENDERER_PROP_0, + GTK_VIDEO_RENDERER_PROP_WIDGET, + GTK_VIDEO_RENDERER_PROP_LAST +}; + +G_DEFINE_TYPE_WITH_CODE (GstPlayerGtkVideoRenderer, + gst_player_gtk_video_renderer, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GST_TYPE_PLAYER_VIDEO_RENDERER, + gst_player_gtk_video_renderer_interface_init)); + +static GParamSpec + * gtk_video_renderer_param_specs[GTK_VIDEO_RENDERER_PROP_LAST] = { NULL, }; + +static void +gst_player_gtk_video_renderer_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstPlayerGtkVideoRenderer *self = GST_PLAYER_GTK_VIDEO_RENDERER (object); + + switch (prop_id) { + case GTK_VIDEO_RENDERER_PROP_WIDGET: + g_value_set_object (value, self->widget); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_player_gtk_video_renderer_finalize (GObject * object) +{ + GstPlayerGtkVideoRenderer *self = GST_PLAYER_GTK_VIDEO_RENDERER (object); + + if (self->sink) + gst_object_unref (self->sink); + if (self->widget) + g_object_unref (self->widget); + + G_OBJECT_CLASS + (gst_player_gtk_video_renderer_parent_class)->finalize (object); +} + +static void + gst_player_gtk_video_renderer_class_init + (GstPlayerGtkVideoRendererClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_player_gtk_video_renderer_get_property; + gobject_class->finalize = gst_player_gtk_video_renderer_finalize; + + gtk_video_renderer_param_specs + [GTK_VIDEO_RENDERER_PROP_WIDGET] = + g_param_spec_object ("widget", "Widget", + "Widget to render the video into", GTK_TYPE_WIDGET, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, + GTK_VIDEO_RENDERER_PROP_LAST, gtk_video_renderer_param_specs); +} + +static void +gst_player_gtk_video_renderer_init (GstPlayerGtkVideoRenderer * self) +{ + GstElement *gtk_sink = gst_element_factory_make ("gtkglsink", NULL); + + if (gtk_sink) { + GstElement *sink = sink = gst_element_factory_make ("glsinkbin", NULL); + g_object_set (sink, "sink", gtk_sink, NULL); + + self->sink = sink; + } else { + gtk_sink = gst_element_factory_make ("gtksink", NULL); + + self->sink = gtk_sink; + } + + g_assert (self->sink != NULL); + + g_object_get (gtk_sink, "widget", &self->widget, NULL); +} + +static GstElement *gst_player_gtk_video_renderer_create_video_sink + (GstPlayerVideoRenderer * iface, GstPlayer * player) +{ + GstElement *gtk; + GstPlayerGtkVideoRenderer *self = GST_PLAYER_GTK_VIDEO_RENDERER (iface); + + return gst_object_ref (self->sink); +} + +static void + gst_player_gtk_video_renderer_interface_init + (GstPlayerVideoRendererInterface * iface) +{ + iface->create_video_sink = gst_player_gtk_video_renderer_create_video_sink; +} + +/** + * gst_player_gtk_video_renderer_new: + * + * Returns: (transfer full): + */ +GstPlayerVideoRenderer * +gst_player_gtk_video_renderer_new (void) +{ + GstElementFactory *factory; + + factory = gst_element_factory_find ("gtkglsink"); + if (!factory) + factory = gst_element_factory_find ("gtksink"); + if (!factory) + return NULL; + + gst_object_unref (factory); + + return g_object_new (GST_TYPE_PLAYER_GTK_VIDEO_RENDERER, NULL); +} + +/** + * gst_player_gtk_video_renderer_get_widget: + * @self: #GstPlayerVideoRenderer instance + * + * Returns: (transfer full): The GtkWidget + */ +GtkWidget *gst_player_gtk_video_renderer_get_widget + (GstPlayerGtkVideoRenderer * self) +{ + GtkWidget *widget; + + g_return_if_fail (GST_IS_PLAYER_GTK_VIDEO_RENDERER (self)); + + g_object_get (self, "widget", &widget, NULL); + + return widget; +} diff --git a/playback/player/gtk/gtk-video-renderer.h b/playback/player/gtk/gtk-video-renderer.h new file mode 100644 index 0000000000..482b609eb1 --- /dev/null +++ b/playback/player/gtk/gtk-video-renderer.h @@ -0,0 +1,49 @@ +/* GStreamer + * + * Copyright (C) 2015 Sebastian Dröge + * + * 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 __GTK_VIDEO_RENDERER_H__ +#define __GTK_VIDEO_RENDERER_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstPlayerGtkVideoRenderer + GstPlayerGtkVideoRenderer; +typedef struct _GstPlayerGtkVideoRendererClass + GstPlayerGtkVideoRendererClass; + +#define GST_TYPE_PLAYER_GTK_VIDEO_RENDERER (gst_player_gtk_video_renderer_get_type ()) +#define GST_IS_PLAYER_GTK_VIDEO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER)) +#define GST_IS_PLAYER_GTK_VIDEO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER)) +#define GST_PLAYER_GTK_VIDEO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER, GstPlayerGtkVideoRendererClass)) +#define GST_PLAYER_GTK_VIDEO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER, GstPlayerGtkVideoRenderer)) +#define GST_PLAYER_GTK_VIDEO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER, GstPlayerGtkVideoRendererClass)) +#define GST_PLAYER_GTK_VIDEO_RENDERER_CAST(obj) ((GstPlayerGtkVideoRenderer*)(obj)) + +GType gst_player_gtk_video_renderer_get_type (void); + +GstPlayerVideoRenderer * gst_player_gtk_video_renderer_new (void); +GtkWidget * gst_player_gtk_video_renderer_get_widget (GstPlayerGtkVideoRenderer * self); + +G_END_DECLS + +#endif /* __GTK_VIDEO_RENDERER_H__ */