From 637212f7e8dc5f76dead61cc3d1cab943f39b58d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 5 Mar 2021 18:10:35 +0100 Subject: [PATCH 01/10] Sink: move GL drawing logic into single function No need having it in another function with additional call if it is used only from single place. --- lib/gst/clapper/gtk4/gtkgstglwidget.c | 121 +++++++++++++------------- 1 file changed, 59 insertions(+), 62 deletions(-) diff --git a/lib/gst/clapper/gtk4/gtkgstglwidget.c b/lib/gst/clapper/gtk4/gtkgstglwidget.c index d7d53748..78b382dc 100644 --- a/lib/gst/clapper/gtk4/gtkgstglwidget.c +++ b/lib/gst/clapper/gtk4/gtkgstglwidget.c @@ -84,6 +84,10 @@ static const GLfloat vertices[] = { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f }; +static const GLushort indices[] = { + 0, 1, 2, 0, 2, 3 +}; + G_DEFINE_TYPE_WITH_CODE (GtkGstGLWidget, gtk_gst_gl_widget, GTK_TYPE_GL_AREA, G_ADD_PRIVATE (GtkGstGLWidget) GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkgstglwidget", 0, @@ -162,59 +166,6 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget) priv->initiated = TRUE; } -static void -_redraw_texture (GtkGstGLWidget * gst_widget, guint tex) -{ - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - const GstGLFuncs *gl = priv->context->gl_vtable; - const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; - - if (gst_widget->base.force_aspect_ratio) { - GstVideoRectangle src, dst, result; - gint widget_width, widget_height, widget_scale; - - gl->ClearColor (0.0, 0.0, 0.0, 1.0); - gl->Clear (GL_COLOR_BUFFER_BIT); - - widget_scale = gtk_widget_get_scale_factor ((GtkWidget *) gst_widget); - widget_width = gtk_widget_get_allocated_width ((GtkWidget *) gst_widget); - widget_height = gtk_widget_get_allocated_height ((GtkWidget *) gst_widget); - - src.x = 0; - src.y = 0; - src.w = gst_widget->base.display_width; - src.h = gst_widget->base.display_height; - - dst.x = 0; - dst.y = 0; - dst.w = widget_width * widget_scale; - dst.h = widget_height * widget_scale; - - gst_video_sink_center_rect (src, dst, &result, TRUE); - - gl->Viewport (result.x, result.y, result.w, result.h); - } - - gst_gl_shader_use (priv->shader); - - if (gl->BindVertexArray) - gl->BindVertexArray (priv->vao); - gtk_gst_gl_widget_bind_buffer (gst_widget); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, tex); - gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0); - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); - - if (gl->BindVertexArray) - gl->BindVertexArray (0); - else - gtk_gst_gl_widget_unbind_buffer (gst_widget); - - gl->BindTexture (GL_TEXTURE_2D, 0); -} - static inline void _draw_black (GstGLContext * context) { @@ -236,9 +187,12 @@ _draw_black_with_gdk (GdkGLContext * gdk_context) static gboolean gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) { - GtkGstGLWidgetPrivate *priv = GTK_GST_GL_WIDGET (widget)->priv; + GtkGstGLWidget *gst_widget = GTK_GST_GL_WIDGET (widget); GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + GtkGstGLWidgetPrivate *priv = gst_widget->priv; + const GstGLFuncs *gl; + GTK_GST_BASE_WIDGET_LOCK (widget); /* Draw black with GDK context when priv is not available yet. @@ -252,7 +206,7 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) if (!priv->initiated || !base_widget->negotiated) { if (!priv->initiated) - gtk_gst_gl_widget_init_redisplay (GTK_GST_GL_WIDGET (widget)); + gtk_gst_gl_widget_init_redisplay (gst_widget); _draw_black (priv->other_context); goto done; @@ -271,9 +225,6 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) } priv->current_tex = *(guint *) gl_frame.data[0]; - gst_gl_insert_debug_marker (priv->other_context, "redrawing texture %u", - priv->current_tex); - gst_gl_overlay_compositor_upload_overlays (priv->overlay_compositor, buffer); @@ -297,11 +248,57 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) GST_DEBUG ("rendering buffer %p with gdk context %p", base_widget->buffer, context); - _redraw_texture (GTK_GST_GL_WIDGET (widget), priv->current_tex); - gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor); + /* Draw texture */ + gl = priv->context->gl_vtable; - gst_gl_insert_debug_marker (priv->other_context, "texture %u redrawn", - priv->current_tex); + if (base_widget->force_aspect_ratio) { + GstVideoRectangle src, dst, result; + gint widget_width, widget_height, widget_scale; + + gl->ClearColor (0.0, 0.0, 0.0, 1.0); + gl->Clear (GL_COLOR_BUFFER_BIT); + + widget_scale = gtk_widget_get_scale_factor (GTK_WIDGET (widget)); + widget_width = gtk_widget_get_allocated_width (GTK_WIDGET (widget)); + widget_height = gtk_widget_get_allocated_height (GTK_WIDGET (widget)); + + src.x = 0; + src.y = 0; + src.w = base_widget->display_width; + src.h = base_widget->display_height; + + dst.x = 0; + dst.y = 0; + dst.w = widget_width * widget_scale; + dst.h = widget_height * widget_scale; + + gst_video_sink_center_rect (src, dst, &result, TRUE); + + gl->Viewport (result.x, result.y, result.w, result.h); + } + + gst_gl_shader_use (priv->shader); + + if (gl->BindVertexArray) + gl->BindVertexArray (priv->vao); + + gtk_gst_gl_widget_bind_buffer (gst_widget); + + gl->ActiveTexture (GL_TEXTURE0); + gl->BindTexture (GL_TEXTURE_2D, priv->current_tex); + gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0); + + gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + if (gl->BindVertexArray) + gl->BindVertexArray (0); + else + gtk_gst_gl_widget_unbind_buffer (gst_widget); + + gl->BindTexture (GL_TEXTURE_2D, 0); + + /* Draw subtitles */ + gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor); done: if (priv->other_context) From fe3fd329324cb78fe48b657439c4e594e3442def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 5 Mar 2021 18:41:26 +0100 Subject: [PATCH 02/10] Sink: keep track of widget allocation size Instead of obtaining allocation size on each frame draw, keep track of its current size and update value on its change. --- lib/gst/clapper/gtk4/gtkgstbasewidget.c | 36 +++++++++++++++++-------- lib/gst/clapper/gtk4/gtkgstbasewidget.h | 4 +++ lib/gst/clapper/gtk4/gtkgstglwidget.c | 11 +++----- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.c b/lib/gst/clapper/gtk4/gtkgstbasewidget.c index 85f6dc20..5ed70f3c 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.c +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.c @@ -91,6 +91,23 @@ gtk_gst_base_widget_measure (GtkWidget * widget, GtkOrientation orientation, *minimum_baseline = -1; *natural_baseline = -1; } + +static void +gtk_gst_base_widget_size_allocate (GtkWidget * widget, + gint width, gint height, gint baseline) +{ + GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + gint scale_factor = gtk_widget_get_scale_factor (widget); + + GTK_GST_BASE_WIDGET_LOCK (base_widget); + + base_widget->scaled_width = width * scale_factor; + base_widget->scaled_height = height * scale_factor; + + GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + + gtk_gl_area_queue_render (GTK_GL_AREA (widget)); +} #endif static void @@ -170,7 +187,6 @@ _calculate_par (GtkGstBaseWidget * widget, GstVideoInfo * info) display_par_d = 1; } - ok = gst_video_calculate_display_ratio (&widget->display_ratio_num, &widget->display_ratio_den, width, height, par_n, par_d, display_par_n, display_par_d); @@ -234,7 +250,7 @@ _queue_draw (GtkGstBaseWidget * widget) gtk_widget_queue_resize (GTK_WIDGET (widget)); } else { - gtk_widget_queue_draw (GTK_WIDGET (widget)); + gtk_gl_area_queue_render (GTK_GL_AREA (widget)); } GTK_GST_BASE_WIDGET_UNLOCK (widget); @@ -308,8 +324,7 @@ gtk_gst_base_widget_key_event (GtkEventControllerKey * key_controller, } static void -_fit_stream_to_allocated_size (GtkGstBaseWidget * base_widget, - GtkAllocation * allocation, GstVideoRectangle * result) +_fit_stream_to_allocated_size (GtkGstBaseWidget * base_widget, GstVideoRectangle * result) { if (base_widget->force_aspect_ratio) { GstVideoRectangle src, dst; @@ -321,15 +336,15 @@ _fit_stream_to_allocated_size (GtkGstBaseWidget * base_widget, dst.x = 0; dst.y = 0; - dst.w = allocation->width; - dst.h = allocation->height; + dst.w = base_widget->scaled_width; + dst.h = base_widget->scaled_height; gst_video_sink_center_rect (src, dst, result, TRUE); } else { result->x = 0; result->y = 0; - result->w = allocation->width; - result->h = allocation->height; + result->w = base_widget->scaled_width; + result->h = base_widget->scaled_height; } } @@ -338,11 +353,9 @@ _display_size_to_stream_size (GtkGstBaseWidget * base_widget, gdouble x, gdouble y, gdouble * stream_x, gdouble * stream_y) { gdouble stream_width, stream_height; - GtkAllocation allocation; GstVideoRectangle result; - gtk_widget_get_allocation (GTK_WIDGET (base_widget), &allocation); - _fit_stream_to_allocated_size (base_widget, &allocation, &result); + _fit_stream_to_allocated_size (base_widget, &result); stream_width = (gdouble) GST_VIDEO_INFO_WIDTH (&base_widget->v_info); stream_height = (gdouble) GST_VIDEO_INFO_HEIGHT (&base_widget->v_info); @@ -475,6 +488,7 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) #if defined(BUILD_FOR_GTK4) widget_klass->measure = gtk_gst_base_widget_measure; + widget_klass->size_allocate = gtk_gst_base_widget_size_allocate; #else widget_klass->get_preferred_width = gtk_gst_base_widget_get_preferred_width; widget_klass->get_preferred_height = gtk_gst_base_widget_get_preferred_height; diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.h b/lib/gst/clapper/gtk4/gtkgstbasewidget.h index 7151b36c..a8e899b2 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.h +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.h @@ -55,6 +55,10 @@ struct _GtkGstBaseWidget gint display_width; gint display_height; + /* Widget dimensions */ + gint scaled_width; + gint scaled_height; + gboolean negotiated; GstBuffer *pending_buffer; GstBuffer *buffer; diff --git a/lib/gst/clapper/gtk4/gtkgstglwidget.c b/lib/gst/clapper/gtk4/gtkgstglwidget.c index 78b382dc..2903fb0b 100644 --- a/lib/gst/clapper/gtk4/gtkgstglwidget.c +++ b/lib/gst/clapper/gtk4/gtkgstglwidget.c @@ -253,15 +253,10 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) if (base_widget->force_aspect_ratio) { GstVideoRectangle src, dst, result; - gint widget_width, widget_height, widget_scale; gl->ClearColor (0.0, 0.0, 0.0, 1.0); gl->Clear (GL_COLOR_BUFFER_BIT); - widget_scale = gtk_widget_get_scale_factor (GTK_WIDGET (widget)); - widget_width = gtk_widget_get_allocated_width (GTK_WIDGET (widget)); - widget_height = gtk_widget_get_allocated_height (GTK_WIDGET (widget)); - src.x = 0; src.y = 0; src.w = base_widget->display_width; @@ -269,8 +264,8 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) dst.x = 0; dst.y = 0; - dst.w = widget_width * widget_scale; - dst.h = widget_height * widget_scale; + dst.w = base_widget->scaled_width; + dst.h = base_widget->scaled_height; gst_video_sink_center_rect (src, dst, &result, TRUE); @@ -429,6 +424,8 @@ gtk_gst_gl_widget_init (GtkGstGLWidget * gst_widget) gtk_gl_area_set_has_alpha (GTK_GL_AREA (gst_widget), !base_widget->ignore_alpha); #endif + + gtk_gl_area_set_auto_render (GTK_GL_AREA (gst_widget), FALSE); } static void From 07fb0a9a464452161bdec926382899050502072b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 5 Mar 2021 19:02:14 +0100 Subject: [PATCH 03/10] Sink: remove GTK4 if-defs Clapper works with GTK4, so reduce codebase by removing GTK3 leftovers --- lib/gst/clapper/gtk4/gstgtkbasesink.c | 53 ++--------------- lib/gst/clapper/gtk4/gtkconfig.h | 7 --- lib/gst/clapper/gtk4/gtkgstbasewidget.c | 77 ++----------------------- lib/gst/clapper/gtk4/gtkgstbasewidget.h | 4 -- lib/gst/clapper/gtk4/gtkgstglwidget.c | 14 ----- lib/gst/clapper/meson.build | 1 - 6 files changed, 10 insertions(+), 146 deletions(-) diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.c b/lib/gst/clapper/gtk4/gstgtkbasesink.c index 1f35a9de..95e1871f 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.c +++ b/lib/gst/clapper/gtk4/gstgtkbasesink.c @@ -117,14 +117,6 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D, G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /* Disabling alpha was removed in GTK4 */ -#if !defined(BUILD_FOR_GTK4) - g_object_class_install_property (gobject_class, PROP_IGNORE_ALPHA, - g_param_spec_boolean ("ignore-alpha", "Ignore Alpha", - "When enabled, alpha will be ignored and converted to black", - DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -#endif - g_object_class_install_property (gobject_class, PROP_IGNORE_TEXTURES, g_param_spec_boolean ("ignore-textures", "Ignore Textures", "When enabled, textures will be ignored and not drawn", @@ -204,11 +196,7 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink) /* Ensure GTK is initialized, this has no side effect if it was already * initialized. Also, we do that lazily, so the application can be first */ - if (!gtk_init_check ( -#if !defined(BUILD_FOR_GTK4) - NULL, NULL -#endif - )) { + if (!gtk_init_check ()) { GST_ERROR_OBJECT (gtk_sink, "Could not ensure GTK initialization."); return NULL; } @@ -223,12 +211,6 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink) gtk_sink->bind_pixel_aspect_ratio = g_object_bind_property (gtk_sink, "pixel-aspect-ratio", gtk_sink->widget, "pixel-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); -#if !defined(BUILD_FOR_GTK4) - gtk_sink->bind_ignore_alpha = - g_object_bind_property (gtk_sink, "ignore-alpha", gtk_sink->widget, - "ignore-alpha", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); -#endif - gtk_sink->bind_ignore_textures = g_object_bind_property (gtk_sink, "ignore-textures", gtk_sink->widget, "ignore-textures", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); @@ -352,16 +334,13 @@ gst_gtk_base_sink_start_on_main (GstBaseSink * bsink) GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink); GstGtkBaseSinkClass *klass = GST_GTK_BASE_SINK_GET_CLASS (bsink); GtkWidget *toplevel; -#if defined(BUILD_FOR_GTK4) GtkRoot *root; -#endif if (gst_gtk_base_sink_get_widget (gst_sink) == NULL) return FALSE; /* After this point, gtk_sink->widget will always be set */ -#if defined(BUILD_FOR_GTK4) root = gtk_widget_get_root (GTK_WIDGET (gst_sink->widget)); if (!GTK_IS_ROOT (root)) { GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (gst_sink->widget)); @@ -371,35 +350,19 @@ gst_gtk_base_sink_start_on_main (GstBaseSink * bsink) parent = temp_parent; } toplevel = (parent) ? parent : GTK_WIDGET (gst_sink->widget); -#else - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (gst_sink->widget)); - if (!gtk_widget_is_toplevel (toplevel)) { -#endif + /* sanity check */ g_assert (klass->window_title); /* User did not add widget its own UI, let's popup a new GtkWindow to * make gst-launch-1.0 work. */ - gst_sink->window = gtk_window_new ( -#if !defined(BUILD_FOR_GTK4) - GTK_WINDOW_TOPLEVEL -#endif - ); + gst_sink->window = gtk_window_new (); gtk_window_set_default_size (GTK_WINDOW (gst_sink->window), 640, 480); gtk_window_set_title (GTK_WINDOW (gst_sink->window), klass->window_title); -#if defined(BUILD_FOR_GTK4) - gtk_window_set_child (GTK_WINDOW ( -#else - gtk_container_add (GTK_CONTAINER ( -#endif - gst_sink->window), toplevel); + gtk_window_set_child (GTK_WINDOW (gst_sink->window), toplevel); gst_sink->window_destroy_id = g_signal_connect ( -#if defined(BUILD_FOR_GTK4) GTK_WINDOW (gst_sink->window), -#else - gst_sink->window, -#endif "destroy", G_CALLBACK (window_destroy_cb), gst_sink); } @@ -419,11 +382,7 @@ gst_gtk_base_sink_stop_on_main (GstBaseSink * bsink) GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink); if (gst_sink->window) { -#if defined(BUILD_FOR_GTK4) gtk_window_destroy (GTK_WINDOW (gst_sink->window)); -#else - gtk_widget_destroy (gst_sink->window); -#endif gst_sink->window = NULL; gst_sink->widget = NULL; } @@ -446,11 +405,7 @@ gst_gtk_base_sink_stop (GstBaseSink * bsink) static void gst_gtk_window_show_all_and_unref (GtkWidget * window) { -#if defined(BUILD_FOR_GTK4) gtk_window_present (GTK_WINDOW (window)); -#else - gtk_widget_show_all (window); -#endif g_object_unref (window); } diff --git a/lib/gst/clapper/gtk4/gtkconfig.h b/lib/gst/clapper/gtk4/gtkconfig.h index ecbf9558..76ee9d11 100644 --- a/lib/gst/clapper/gtk4/gtkconfig.h +++ b/lib/gst/clapper/gtk4/gtkconfig.h @@ -18,14 +18,7 @@ * Boston, MA 02110-1301, USA. */ -#if defined(BUILD_FOR_GTK4) #define GTKCONFIG_PLUGIN gtk4 #define GTKCONFIG_NAME "GTK4" #define GTKCONFIG_SINK "gtk4sink" #define GTKCONFIG_GLSINK "gtk4glsink" -#else -#define GTKCONFIG_PLUGIN gtk -#define GTKCONFIG_NAME "GTK" -#define GTKCONFIG_SINK "gtksink" -#define GTKCONFIG_GLSINK "gtkglsink" -#endif diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.c b/lib/gst/clapper/gtk4/gtkgstbasewidget.c index 5ed70f3c..6a1079b6 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.c +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.c @@ -77,7 +77,6 @@ gtk_gst_base_widget_get_preferred_height (GtkWidget * widget, gint * min, *natural = video_height; } -#if defined(BUILD_FOR_GTK4) static void gtk_gst_base_widget_measure (GtkWidget * widget, GtkOrientation orientation, gint for_size, gint * min, gint * natural, @@ -108,7 +107,6 @@ gtk_gst_base_widget_size_allocate (GtkWidget * widget, gtk_gl_area_queue_render (GTK_GL_AREA (widget)); } -#endif static void gtk_gst_base_widget_set_property (GObject * object, guint prop_id, @@ -276,25 +274,6 @@ _gdk_key_to_navigation_string (guint keyval) } } -static GdkEvent * -_get_current_event (GtkEventController * controller) -{ -#if defined(BUILD_FOR_GTK4) - return gtk_event_controller_get_current_event (controller); -#else - return gtk_get_current_event (); -#endif -} - -static void -_gdk_event_free (GdkEvent * event) -{ -#if !defined(BUILD_FOR_GTK4) - if (event) - gdk_event_free (event); -#endif -} - static gboolean gtk_gst_base_widget_key_event (GtkEventControllerKey * key_controller, guint keyval, guint keycode, GdkModifierType state) @@ -306,7 +285,7 @@ gtk_gst_base_widget_key_event (GtkEventControllerKey * key_controller, if ((element = g_weak_ref_get (&base_widget->element))) { if (GST_IS_NAVIGATION (element)) { - GdkEvent *event = _get_current_event (controller); + GdkEvent *event = gtk_event_controller_get_current_event (controller); const gchar *str = _gdk_key_to_navigation_string (keyval); if (str) { @@ -315,7 +294,6 @@ gtk_gst_base_widget_key_event (GtkEventControllerKey * key_controller, GDK_KEY_PRESS ? "key-press" : "key-release"; gst_navigation_send_key_event (GST_NAVIGATION (element), key_type, str); } - _gdk_event_free (event); } g_object_unref (element); } @@ -387,12 +365,7 @@ _display_size_to_stream_size (GtkGstBaseWidget * base_widget, gdouble x, } static gboolean -gtk_gst_base_widget_button_event ( -#if defined(BUILD_FOR_GTK4) - GtkGestureClick * gesture, -#else - GtkGestureMultiPress * gesture, -#endif +gtk_gst_base_widget_button_event (GtkGestureClick * gesture, gint n_press, gdouble x, gdouble y) { GtkEventController *controller = GTK_EVENT_CONTROLLER (gesture); @@ -402,28 +375,18 @@ gtk_gst_base_widget_button_event ( if ((element = g_weak_ref_get (&base_widget->element))) { if (GST_IS_NAVIGATION (element)) { - GdkEvent *event = _get_current_event (controller); + GdkEvent *event = gtk_event_controller_get_current_event (controller); const gchar *key_type = gdk_event_get_event_type (event) == GDK_BUTTON_PRESS ? "mouse-button-press" : "mouse-button-release"; gdouble stream_x, stream_y; -#if !defined(BUILD_FOR_GTK4) - guint button; - gdk_event_get_button (event, &button); -#endif _display_size_to_stream_size (base_widget, x, y, &stream_x, &stream_y); gst_navigation_send_mouse_event (GST_NAVIGATION (element), key_type, -#if defined(BUILD_FOR_GTK4) /* Gesture is set to ignore other buttons so we do not have to check */ GDK_BUTTON_PRIMARY, -#else - button, -#endif stream_x, stream_y); - - _gdk_event_free (event); } g_object_unref (element); } @@ -486,13 +449,8 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) "When enabled, textures will be ignored and not drawn", DEFAULT_IGNORE_TEXTURES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -#if defined(BUILD_FOR_GTK4) widget_klass->measure = gtk_gst_base_widget_measure; widget_klass->size_allocate = gtk_gst_base_widget_size_allocate; -#else - widget_klass->get_preferred_width = gtk_gst_base_widget_get_preferred_width; - widget_klass->get_preferred_height = gtk_gst_base_widget_get_preferred_height; -#endif GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_widget, "gtkbasewidget", 0, "GTK Video Base Widget"); @@ -513,36 +471,22 @@ gtk_gst_base_widget_init (GtkGstBaseWidget * widget) g_weak_ref_init (&widget->element, NULL); g_mutex_init (&widget->lock); - widget->key_controller = gtk_event_controller_key_new ( -#if !defined(BUILD_FOR_GTK4) - GTK_WIDGET (widget) -#endif - ); + widget->key_controller = gtk_event_controller_key_new (); g_signal_connect (widget->key_controller, "key-pressed", G_CALLBACK (gtk_gst_base_widget_key_event), NULL); g_signal_connect (widget->key_controller, "key-released", G_CALLBACK (gtk_gst_base_widget_key_event), NULL); - widget->motion_controller = gtk_event_controller_motion_new ( -#if !defined(BUILD_FOR_GTK4) - GTK_WIDGET (widget) -#endif - ); + widget->motion_controller = gtk_event_controller_motion_new (); g_signal_connect (widget->motion_controller, "motion", G_CALLBACK (gtk_gst_base_widget_motion_event), NULL); - widget->click_gesture = -#if defined(BUILD_FOR_GTK4) - gtk_gesture_click_new (); -#else - gtk_gesture_multi_press_new (GTK_WIDGET (widget)); -#endif + widget->click_gesture = gtk_gesture_click_new (); g_signal_connect (widget->click_gesture, "pressed", G_CALLBACK (gtk_gst_base_widget_button_event), NULL); g_signal_connect (widget->click_gesture, "released", G_CALLBACK (gtk_gst_base_widget_button_event), NULL); -#if defined(BUILD_FOR_GTK4) /* Otherwise widget in grid will appear as a 1x1px * video which might be misleading for users */ gtk_widget_set_hexpand (GTK_WIDGET (widget), TRUE); @@ -556,7 +500,6 @@ gtk_gst_base_widget_init (GtkGstBaseWidget * widget) gtk_widget_add_controller (GTK_WIDGET (widget), widget->motion_controller); gtk_widget_add_controller (GTK_WIDGET (widget), GTK_EVENT_CONTROLLER (widget->click_gesture)); -#endif gtk_widget_set_can_focus (GTK_WIDGET (widget), TRUE); } @@ -566,14 +509,6 @@ gtk_gst_base_widget_finalize (GObject * object) { GtkGstBaseWidget *widget = GTK_GST_BASE_WIDGET (object); - /* GTK4 takes ownership of EventControllers - * while GTK3 still needs manual unref */ -#if !defined(BUILD_FOR_GTK4) - g_object_unref (widget->key_controller); - g_object_unref (widget->motion_controller); - g_object_unref (widget->click_gesture); -#endif - gst_buffer_replace (&widget->pending_buffer, NULL); gst_buffer_replace (&widget->buffer, NULL); g_mutex_clear (&widget->lock); diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.h b/lib/gst/clapper/gtk4/gtkgstbasewidget.h index a8e899b2..4532b821 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.h +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.h @@ -26,10 +26,6 @@ #include #include -#if !defined(BUILD_FOR_GTK4) -#include -#endif - #define GTK_GST_BASE_WIDGET(w) ((GtkGstBaseWidget *)(w)) #define GTK_GST_BASE_WIDGET_CLASS(k) ((GtkGstBaseWidgetClass *)(k)) #define GTK_GST_BASE_WIDGET_LOCK(w) g_mutex_lock(&((GtkGstBaseWidget*)(w))->lock) diff --git a/lib/gst/clapper/gtk4/gtkgstglwidget.c b/lib/gst/clapper/gtk4/gtkgstglwidget.c index 2903fb0b..6b3ee8df 100644 --- a/lib/gst/clapper/gtk4/gtkgstglwidget.c +++ b/lib/gst/clapper/gtk4/gtkgstglwidget.c @@ -31,20 +31,12 @@ #include #if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) -#if defined(BUILD_FOR_GTK4) #include -#else -#include -#endif #include #endif #if GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND) -#if defined(BUILD_FOR_GTK4) #include -#else -#include -#endif #include #endif @@ -419,12 +411,6 @@ gtk_gst_gl_widget_init (GtkGstGLWidget * gst_widget) GST_INFO ("Created %" GST_PTR_FORMAT, priv->display); - /* GTK4 always has alpha */ -#if !defined(BUILD_FOR_GTK4) - gtk_gl_area_set_has_alpha (GTK_GL_AREA (gst_widget), - !base_widget->ignore_alpha); -#endif - gtk_gl_area_set_auto_render (GTK_GL_AREA (gst_widget), FALSE); } diff --git a/lib/gst/clapper/meson.build b/lib/gst/clapper/meson.build index 961d2f14..456706d8 100644 --- a/lib/gst/clapper/meson.build +++ b/lib/gst/clapper/meson.build @@ -32,7 +32,6 @@ gstclapper_defines = [ '-DBUILDING_GST_CLAPPER', '-DGST_USE_UNSTABLE_API', '-DHAVE_GTK_GL', - '-DBUILD_FOR_GTK4', ] gtk_deps = [gstgl_dep, gstglproto_dep] have_gtk_gl_windowing = false From 93549a67af02410b241c1a2ae7d0d7eeff7b2d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 5 Mar 2021 19:26:29 +0100 Subject: [PATCH 04/10] Sink: remove ignore_alpha property GTK4 no longer supports ignoring alpha --- lib/gst/clapper/gtk4/gstgtkbasesink.c | 9 --------- lib/gst/clapper/gtk4/gstgtkbasesink.h | 3 --- lib/gst/clapper/gtk4/gtkgstbasewidget.c | 14 -------------- lib/gst/clapper/gtk4/gtkgstbasewidget.h | 1 - 4 files changed, 27 deletions(-) diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.c b/lib/gst/clapper/gtk4/gstgtkbasesink.c index 95e1871f..6775dccc 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.c +++ b/lib/gst/clapper/gtk4/gstgtkbasesink.c @@ -38,7 +38,6 @@ GST_DEBUG_CATEGORY (gst_debug_gtk_base_sink); #define DEFAULT_FORCE_ASPECT_RATIO TRUE #define DEFAULT_PAR_N 0 #define DEFAULT_PAR_D 1 -#define DEFAULT_IGNORE_ALPHA TRUE #define DEFAULT_IGNORE_TEXTURES FALSE static void gst_gtk_base_sink_finalize (GObject * object); @@ -70,7 +69,6 @@ enum PROP_WIDGET, PROP_FORCE_ASPECT_RATIO, PROP_PIXEL_ASPECT_RATIO, - PROP_IGNORE_ALPHA, PROP_IGNORE_TEXTURES, }; @@ -141,7 +139,6 @@ gst_gtk_base_sink_init (GstGtkBaseSink * gtk_sink) gtk_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; gtk_sink->par_n = DEFAULT_PAR_N; gtk_sink->par_d = DEFAULT_PAR_D; - gtk_sink->ignore_alpha = DEFAULT_IGNORE_ALPHA; gtk_sink->ignore_textures = DEFAULT_IGNORE_TEXTURES; } @@ -259,9 +256,6 @@ gst_gtk_base_sink_get_property (GObject * object, guint prop_id, case PROP_PIXEL_ASPECT_RATIO: gst_value_set_fraction (value, gtk_sink->par_n, gtk_sink->par_d); break; - case PROP_IGNORE_ALPHA: - g_value_set_boolean (value, gtk_sink->ignore_alpha); - break; case PROP_IGNORE_TEXTURES: g_value_set_boolean (value, gtk_sink->ignore_textures); break; @@ -285,9 +279,6 @@ gst_gtk_base_sink_set_property (GObject * object, guint prop_id, gtk_sink->par_n = gst_value_get_fraction_numerator (value); gtk_sink->par_d = gst_value_get_fraction_denominator (value); break; - case PROP_IGNORE_ALPHA: - gtk_sink->ignore_alpha = g_value_get_boolean (value); - break; case PROP_IGNORE_TEXTURES: gtk_sink->ignore_textures = g_value_get_boolean (value); break; diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.h b/lib/gst/clapper/gtk4/gstgtkbasesink.h index 2a8b4b15..f12ab636 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.h +++ b/lib/gst/clapper/gtk4/gstgtkbasesink.h @@ -65,9 +65,6 @@ struct _GstGtkBaseSink gint par_d; GBinding *bind_pixel_aspect_ratio; - gboolean ignore_alpha; - GBinding *bind_ignore_alpha; - gboolean ignore_textures; GBinding *bind_ignore_textures; diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.c b/lib/gst/clapper/gtk4/gtkgstbasewidget.c index 6a1079b6..f1795546 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.c +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.c @@ -33,7 +33,6 @@ GST_DEBUG_CATEGORY (gst_debug_gtk_base_widget); #define DEFAULT_FORCE_ASPECT_RATIO TRUE #define DEFAULT_PAR_N 0 #define DEFAULT_PAR_D 1 -#define DEFAULT_IGNORE_ALPHA TRUE #define DEFAULT_IGNORE_TEXTURES FALSE enum @@ -41,7 +40,6 @@ enum PROP_0, PROP_FORCE_ASPECT_RATIO, PROP_PIXEL_ASPECT_RATIO, - PROP_IGNORE_ALPHA, PROP_IGNORE_TEXTURES, }; @@ -122,9 +120,6 @@ gtk_gst_base_widget_set_property (GObject * object, guint prop_id, gtk_widget->par_n = gst_value_get_fraction_numerator (value); gtk_widget->par_d = gst_value_get_fraction_denominator (value); break; - case PROP_IGNORE_ALPHA: - gtk_widget->ignore_alpha = g_value_get_boolean (value); - break; case PROP_IGNORE_TEXTURES: gtk_widget->ignore_textures = g_value_get_boolean (value); break; @@ -147,9 +142,6 @@ gtk_gst_base_widget_get_property (GObject * object, guint prop_id, case PROP_PIXEL_ASPECT_RATIO: gst_value_set_fraction (value, gtk_widget->par_n, gtk_widget->par_d); break; - case PROP_IGNORE_ALPHA: - g_value_set_boolean (value, gtk_widget->ignore_alpha); - break; case PROP_IGNORE_TEXTURES: g_value_set_boolean (value, gtk_widget->ignore_textures); break; @@ -439,11 +431,6 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D, G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_klass, PROP_IGNORE_ALPHA, - g_param_spec_boolean ("ignore-alpha", "Ignore Alpha", - "When enabled, alpha will be ignored and converted to black", - DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_klass, PROP_IGNORE_TEXTURES, g_param_spec_boolean ("ignore-textures", "Ignore Textures", "When enabled, textures will be ignored and not drawn", @@ -462,7 +449,6 @@ gtk_gst_base_widget_init (GtkGstBaseWidget * widget) widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; widget->par_n = DEFAULT_PAR_N; widget->par_d = DEFAULT_PAR_D; - widget->ignore_alpha = DEFAULT_IGNORE_ALPHA; widget->ignore_textures = DEFAULT_IGNORE_TEXTURES; gst_video_info_init (&widget->v_info); diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.h b/lib/gst/clapper/gtk4/gtkgstbasewidget.h index 4532b821..8721c441 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.h +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.h @@ -45,7 +45,6 @@ struct _GtkGstBaseWidget /* properties */ gboolean force_aspect_ratio; gint par_n, par_d; - gboolean ignore_alpha; gboolean ignore_textures; gint display_width; From 95c38453983fdd9c713d7c1e6f12b0b30461f607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 5 Mar 2021 21:06:03 +0100 Subject: [PATCH 05/10] Sink: merge gstsink into single class Clapper only uses single video sink. No need for subclassing it. --- lib/gst/clapper/gstclapper-gtk4-plugin.c | 4 +- lib/gst/clapper/gtk4/gstgtkbasesink.c | 248 +++++++++++++++-- lib/gst/clapper/gtk4/gstgtkbasesink.h | 13 +- lib/gst/clapper/gtk4/gstgtkglsink.c | 336 ----------------------- lib/gst/clapper/gtk4/gstgtkglsink.h | 64 ----- lib/gst/clapper/meson.build | 1 - 6 files changed, 246 insertions(+), 420 deletions(-) delete mode 100644 lib/gst/clapper/gtk4/gstgtkglsink.c delete mode 100644 lib/gst/clapper/gtk4/gstgtkglsink.h diff --git a/lib/gst/clapper/gstclapper-gtk4-plugin.c b/lib/gst/clapper/gstclapper-gtk4-plugin.c index 5a38378f..43e60873 100644 --- a/lib/gst/clapper/gstclapper-gtk4-plugin.c +++ b/lib/gst/clapper/gstclapper-gtk4-plugin.c @@ -30,7 +30,7 @@ #endif #include "gstclapper-gtk4-plugin.h" -#include "gtk4/gstgtkglsink.h" +#include "gtk4/gstgtkbasesink.h" enum { @@ -78,7 +78,7 @@ gst_clapper_gtk4_plugin_constructed (GObject * object) GstClapperGtk4Plugin *self = GST_CLAPPER_GTK4_PLUGIN (object); if (!self->video_sink) - self->video_sink = g_object_new (GST_TYPE_GTK_GL_SINK, NULL); + self->video_sink = g_object_new (GST_TYPE_GTK_BASE_SINK, NULL); gst_object_ref_sink (self->video_sink); diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.c b/lib/gst/clapper/gtk4/gstgtkbasesink.c index 6775dccc..47b38e71 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.c +++ b/lib/gst/clapper/gtk4/gstgtkbasesink.c @@ -29,8 +29,12 @@ #include "config.h" #endif +#include + +#include "gtkconfig.h" #include "gstgtkbasesink.h" #include "gstgtkutils.h" +#include "gtkgstglwidget.h" GST_DEBUG_CATEGORY (gst_debug_gtk_base_sink); #define GST_CAT_DEFAULT gst_debug_gtk_base_sink @@ -40,12 +44,25 @@ GST_DEBUG_CATEGORY (gst_debug_gtk_base_sink); #define DEFAULT_PAR_D 1 #define DEFAULT_IGNORE_TEXTURES FALSE +static GstStaticPadTemplate gst_gtk_base_sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES + (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, "RGBA") "; " + GST_VIDEO_CAPS_MAKE_WITH_FEATURES + (GST_CAPS_FEATURE_MEMORY_GL_MEMORY ", " + GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, "RGBA"))); + static void gst_gtk_base_sink_finalize (GObject * object); static void gst_gtk_base_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * param_spec); static void gst_gtk_base_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * param_spec); +static gboolean gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, + GstQuery * query); +static gboolean gst_gtk_base_sink_query (GstBaseSink * bsink, GstQuery * query); static gboolean gst_gtk_base_sink_start (GstBaseSink * bsink); static gboolean gst_gtk_base_sink_stop (GstBaseSink * bsink); @@ -55,6 +72,8 @@ gst_gtk_base_sink_change_state (GstElement * element, static void gst_gtk_base_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, GstClockTime * start, GstClockTime * end); +static GstCaps *gst_gtk_base_sink_get_caps (GstBaseSink * bsink, + GstCaps * filter); static gboolean gst_gtk_base_sink_set_caps (GstBaseSink * bsink, GstCaps * caps); static GstFlowReturn gst_gtk_base_sink_show_frame (GstVideoSink * bsink, @@ -73,14 +92,13 @@ enum }; #define gst_gtk_base_sink_parent_class parent_class -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstGtkBaseSink, gst_gtk_base_sink, +G_DEFINE_TYPE_WITH_CODE (GstGtkBaseSink, gst_gtk_base_sink, GST_TYPE_VIDEO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, gst_gtk_base_sink_navigation_interface_init); GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_sink, "gtkbasesink", 0, "GTK Video Sink base class")); - static void gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) { @@ -88,11 +106,13 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) GstElementClass *gstelement_class; GstBaseSinkClass *gstbasesink_class; GstVideoSinkClass *gstvideosink_class; + GstGtkBaseSinkClass *gstgtkbasesink_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; gstbasesink_class = (GstBaseSinkClass *) klass; gstvideosink_class = (GstVideoSinkClass *) klass; + gstgtkbasesink_class = (GstGtkBaseSinkClass *) klass; gobject_class->set_property = gst_gtk_base_sink_set_property; gobject_class->get_property = gst_gtk_base_sink_get_property; @@ -123,13 +143,29 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) gobject_class->finalize = gst_gtk_base_sink_finalize; gstelement_class->change_state = gst_gtk_base_sink_change_state; + + gstbasesink_class->get_caps = gst_gtk_base_sink_get_caps; gstbasesink_class->set_caps = gst_gtk_base_sink_set_caps; gstbasesink_class->get_times = gst_gtk_base_sink_get_times; + gstbasesink_class->propose_allocation = gst_gtk_base_sink_propose_allocation; + gstbasesink_class->query = gst_gtk_base_sink_query; gstbasesink_class->start = gst_gtk_base_sink_start; gstbasesink_class->stop = gst_gtk_base_sink_stop; gstvideosink_class->show_frame = gst_gtk_base_sink_show_frame; + gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new; + gstgtkbasesink_class->window_title = GTKCONFIG_NAME " GL Renderer"; + + gst_element_class_set_metadata (gstelement_class, + GTKCONFIG_NAME " GL Video Sink", + "Sink/Video", "A video sink that renders to a GtkWidget using OpenGL", + "Matthew Waters , " + "Rafał Dzięgiel "); + + gst_element_class_add_static_pad_template (gstelement_class, + &gst_gtk_base_sink_template); + gst_type_mark_as_plugin_api (GST_TYPE_GTK_BASE_SINK, 0); } @@ -145,18 +181,18 @@ gst_gtk_base_sink_init (GstGtkBaseSink * gtk_sink) static void gst_gtk_base_sink_finalize (GObject * object) { - GstGtkBaseSink *gtk_sink = GST_GTK_BASE_SINK (object); + GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (object); GST_DEBUG ("finalizing base sink"); - GST_OBJECT_LOCK (gtk_sink); - if (gtk_sink->window && gtk_sink->window_destroy_id) - g_signal_handler_disconnect (gtk_sink->window, gtk_sink->window_destroy_id); - if (gtk_sink->widget && gtk_sink->widget_destroy_id) - g_signal_handler_disconnect (gtk_sink->widget, gtk_sink->widget_destroy_id); + GST_OBJECT_LOCK (base_sink); + if (base_sink->window && base_sink->window_destroy_id) + g_signal_handler_disconnect (base_sink->window, base_sink->window_destroy_id); + if (base_sink->widget && base_sink->widget_destroy_id) + g_signal_handler_disconnect (base_sink->widget, base_sink->widget_destroy_id); - g_clear_object (>k_sink->widget); - GST_OBJECT_UNLOCK (gtk_sink); + g_clear_object (&base_sink->widget); + GST_OBJECT_UNLOCK (base_sink); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -319,6 +355,118 @@ gst_gtk_base_sink_navigation_interface_init (GstNavigationInterface * iface) iface->send_event = gst_gtk_base_sink_navigation_send_event; } +static gboolean +gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) +{ + GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); + GstBufferPool *pool = NULL; + GstStructure *config; + GstCaps *caps; + GstVideoInfo info; + guint size; + gboolean need_pool; + GstStructure *allocation_meta = NULL; + gint display_width, display_height; + + if (!base_sink->display || !base_sink->context) + return FALSE; + + gst_query_parse_allocation (query, &caps, &need_pool); + + if (caps == NULL) + goto no_caps; + + if (!gst_video_info_from_caps (&info, caps)) + goto invalid_caps; + + /* the normal size of a frame */ + size = info.size; + + if (need_pool) { + GST_DEBUG_OBJECT (base_sink, "create new pool"); + pool = gst_gl_buffer_pool_new (base_sink->context); + + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, caps, size, 0, 0); + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_GL_SYNC_META); + + if (!gst_buffer_pool_set_config (pool, config)) + goto config_failed; + } + + /* we need at least 2 buffer because we hold on to the last one */ + gst_query_add_allocation_pool (query, pool, size, 2, 0); + if (pool) + gst_object_unref (pool); + + GST_OBJECT_LOCK (base_sink); + display_width = base_sink->display_width; + display_height = base_sink->display_height; + GST_OBJECT_UNLOCK (base_sink); + + if (display_width != 0 && display_height != 0) { + GST_DEBUG_OBJECT (base_sink, "sending alloc query with size %dx%d", + display_width, display_height); + allocation_meta = gst_structure_new ("GstVideoOverlayCompositionMeta", + "width", G_TYPE_UINT, display_width, + "height", G_TYPE_UINT, display_height, NULL); + } + + gst_query_add_allocation_meta (query, + GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, allocation_meta); + + if (allocation_meta) + gst_structure_free (allocation_meta); + + /* we also support various metadata */ + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); + + if (base_sink->context->gl_vtable->FenceSync) + gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0); + + 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"); + return FALSE; + } +} + +static gboolean +gst_gtk_base_sink_query (GstBaseSink * bsink, GstQuery * query) +{ + GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONTEXT: + { + if (gst_gl_handle_context_query ((GstElement *) base_sink, query, + base_sink->display, base_sink->context, base_sink->gtk_context)) + return TRUE; + break; + } + default: + res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); + break; + } + + return res; +} + static gboolean gst_gtk_base_sink_start_on_main (GstBaseSink * bsink) { @@ -330,7 +478,7 @@ gst_gtk_base_sink_start_on_main (GstBaseSink * bsink) if (gst_gtk_base_sink_get_widget (gst_sink) == NULL) return FALSE; - /* After this point, gtk_sink->widget will always be set */ + /* After this point, base_sink->widget will always be set */ root = gtk_widget_get_root (GTK_WIDGET (gst_sink->widget)); if (!GTK_IS_ROOT (root)) { @@ -363,8 +511,39 @@ gst_gtk_base_sink_start_on_main (GstBaseSink * bsink) static gboolean gst_gtk_base_sink_start (GstBaseSink * bsink) { - return ! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) - gst_gtk_base_sink_start_on_main, bsink); + GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); + GtkGstGLWidget *gst_widget; + + if (!(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) + gst_gtk_base_sink_start_on_main, bsink))) + return FALSE; + + /* After this point, base_sink->widget will always be set */ + gst_widget = GTK_GST_GL_WIDGET (base_sink->widget); + + if (!gtk_gst_gl_widget_init_winsys (gst_widget)) { + GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", + "Failed to initialize OpenGL with GTK"), (NULL)); + return FALSE; + } + + if (!base_sink->display) + base_sink->display = gtk_gst_gl_widget_get_display (gst_widget); + if (!base_sink->context) + base_sink->context = gtk_gst_gl_widget_get_context (gst_widget); + if (!base_sink->gtk_context) + base_sink->gtk_context = gtk_gst_gl_widget_get_gtk_context (gst_widget); + + if (!base_sink->display || !base_sink->context || !base_sink->gtk_context) { + GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", + "Failed to retrieve OpenGL context from GTK"), (NULL)); + return FALSE; + } + + gst_gl_element_propagate_display_context (GST_ELEMENT (bsink), + base_sink->display); + + return TRUE; } static gboolean @@ -384,9 +563,21 @@ gst_gtk_base_sink_stop_on_main (GstBaseSink * bsink) static gboolean gst_gtk_base_sink_stop (GstBaseSink * bsink) { - GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink); + GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); - if (gst_sink->window) + if (base_sink->display) { + gst_object_unref (base_sink->display); + base_sink->display = NULL; + } + if (base_sink->context) { + gst_object_unref (base_sink->context); + base_sink->context = NULL; + } + if (base_sink->gtk_context) { + gst_object_unref (base_sink->gtk_context); + base_sink->gtk_context = NULL; + } + if (base_sink->window) return ! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) gst_gtk_base_sink_stop_on_main, bsink); @@ -466,7 +657,32 @@ gst_gtk_base_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, } } -gboolean +static GstCaps * +gst_gtk_base_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) +{ + GstCaps *tmp = NULL; + GstCaps *result = NULL; + + tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink)); + + if (filter) { + GST_DEBUG_OBJECT (bsink, "intersecting with filter caps %" GST_PTR_FORMAT, + filter); + + result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (tmp); + } else { + result = tmp; + } + + result = gst_gl_overlay_compositor_add_caps (result); + + GST_DEBUG_OBJECT (bsink, "returning caps: %" GST_PTR_FORMAT, result); + + return result; +} + +static gboolean gst_gtk_base_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstGtkBaseSink *gtk_sink = GST_GTK_BASE_SINK (bsink); diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.h b/lib/gst/clapper/gtk4/gstgtkbasesink.h index f12ab636..bac19ac7 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.h +++ b/lib/gst/clapper/gtk4/gstgtkbasesink.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "gtkgstbasewidget.h" @@ -37,7 +38,6 @@ #define GST_GTK_BASE_SINK_CAST(obj) ((GstGtkBaseSink*)(obj)) G_BEGIN_DECLS - typedef struct _GstGtkBaseSink GstGtkBaseSink; typedef struct _GstGtkBaseSinkClass GstGtkBaseSinkClass; @@ -71,6 +71,17 @@ struct _GstGtkBaseSink GtkWidget *window; gulong widget_destroy_id; gulong window_destroy_id; + + GstGLDisplay *display; + GstGLContext *context; + GstGLContext *gtk_context; + + GstGLUpload *upload; + GstBuffer *uploaded_buffer; + + /* read/write with object lock */ + gint display_width; + gint display_height; }; /** diff --git a/lib/gst/clapper/gtk4/gstgtkglsink.c b/lib/gst/clapper/gtk4/gstgtkglsink.c deleted file mode 100644 index a6854f98..00000000 --- a/lib/gst/clapper/gtk4/gstgtkglsink.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters - * Copyright (C) 2020 Rafał Dzięgiel - * - * 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. - */ - -/** - * SECTION:element-gtkglsink - * @title: gtkglsink - */ - -/** - * SECTION:element-gtk4glsink - * @title: gtk4glsink - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gtkconfig.h" -#include "gstgtkglsink.h" -#include "gtkgstglwidget.h" - -GST_DEBUG_CATEGORY (gst_debug_gtk_gl_sink); -#define GST_CAT_DEFAULT gst_debug_gtk_gl_sink - -static gboolean gst_gtk_gl_sink_start (GstBaseSink * bsink); -static gboolean gst_gtk_gl_sink_stop (GstBaseSink * bsink); -static gboolean gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query); -static gboolean gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, - GstQuery * query); -static GstCaps *gst_gtk_gl_sink_get_caps (GstBaseSink * bsink, - GstCaps * filter); - -static void gst_gtk_gl_sink_finalize (GObject * object); - -static GstStaticPadTemplate gst_gtk_gl_sink_template = - GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, "RGBA") "; " - GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_GL_MEMORY ", " - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, "RGBA"))); - -#define gst_gtk_gl_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGtkGLSink, gst_gtk_gl_sink, - GST_TYPE_GTK_BASE_SINK, GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_gl_sink, - GTKCONFIG_GLSINK, 0, GTKCONFIG_NAME " GL Video Sink")); - -static void -gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - GstGtkBaseSinkClass *gstgtkbasesink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstgtkbasesink_class = (GstGtkBaseSinkClass *) klass; - - gobject_class->finalize = gst_gtk_gl_sink_finalize; - - gstbasesink_class->query = gst_gtk_gl_sink_query; - gstbasesink_class->propose_allocation = gst_gtk_gl_sink_propose_allocation; - gstbasesink_class->start = gst_gtk_gl_sink_start; - gstbasesink_class->stop = gst_gtk_gl_sink_stop; - gstbasesink_class->get_caps = gst_gtk_gl_sink_get_caps; - - gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new; - gstgtkbasesink_class->window_title = GTKCONFIG_NAME " GL Renderer"; - - gst_element_class_set_metadata (gstelement_class, - GTKCONFIG_NAME " GL Video Sink", - "Sink/Video", "A video sink that renders to a GtkWidget using OpenGL", - "Matthew Waters , " - "Rafał Dzięgiel "); - - gst_element_class_add_static_pad_template (gstelement_class, - &gst_gtk_gl_sink_template); -} - -static void -gst_gtk_gl_sink_init (GstGtkGLSink * gtk_sink) -{ -} - -static gboolean -gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query) -{ - GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (bsink); - gboolean res = FALSE; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONTEXT: - { - if (gst_gl_handle_context_query ((GstElement *) gtk_sink, query, - gtk_sink->display, gtk_sink->context, gtk_sink->gtk_context)) - return TRUE; - break; - } - default: - res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); - break; - } - - return res; -} - -static void -destroy_cb (GtkWidget * widget, GstGtkGLSink * gtk_sink) -{ - if (gtk_sink->widget_destroy_sig_handler) { - g_signal_handler_disconnect (widget, gtk_sink->widget_destroy_sig_handler); - gtk_sink->widget_destroy_sig_handler = 0; - } -} - -static gboolean -gst_gtk_gl_sink_start (GstBaseSink * bsink) -{ - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); - GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (bsink); - GtkGstGLWidget *gst_widget; - - if (!GST_BASE_SINK_CLASS (parent_class)->start (bsink)) - return FALSE; - - /* After this point, gtk_sink->widget will always be set */ - gst_widget = GTK_GST_GL_WIDGET (base_sink->widget); - - if (!gtk_sink->widget_destroy_sig_handler) { - gtk_sink->widget_destroy_sig_handler = - g_signal_connect (gst_widget, "destroy", G_CALLBACK (destroy_cb), - gtk_sink); - } - - if (!gtk_gst_gl_widget_init_winsys (gst_widget)) { - GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", - "Failed to initialize OpenGL with GTK"), (NULL)); - return FALSE; - } - - if (!gtk_sink->display) - gtk_sink->display = gtk_gst_gl_widget_get_display (gst_widget); - if (!gtk_sink->context) - gtk_sink->context = gtk_gst_gl_widget_get_context (gst_widget); - if (!gtk_sink->gtk_context) - gtk_sink->gtk_context = gtk_gst_gl_widget_get_gtk_context (gst_widget); - - if (!gtk_sink->display || !gtk_sink->context || !gtk_sink->gtk_context) { - GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", - "Failed to retrieve OpenGL context from GTK"), (NULL)); - return FALSE; - } - - gst_gl_element_propagate_display_context (GST_ELEMENT (bsink), - gtk_sink->display); - - return TRUE; -} - -static gboolean -gst_gtk_gl_sink_stop (GstBaseSink * bsink) -{ - GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (bsink); - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); - - if (gtk_sink->display) { - gst_object_unref (gtk_sink->display); - gtk_sink->display = NULL; - } - - if (gtk_sink->context) { - gst_object_unref (gtk_sink->context); - gtk_sink->context = NULL; - } - - if (gtk_sink->gtk_context) { - gst_object_unref (gtk_sink->gtk_context); - gtk_sink->gtk_context = NULL; - } - - return GST_BASE_SINK_CLASS (parent_class)->stop (bsink); -} - -static gboolean -gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) -{ - GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (bsink); - GstBufferPool *pool = NULL; - GstStructure *config; - GstCaps *caps; - GstVideoInfo info; - guint size; - gboolean need_pool; - GstStructure *allocation_meta = NULL; - gint display_width, display_height; - - if (!gtk_sink->display || !gtk_sink->context) - return FALSE; - - gst_query_parse_allocation (query, &caps, &need_pool); - - if (caps == NULL) - goto no_caps; - - if (!gst_video_info_from_caps (&info, caps)) - goto invalid_caps; - - /* the normal size of a frame */ - size = info.size; - - if (need_pool) { - GST_DEBUG_OBJECT (gtk_sink, "create new pool"); - pool = gst_gl_buffer_pool_new (gtk_sink->context); - - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_set_params (config, caps, size, 0, 0); - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_GL_SYNC_META); - - if (!gst_buffer_pool_set_config (pool, config)) - goto config_failed; - } - - /* we need at least 2 buffer because we hold on to the last one */ - gst_query_add_allocation_pool (query, pool, size, 2, 0); - if (pool) - gst_object_unref (pool); - - GST_OBJECT_LOCK (gtk_sink); - display_width = gtk_sink->display_width; - display_height = gtk_sink->display_height; - GST_OBJECT_UNLOCK (gtk_sink); - - if (display_width != 0 && display_height != 0) { - GST_DEBUG_OBJECT (gtk_sink, "sending alloc query with size %dx%d", - display_width, display_height); - allocation_meta = gst_structure_new ("GstVideoOverlayCompositionMeta", - "width", G_TYPE_UINT, display_width, - "height", G_TYPE_UINT, display_height, NULL); - } - - gst_query_add_allocation_meta (query, - GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, allocation_meta); - - if (allocation_meta) - gst_structure_free (allocation_meta); - - /* we also support various metadata */ - gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); - - if (gtk_sink->context->gl_vtable->FenceSync) - gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0); - - 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"); - return FALSE; - } -} - -static GstCaps * -gst_gtk_gl_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) -{ - GstCaps *tmp = NULL; - GstCaps *result = NULL; - - tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink)); - - if (filter) { - GST_DEBUG_OBJECT (bsink, "intersecting with filter caps %" GST_PTR_FORMAT, - filter); - - result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (tmp); - } else { - result = tmp; - } - - result = gst_gl_overlay_compositor_add_caps (result); - - GST_DEBUG_OBJECT (bsink, "returning caps: %" GST_PTR_FORMAT, result); - - return result; -} - -static void -gst_gtk_gl_sink_finalize (GObject * object) -{ - GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (object); - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (object); - - if (gtk_sink->widget_destroy_sig_handler) { - g_signal_handler_disconnect (base_sink->widget, - gtk_sink->widget_destroy_sig_handler); - gtk_sink->widget_destroy_sig_handler = 0; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} diff --git a/lib/gst/clapper/gtk4/gstgtkglsink.h b/lib/gst/clapper/gtk4/gstgtkglsink.h deleted file mode 100644 index 9dbe8fc0..00000000 --- a/lib/gst/clapper/gtk4/gstgtkglsink.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters - * - * 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_GTK_GL_SINK_H__ -#define __GST_GTK_GL_SINK_H__ - -#include -#include -#include -#include -#include - -#include "gstgtkbasesink.h" - -G_BEGIN_DECLS - -#define GST_TYPE_GTK_GL_SINK (gst_gtk_gl_sink_get_type ()) -G_DECLARE_FINAL_TYPE (GstGtkGLSink, gst_gtk_gl_sink, GST, GTK_GL_SINK, - GstGtkBaseSink); - -/** - * GstGtkGLSink: - * - * Opaque #GstGtkGLSink object - */ -struct _GstGtkGLSink -{ - /* */ - GstGtkBaseSink parent; - - GstGLDisplay *display; - GstGLContext *context; - GstGLContext *gtk_context; - - GstGLUpload *upload; - GstBuffer *uploaded_buffer; - - /* read/write with object lock */ - gint display_width; - gint display_height; - - gulong widget_destroy_sig_handler; -}; - -G_END_DECLS - -#endif /* __GST_GTK_GL_SINK_H__ */ diff --git a/lib/gst/clapper/meson.build b/lib/gst/clapper/meson.build index 456706d8..bbf910fa 100644 --- a/lib/gst/clapper/meson.build +++ b/lib/gst/clapper/meson.build @@ -11,7 +11,6 @@ gstclapper_sources = [ 'gtk4/gstgtkbasesink.c', 'gtk4/gstgtkutils.c', 'gtk4/gtkgstbasewidget.c', - 'gtk4/gstgtkglsink.c', 'gtk4/gtkgstglwidget.c', ] gstclapper_headers = [ From 13d675beff9c92ca9649b101e47ccb980a5b1b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 5 Mar 2021 23:23:34 +0100 Subject: [PATCH 06/10] Sink: merge gtkwidget into single class Same as with video sink. Clapper uses only one so no need for subclassing. --- lib/gst/clapper/gtk4/gstgtkbasesink.c | 15 +- lib/gst/clapper/gtk4/gtkgstbasewidget.c | 694 +++++++++++++++++++++--- lib/gst/clapper/gtk4/gtkgstbasewidget.h | 40 +- lib/gst/clapper/gtk4/gtkgstglwidget.c | 584 -------------------- lib/gst/clapper/gtk4/gtkgstglwidget.h | 77 --- lib/gst/clapper/meson.build | 1 - 6 files changed, 642 insertions(+), 769 deletions(-) delete mode 100644 lib/gst/clapper/gtk4/gtkgstglwidget.c delete mode 100644 lib/gst/clapper/gtk4/gtkgstglwidget.h diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.c b/lib/gst/clapper/gtk4/gstgtkbasesink.c index 47b38e71..9dd973cd 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.c +++ b/lib/gst/clapper/gtk4/gstgtkbasesink.c @@ -34,7 +34,6 @@ #include "gtkconfig.h" #include "gstgtkbasesink.h" #include "gstgtkutils.h" -#include "gtkgstglwidget.h" GST_DEBUG_CATEGORY (gst_debug_gtk_base_sink); #define GST_CAT_DEFAULT gst_debug_gtk_base_sink @@ -154,7 +153,7 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) gstvideosink_class->show_frame = gst_gtk_base_sink_show_frame; - gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new; + gstgtkbasesink_class->create_widget = gtk_gst_base_widget_new; gstgtkbasesink_class->window_title = GTKCONFIG_NAME " GL Renderer"; gst_element_class_set_metadata (gstelement_class, @@ -512,27 +511,27 @@ static gboolean gst_gtk_base_sink_start (GstBaseSink * bsink) { GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); - GtkGstGLWidget *gst_widget; + GtkGstBaseWidget *base_widget; if (!(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) gst_gtk_base_sink_start_on_main, bsink))) return FALSE; /* After this point, base_sink->widget will always be set */ - gst_widget = GTK_GST_GL_WIDGET (base_sink->widget); + base_widget = GTK_GST_BASE_WIDGET (base_sink->widget); - if (!gtk_gst_gl_widget_init_winsys (gst_widget)) { + if (!gtk_gst_base_widget_init_winsys (base_widget)) { GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", "Failed to initialize OpenGL with GTK"), (NULL)); return FALSE; } if (!base_sink->display) - base_sink->display = gtk_gst_gl_widget_get_display (gst_widget); + base_sink->display = gtk_gst_base_widget_get_display (base_widget); if (!base_sink->context) - base_sink->context = gtk_gst_gl_widget_get_context (gst_widget); + base_sink->context = gtk_gst_base_widget_get_context (base_widget); if (!base_sink->gtk_context) - base_sink->gtk_context = gtk_gst_gl_widget_get_gtk_context (gst_widget); + base_sink->gtk_context = gtk_gst_base_widget_get_gtk_context (base_widget); if (!base_sink->display || !base_sink->context || !base_sink->gtk_context) { GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.c b/lib/gst/clapper/gtk4/gtkgstbasewidget.c index f1795546..03ce8793 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.c +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.c @@ -24,8 +24,30 @@ #endif #include +#include +#include #include "gtkgstbasewidget.h" +#include "gstgtkutils.h" + +#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) +#include +#include +#endif + +#if GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND) +#include +#include +#endif + +/** + * SECTION:gtkgstbasewidget + * @title: GtkGstBaseWidget + * @short_description: a #GtkGLArea that renders GStreamer video #GstBuffers + * @see_also: #GtkGLArea, #GstBuffer + * + * #GtkGstBaseWidget is an #GtkWidget that renders GStreamer video buffers. + */ GST_DEBUG_CATEGORY (gst_debug_gtk_base_widget); #define GST_CAT_DEFAULT gst_debug_gtk_base_widget @@ -35,6 +57,39 @@ GST_DEBUG_CATEGORY (gst_debug_gtk_base_widget); #define DEFAULT_PAR_D 1 #define DEFAULT_IGNORE_TEXTURES FALSE +struct _GtkGstBaseWidgetPrivate +{ + gboolean initiated; + GstGLDisplay *display; + GdkGLContext *gdk_context; + GstGLContext *other_context; + GstGLContext *context; + GstGLUpload *upload; + GstGLShader *shader; + GLuint vao; + GLuint vertex_buffer; + GLint attr_position; + GLint attr_texture; + GLuint current_tex; + GstGLOverlayCompositor *overlay_compositor; +}; + +static const GLfloat vertices[] = { + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 1.0f +}; + +static const GLushort indices[] = { + 0, 1, 2, 0, 2, 3 +}; + +G_DEFINE_TYPE_WITH_CODE (GtkGstBaseWidget, gtk_gst_base_widget, GTK_TYPE_GL_AREA, + G_ADD_PRIVATE (GtkGstBaseWidget) + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkgstbasewidget", 0, + "GTK Gst Base Widget")); + enum { PROP_0, @@ -47,10 +102,10 @@ static void gtk_gst_base_widget_get_preferred_width (GtkWidget * widget, gint * min, gint * natural) { - GtkGstBaseWidget *gst_widget = (GtkGstBaseWidget *) widget; - gint video_width = gst_widget->display_width; + GtkGstBaseWidget *base_widget = (GtkGstBaseWidget *) widget; + gint video_width = base_widget->display_width; - if (!gst_widget->negotiated) + if (!base_widget->negotiated) video_width = 10; if (min) @@ -63,10 +118,10 @@ static void gtk_gst_base_widget_get_preferred_height (GtkWidget * widget, gint * min, gint * natural) { - GtkGstBaseWidget *gst_widget = (GtkGstBaseWidget *) widget; - gint video_height = gst_widget->display_height; + GtkGstBaseWidget *base_widget = (GtkGstBaseWidget *) widget; + gint video_height = base_widget->display_height; - if (!gst_widget->negotiated) + if (!base_widget->negotiated) video_height = 10; if (min) @@ -410,98 +465,288 @@ gtk_gst_base_widget_motion_event (GtkEventControllerMotion * motion_controller, return FALSE; } -void -gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) +static void +gtk_gst_base_widget_bind_buffer (GtkGstBaseWidget * base_widget) { - GObjectClass *gobject_klass = (GObjectClass *) klass; - GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass; + GtkGstBaseWidgetPrivate *priv = base_widget->priv; + const GstGLFuncs *gl = priv->context->gl_vtable; - gobject_klass->set_property = gtk_gst_base_widget_set_property; - gobject_klass->get_property = gtk_gst_base_widget_get_property; + gl->BindBuffer (GL_ARRAY_BUFFER, priv->vertex_buffer); - g_object_class_install_property (gobject_klass, PROP_FORCE_ASPECT_RATIO, - g_param_spec_boolean ("force-aspect-ratio", - "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", - DEFAULT_FORCE_ASPECT_RATIO, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* Load the vertex position */ + gl->VertexAttribPointer (priv->attr_position, 3, GL_FLOAT, GL_FALSE, + 5 * sizeof (GLfloat), (void *) 0); - g_object_class_install_property (gobject_klass, PROP_PIXEL_ASPECT_RATIO, - gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio", - "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D, - G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* Load the texture coordinate */ + gl->VertexAttribPointer (priv->attr_texture, 2, GL_FLOAT, GL_FALSE, + 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); - g_object_class_install_property (gobject_klass, PROP_IGNORE_TEXTURES, - g_param_spec_boolean ("ignore-textures", "Ignore Textures", - "When enabled, textures will be ignored and not drawn", - DEFAULT_IGNORE_TEXTURES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - widget_klass->measure = gtk_gst_base_widget_measure; - widget_klass->size_allocate = gtk_gst_base_widget_size_allocate; - - GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_widget, "gtkbasewidget", 0, - "GTK Video Base Widget"); + gl->EnableVertexAttribArray (priv->attr_position); + gl->EnableVertexAttribArray (priv->attr_texture); } -void -gtk_gst_base_widget_init (GtkGstBaseWidget * widget) +static void +gtk_gst_base_widget_unbind_buffer (GtkGstBaseWidget * base_widget) { - widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; - widget->par_n = DEFAULT_PAR_N; - widget->par_d = DEFAULT_PAR_D; - widget->ignore_textures = DEFAULT_IGNORE_TEXTURES; + GtkGstBaseWidgetPrivate *priv = base_widget->priv; + const GstGLFuncs *gl = priv->context->gl_vtable; - gst_video_info_init (&widget->v_info); - gst_video_info_init (&widget->pending_v_info); + gl->BindBuffer (GL_ARRAY_BUFFER, 0); - g_weak_ref_init (&widget->element, NULL); - g_mutex_init (&widget->lock); - - widget->key_controller = gtk_event_controller_key_new (); - g_signal_connect (widget->key_controller, "key-pressed", - G_CALLBACK (gtk_gst_base_widget_key_event), NULL); - g_signal_connect (widget->key_controller, "key-released", - G_CALLBACK (gtk_gst_base_widget_key_event), NULL); - - widget->motion_controller = gtk_event_controller_motion_new (); - g_signal_connect (widget->motion_controller, "motion", - G_CALLBACK (gtk_gst_base_widget_motion_event), NULL); - - widget->click_gesture = gtk_gesture_click_new (); - g_signal_connect (widget->click_gesture, "pressed", - G_CALLBACK (gtk_gst_base_widget_button_event), NULL); - g_signal_connect (widget->click_gesture, "released", - G_CALLBACK (gtk_gst_base_widget_button_event), NULL); - - /* Otherwise widget in grid will appear as a 1x1px - * video which might be misleading for users */ - gtk_widget_set_hexpand (GTK_WIDGET (widget), TRUE); - gtk_widget_set_vexpand (GTK_WIDGET (widget), TRUE); - - gtk_widget_set_focusable (GTK_WIDGET (widget), TRUE); - gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (widget->click_gesture), - GDK_BUTTON_PRIMARY); - - gtk_widget_add_controller (GTK_WIDGET (widget), widget->key_controller); - gtk_widget_add_controller (GTK_WIDGET (widget), widget->motion_controller); - gtk_widget_add_controller (GTK_WIDGET (widget), - GTK_EVENT_CONTROLLER (widget->click_gesture)); - - gtk_widget_set_can_focus (GTK_WIDGET (widget), TRUE); + gl->DisableVertexAttribArray (priv->attr_position); + gl->DisableVertexAttribArray (priv->attr_texture); } -void +static void +gtk_gst_base_widget_init_redisplay (GtkGstBaseWidget * base_widget) +{ + GtkGstBaseWidgetPrivate *priv = base_widget->priv; + const GstGLFuncs *gl = priv->context->gl_vtable; + GError *error = NULL; + + gst_gl_insert_debug_marker (priv->other_context, "initializing redisplay"); + if (!(priv->shader = gst_gl_shader_new_default (priv->context, &error))) { + GST_ERROR ("Failed to initialize shader: %s", error->message); + return; + } + + priv->attr_position = + gst_gl_shader_get_attribute_location (priv->shader, "a_position"); + priv->attr_texture = + gst_gl_shader_get_attribute_location (priv->shader, "a_texcoord"); + + if (gl->GenVertexArrays) { + gl->GenVertexArrays (1, &priv->vao); + gl->BindVertexArray (priv->vao); + } + + gl->GenBuffers (1, &priv->vertex_buffer); + gl->BindBuffer (GL_ARRAY_BUFFER, priv->vertex_buffer); + gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), vertices, + GL_STATIC_DRAW); + + if (gl->GenVertexArrays) { + gtk_gst_base_widget_bind_buffer (base_widget); + gl->BindVertexArray (0); + } + + gl->BindBuffer (GL_ARRAY_BUFFER, 0); + + priv->overlay_compositor = + gst_gl_overlay_compositor_new (priv->other_context); + + priv->initiated = TRUE; +} + +static inline void +_draw_black (GstGLContext * context) +{ + const GstGLFuncs *gl = context->gl_vtable; + + gst_gl_insert_debug_marker (context, "rendering black"); + gl->ClearColor (0.0, 0.0, 0.0, 1.0); + gl->Clear (GL_COLOR_BUFFER_BIT); +} + +static inline void +_draw_black_with_gdk (GdkGLContext * gdk_context) +{ + GST_DEBUG ("rendering empty frame with gdk context %p", gdk_context); + glClearColor (0.0, 0.0, 0.0, 1.0); + glClear (GL_COLOR_BUFFER_BIT); +} + +static gboolean +gtk_gst_base_widget_render (GtkGLArea * widget, GdkGLContext * context) +{ + GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + + GtkGstBaseWidgetPrivate *priv = base_widget->priv; + const GstGLFuncs *gl; + + GTK_GST_BASE_WIDGET_LOCK (widget); + + /* Draw black with GDK context when priv is not available yet. + GTK calls render with GDK context already active. */ + if (!priv->context || !priv->other_context || base_widget->ignore_textures) { + _draw_black_with_gdk (context); + goto done; + } + + gst_gl_context_activate (priv->other_context, TRUE); + + if (!priv->initiated || !base_widget->negotiated) { + if (!priv->initiated) + gtk_gst_base_widget_init_redisplay (base_widget); + + _draw_black (priv->other_context); + goto done; + } + + /* Upload latest buffer */ + if (base_widget->pending_buffer) { + GstBuffer *buffer = base_widget->pending_buffer; + GstVideoFrame gl_frame; + GstGLSyncMeta *sync_meta; + + if (!gst_video_frame_map (&gl_frame, &base_widget->v_info, buffer, + GST_MAP_READ | GST_MAP_GL)) { + _draw_black (priv->other_context); + goto done; + } + + priv->current_tex = *(guint *) gl_frame.data[0]; + gst_gl_overlay_compositor_upload_overlays (priv->overlay_compositor, + buffer); + + sync_meta = gst_buffer_get_gl_sync_meta (buffer); + if (sync_meta) { + /* XXX: the set_sync() seems to be needed for resizing */ + gst_gl_sync_meta_set_sync_point (sync_meta, priv->context); + gst_gl_sync_meta_wait (sync_meta, priv->other_context); + } + + gst_video_frame_unmap (&gl_frame); + + if (base_widget->buffer) + gst_buffer_unref (base_widget->buffer); + + /* Keep the buffer to ensure current_tex stay valid */ + base_widget->buffer = buffer; + base_widget->pending_buffer = NULL; + } + + GST_DEBUG ("rendering buffer %p with gdk context %p", + base_widget->buffer, context); + + /* Draw texture */ + gl = priv->context->gl_vtable; + + if (base_widget->force_aspect_ratio) { + GstVideoRectangle src, dst, result; + + gl->ClearColor (0.0, 0.0, 0.0, 1.0); + gl->Clear (GL_COLOR_BUFFER_BIT); + + src.x = 0; + src.y = 0; + src.w = base_widget->display_width; + src.h = base_widget->display_height; + + dst.x = 0; + dst.y = 0; + dst.w = base_widget->scaled_width; + dst.h = base_widget->scaled_height; + + gst_video_sink_center_rect (src, dst, &result, TRUE); + + gl->Viewport (result.x, result.y, result.w, result.h); + } + + gst_gl_shader_use (priv->shader); + + if (gl->BindVertexArray) + gl->BindVertexArray (priv->vao); + + gtk_gst_base_widget_bind_buffer (base_widget); + + gl->ActiveTexture (GL_TEXTURE0); + gl->BindTexture (GL_TEXTURE_2D, priv->current_tex); + gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0); + + gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + if (gl->BindVertexArray) + gl->BindVertexArray (0); + else + gtk_gst_base_widget_unbind_buffer (base_widget); + + gl->BindTexture (GL_TEXTURE_2D, 0); + + /* Draw subtitles */ + gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor); + +done: + if (priv->other_context) + gst_gl_context_activate (priv->other_context, FALSE); + + GTK_GST_BASE_WIDGET_UNLOCK (widget); + return FALSE; +} + +static void +_reset_gl (GtkGstBaseWidget * base_widget) +{ + GtkGstBaseWidgetPrivate *priv = base_widget->priv; + const GstGLFuncs *gl = priv->other_context->gl_vtable; + + if (!priv->gdk_context) + priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (base_widget)); + + if (priv->gdk_context == NULL) + return; + + gdk_gl_context_make_current (priv->gdk_context); + gst_gl_context_activate (priv->other_context, TRUE); + + if (priv->vao) { + gl->DeleteVertexArrays (1, &priv->vao); + priv->vao = 0; + } + + if (priv->vertex_buffer) { + gl->DeleteBuffers (1, &priv->vertex_buffer); + priv->vertex_buffer = 0; + } + + if (priv->upload) { + gst_object_unref (priv->upload); + priv->upload = NULL; + } + + if (priv->shader) { + gst_object_unref (priv->shader); + priv->shader = NULL; + } + + if (priv->overlay_compositor) + gst_object_unref (priv->overlay_compositor); + + gst_gl_context_activate (priv->other_context, FALSE); + + gst_object_unref (priv->other_context); + priv->other_context = NULL; + + gdk_gl_context_clear_current (); + + g_object_unref (priv->gdk_context); + priv->gdk_context = NULL; +} + +static void gtk_gst_base_widget_finalize (GObject * object) { - GtkGstBaseWidget *widget = GTK_GST_BASE_WIDGET (object); + GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (object); + GtkGstBaseWidgetPrivate *priv = base_widget->priv; - gst_buffer_replace (&widget->pending_buffer, NULL); - gst_buffer_replace (&widget->buffer, NULL); - g_mutex_clear (&widget->lock); - g_weak_ref_clear (&widget->element); + if (priv->other_context) + gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _reset_gl, base_widget); - if (widget->draw_id) - g_source_remove (widget->draw_id); + if (priv->context) + gst_object_unref (priv->context); + + if (priv->display) + gst_object_unref (priv->display); + + if (base_widget->draw_id) + g_source_remove (base_widget->draw_id); + + gst_buffer_replace (&base_widget->pending_buffer, NULL); + gst_buffer_replace (&base_widget->buffer, NULL); + g_mutex_clear (&base_widget->lock); + g_weak_ref_clear (&base_widget->element); + + G_OBJECT_CLASS (gtk_gst_base_widget_parent_class)->finalize (object); } void @@ -552,3 +797,288 @@ gtk_gst_base_widget_set_buffer (GtkGstBaseWidget * widget, GstBuffer * buffer) GTK_GST_BASE_WIDGET_UNLOCK (widget); } + +static void +_get_gl_context (GtkGstBaseWidget * base_widget) +{ + GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GstGLPlatform platform = GST_GL_PLATFORM_NONE; + GstGLAPI gl_api = GST_GL_API_NONE; + guintptr gl_handle = 0; + + gtk_widget_realize (GTK_WIDGET (base_widget)); + + if (priv->other_context) + gst_object_unref (priv->other_context); + priv->other_context = NULL; + + if (priv->gdk_context) + g_object_unref (priv->gdk_context); + + priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (base_widget)); + if (priv->gdk_context == NULL) { + GError *error = gtk_gl_area_get_error (GTK_GL_AREA (base_widget)); + + GST_ERROR_OBJECT (base_widget, "Error creating GdkGLContext : %s", + error ? error->message : "No error set by Gdk"); + g_clear_error (&error); + return; + } + + g_object_ref (priv->gdk_context); + + gdk_gl_context_make_current (priv->gdk_context); + +#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) + if (GST_IS_GL_DISPLAY_X11 (priv->display)) { +#if GST_GL_HAVE_PLATFORM_GLX + if (!gl_handle) { + platform = GST_GL_PLATFORM_GLX; + gl_handle = gst_gl_context_get_current_gl_context (platform); + } +#endif + +#if GST_GL_HAVE_PLATFORM_EGL + if (!gl_handle) { + platform = GST_GL_PLATFORM_EGL; + gl_handle = gst_gl_context_get_current_gl_context (platform); + } +#endif + + if (gl_handle) { + gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL); + priv->other_context = + gst_gl_context_new_wrapped (priv->display, gl_handle, + platform, gl_api); + } + } +#endif +#if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (GDK_WINDOWING_WAYLAND) + if (GST_IS_GL_DISPLAY_WAYLAND (priv->display)) { + platform = GST_GL_PLATFORM_EGL; + gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL); + gl_handle = gst_gl_context_get_current_gl_context (platform); + if (gl_handle) + priv->other_context = + gst_gl_context_new_wrapped (priv->display, gl_handle, + platform, gl_api); + } +#endif + + (void) platform; + (void) gl_api; + (void) gl_handle; + + if (priv->other_context) { + GError *error = NULL; + + GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT, + priv->other_context); + gst_gl_context_activate (priv->other_context, TRUE); + if (!gst_gl_context_fill_info (priv->other_context, &error)) { + GST_ERROR ("failed to retrieve gdk context info: %s", error->message); + g_clear_error (&error); + g_object_unref (priv->other_context); + priv->other_context = NULL; + } else { + gst_gl_context_activate (priv->other_context, FALSE); + } + } else { + GST_WARNING ("Could not retrieve Gdk OpenGL context"); + } +} + +static void +gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) +{ + GObjectClass *gobject_klass = (GObjectClass *) klass; + GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass; + GtkGLAreaClass *gl_area_klass = (GtkGLAreaClass *) klass; + + gobject_klass->set_property = gtk_gst_base_widget_set_property; + gobject_klass->get_property = gtk_gst_base_widget_get_property; + gobject_klass->finalize = gtk_gst_base_widget_finalize; + + g_object_class_install_property (gobject_klass, PROP_FORCE_ASPECT_RATIO, + g_param_spec_boolean ("force-aspect-ratio", + "Force aspect ratio", + "When enabled, scaling will respect original aspect ratio", + DEFAULT_FORCE_ASPECT_RATIO, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_PIXEL_ASPECT_RATIO, + gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio", + "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D, + G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_IGNORE_TEXTURES, + g_param_spec_boolean ("ignore-textures", "Ignore Textures", + "When enabled, textures will be ignored and not drawn", + DEFAULT_IGNORE_TEXTURES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + widget_klass->measure = gtk_gst_base_widget_measure; + widget_klass->size_allocate = gtk_gst_base_widget_size_allocate; + + gl_area_klass->render = gtk_gst_base_widget_render; + + GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_widget, "gtkbasewidget", 0, + "GTK Video Base Widget"); +} + +static void +gtk_gst_base_widget_init (GtkGstBaseWidget * widget) +{ + GdkDisplay *display; + GtkGstBaseWidgetPrivate *priv; + + widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; + widget->par_n = DEFAULT_PAR_N; + widget->par_d = DEFAULT_PAR_D; + widget->ignore_textures = DEFAULT_IGNORE_TEXTURES; + + gst_video_info_init (&widget->v_info); + gst_video_info_init (&widget->pending_v_info); + + g_weak_ref_init (&widget->element, NULL); + g_mutex_init (&widget->lock); + + widget->key_controller = gtk_event_controller_key_new (); + g_signal_connect (widget->key_controller, "key-pressed", + G_CALLBACK (gtk_gst_base_widget_key_event), NULL); + g_signal_connect (widget->key_controller, "key-released", + G_CALLBACK (gtk_gst_base_widget_key_event), NULL); + + widget->motion_controller = gtk_event_controller_motion_new (); + g_signal_connect (widget->motion_controller, "motion", + G_CALLBACK (gtk_gst_base_widget_motion_event), NULL); + + widget->click_gesture = gtk_gesture_click_new (); + g_signal_connect (widget->click_gesture, "pressed", + G_CALLBACK (gtk_gst_base_widget_button_event), NULL); + g_signal_connect (widget->click_gesture, "released", + G_CALLBACK (gtk_gst_base_widget_button_event), NULL); + + /* Otherwise widget in grid will appear as a 1x1px + * video which might be misleading for users */ + gtk_widget_set_hexpand (GTK_WIDGET (widget), TRUE); + gtk_widget_set_vexpand (GTK_WIDGET (widget), TRUE); + + gtk_widget_set_focusable (GTK_WIDGET (widget), TRUE); + gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (widget->click_gesture), + GDK_BUTTON_PRIMARY); + + gtk_widget_add_controller (GTK_WIDGET (widget), widget->key_controller); + gtk_widget_add_controller (GTK_WIDGET (widget), widget->motion_controller); + gtk_widget_add_controller (GTK_WIDGET (widget), + GTK_EVENT_CONTROLLER (widget->click_gesture)); + + gtk_widget_set_can_focus (GTK_WIDGET (widget), TRUE); + + widget->priv = priv = gtk_gst_base_widget_get_instance_private (widget); + + display = gdk_display_get_default (); + +#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) + if (GDK_IS_X11_DISPLAY (display)) { + priv->display = (GstGLDisplay *) + gst_gl_display_x11_new_with_display (gdk_x11_display_get_xdisplay + (display)); + } +#endif +#if GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND) + if (GDK_IS_WAYLAND_DISPLAY (display)) { + struct wl_display *wayland_display = + gdk_wayland_display_get_wl_display (display); + priv->display = (GstGLDisplay *) + gst_gl_display_wayland_new_with_display (wayland_display); + } +#endif + + (void) display; + + if (!priv->display) + priv->display = gst_gl_display_new (); + + GST_INFO ("Created %" GST_PTR_FORMAT, priv->display); + + gtk_gl_area_set_auto_render (GTK_GL_AREA (widget), FALSE); +} + +GtkWidget * +gtk_gst_base_widget_new (void) +{ + return (GtkWidget *) g_object_new (GTK_TYPE_GST_BASE_WIDGET, NULL); +} + +gboolean +gtk_gst_base_widget_init_winsys (GtkGstBaseWidget * base_widget) +{ + GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GError *error = NULL; + + g_return_val_if_fail (GTK_IS_GST_BASE_WIDGET (base_widget), FALSE); + g_return_val_if_fail (priv->display != NULL, FALSE); + + GTK_GST_BASE_WIDGET_LOCK (base_widget); + + if (priv->display && priv->gdk_context && priv->other_context) { + GST_TRACE ("have already initialized contexts"); + GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + return TRUE; + } + + if (!priv->other_context) { + GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _get_gl_context, base_widget); + GTK_GST_BASE_WIDGET_LOCK (base_widget); + } + + if (!GST_IS_GL_CONTEXT (priv->other_context)) { + GST_FIXME ("Could not retrieve Gdk OpenGL context"); + GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + return FALSE; + } + + GST_OBJECT_LOCK (priv->display); + if (!gst_gl_display_create_context (priv->display, priv->other_context, + &priv->context, &error)) { + GST_WARNING ("Could not create OpenGL context: %s", + error ? error->message : "Unknown"); + g_clear_error (&error); + GST_OBJECT_UNLOCK (priv->display); + GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + return FALSE; + } + gst_gl_display_add_context (priv->display, priv->context); + GST_OBJECT_UNLOCK (priv->display); + + GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + return TRUE; +} + +GstGLContext * +gtk_gst_base_widget_get_gtk_context (GtkGstBaseWidget * base_widget) +{ + if (!base_widget->priv->other_context) + return NULL; + + return gst_object_ref (base_widget->priv->other_context); +} + +GstGLContext * +gtk_gst_base_widget_get_context (GtkGstBaseWidget * base_widget) +{ + if (!base_widget->priv->context) + return NULL; + + return gst_object_ref (base_widget->priv->context); +} + +GstGLDisplay * +gtk_gst_base_widget_get_display (GtkGstBaseWidget * base_widget) +{ + if (!base_widget->priv->display) + return NULL; + + return gst_object_ref (base_widget->priv->display); +} diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.h b/lib/gst/clapper/gtk4/gtkgstbasewidget.h index 8721c441..c7a1e6d3 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.h +++ b/lib/gst/clapper/gtk4/gtkgstbasewidget.h @@ -25,22 +25,29 @@ #include #include #include - -#define GTK_GST_BASE_WIDGET(w) ((GtkGstBaseWidget *)(w)) -#define GTK_GST_BASE_WIDGET_CLASS(k) ((GtkGstBaseWidgetClass *)(k)) -#define GTK_GST_BASE_WIDGET_LOCK(w) g_mutex_lock(&((GtkGstBaseWidget*)(w))->lock) -#define GTK_GST_BASE_WIDGET_UNLOCK(w) g_mutex_unlock(&((GtkGstBaseWidget*)(w))->lock) +#include G_BEGIN_DECLS +GType gtk_gst_base_widget_get_type (void); +#define GTK_TYPE_GST_BASE_WIDGET (gtk_gst_base_widget_get_type()) +#define GTK_GST_BASE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GTK_TYPE_GST_BASE_WIDGET,GtkGstBaseWidget)) +#define GTK_GST_BASE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GTK_TYPE_GST_BASE_WIDGET,GtkGstBaseWidgetClass)) +#define GTK_IS_GST_BASE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GTK_TYPE_GST_BASE_WIDGET)) +#define GTK_IS_GST_BASE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GTK_TYPE_GST_BASE_WIDGET)) +#define GTK_GST_BASE_WIDGET_CAST(obj) ((GtkGstBaseWidget*)(obj)) +#define GTK_GST_BASE_WIDGET_LOCK(w) g_mutex_lock(&((GtkGstBaseWidget*)(w))->lock) +#define GTK_GST_BASE_WIDGET_UNLOCK(w) g_mutex_unlock(&((GtkGstBaseWidget*)(w))->lock) + typedef struct _GtkGstBaseWidget GtkGstBaseWidget; typedef struct _GtkGstBaseWidgetClass GtkGstBaseWidgetClass; +typedef struct _GtkGstBaseWidgetPrivate GtkGstBaseWidgetPrivate; struct _GtkGstBaseWidget { - union { - GtkGLArea gl_area; - } parent; + /* */ + GtkGLArea parent; + GtkGstBaseWidgetPrivate *priv; /* properties */ gboolean force_aspect_ratio; @@ -80,22 +87,21 @@ struct _GtkGstBaseWidget struct _GtkGstBaseWidgetClass { - union { - GtkGLAreaClass gl_area_class; - } parent_class; + GtkGLAreaClass parent_class; }; -/* For implementer */ -void gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass); -void gtk_gst_base_widget_init (GtkGstBaseWidget * widget); - -void gtk_gst_base_widget_finalize (GObject * object); - /* API */ gboolean gtk_gst_base_widget_set_format (GtkGstBaseWidget * widget, GstVideoInfo * v_info); void gtk_gst_base_widget_set_buffer (GtkGstBaseWidget * widget, GstBuffer * buffer); void gtk_gst_base_widget_set_element (GtkGstBaseWidget * widget, GstElement * element); +GtkWidget * gtk_gst_base_widget_new (void); + +gboolean gtk_gst_base_widget_init_winsys (GtkGstBaseWidget * widget); +GstGLDisplay * gtk_gst_base_widget_get_display (GtkGstBaseWidget * widget); +GstGLContext * gtk_gst_base_widget_get_context (GtkGstBaseWidget * widget); +GstGLContext * gtk_gst_base_widget_get_gtk_context (GtkGstBaseWidget * widget); + G_END_DECLS #endif /* __GTK_GST_BASE_WIDGET_H__ */ diff --git a/lib/gst/clapper/gtk4/gtkgstglwidget.c b/lib/gst/clapper/gtk4/gtkgstglwidget.c deleted file mode 100644 index 6b3ee8df..00000000 --- a/lib/gst/clapper/gtk4/gtkgstglwidget.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters - * Copyright (C) 2020 Rafał Dzięgiel - * - * 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 - -#include "gtkgstglwidget.h" -#include "gstgtkutils.h" -#include -#include - -#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) -#include -#include -#endif - -#if GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND) -#include -#include -#endif - -/** - * SECTION:gtkgstglwidget - * @title: GtkGstGlWidget - * @short_description: a #GtkGLArea that renders GStreamer video #GstBuffers - * @see_also: #GtkGLArea, #GstBuffer - * - * #GtkGstGLWidget is an #GtkWidget that renders GStreamer video buffers. - */ - -#define GST_CAT_DEFAULT gtk_gst_gl_widget_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -struct _GtkGstGLWidgetPrivate -{ - gboolean initiated; - GstGLDisplay *display; - GdkGLContext *gdk_context; - GstGLContext *other_context; - GstGLContext *context; - GstGLUpload *upload; - GstGLShader *shader; - GLuint vao; - GLuint vertex_buffer; - GLint attr_position; - GLint attr_texture; - GLuint current_tex; - GstGLOverlayCompositor *overlay_compositor; -}; - -static const GLfloat vertices[] = { - 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 1.0f -}; - -static const GLushort indices[] = { - 0, 1, 2, 0, 2, 3 -}; - -G_DEFINE_TYPE_WITH_CODE (GtkGstGLWidget, gtk_gst_gl_widget, GTK_TYPE_GL_AREA, - G_ADD_PRIVATE (GtkGstGLWidget) - GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkgstglwidget", 0, - "GTK Gst GL Widget")); - -static void -gtk_gst_gl_widget_bind_buffer (GtkGstGLWidget * gst_widget) -{ - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - const GstGLFuncs *gl = priv->context->gl_vtable; - - gl->BindBuffer (GL_ARRAY_BUFFER, priv->vertex_buffer); - - /* Load the vertex position */ - gl->VertexAttribPointer (priv->attr_position, 3, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) 0); - - /* Load the texture coordinate */ - gl->VertexAttribPointer (priv->attr_texture, 2, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); - - gl->EnableVertexAttribArray (priv->attr_position); - gl->EnableVertexAttribArray (priv->attr_texture); -} - -static void -gtk_gst_gl_widget_unbind_buffer (GtkGstGLWidget * gst_widget) -{ - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - const GstGLFuncs *gl = priv->context->gl_vtable; - - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - gl->DisableVertexAttribArray (priv->attr_position); - gl->DisableVertexAttribArray (priv->attr_texture); -} - -static void -gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget) -{ - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - const GstGLFuncs *gl = priv->context->gl_vtable; - GError *error = NULL; - - gst_gl_insert_debug_marker (priv->other_context, "initializing redisplay"); - if (!(priv->shader = gst_gl_shader_new_default (priv->context, &error))) { - GST_ERROR ("Failed to initialize shader: %s", error->message); - return; - } - - priv->attr_position = - gst_gl_shader_get_attribute_location (priv->shader, "a_position"); - priv->attr_texture = - gst_gl_shader_get_attribute_location (priv->shader, "a_texcoord"); - - if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &priv->vao); - gl->BindVertexArray (priv->vao); - } - - gl->GenBuffers (1, &priv->vertex_buffer); - gl->BindBuffer (GL_ARRAY_BUFFER, priv->vertex_buffer); - gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), vertices, - GL_STATIC_DRAW); - - if (gl->GenVertexArrays) { - gtk_gst_gl_widget_bind_buffer (gst_widget); - gl->BindVertexArray (0); - } - - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - priv->overlay_compositor = - gst_gl_overlay_compositor_new (priv->other_context); - - priv->initiated = TRUE; -} - -static inline void -_draw_black (GstGLContext * context) -{ - const GstGLFuncs *gl = context->gl_vtable; - - gst_gl_insert_debug_marker (context, "rendering black"); - gl->ClearColor (0.0, 0.0, 0.0, 1.0); - gl->Clear (GL_COLOR_BUFFER_BIT); -} - -static inline void -_draw_black_with_gdk (GdkGLContext * gdk_context) -{ - GST_DEBUG ("rendering empty frame with gdk context %p", gdk_context); - glClearColor (0.0, 0.0, 0.0, 1.0); - glClear (GL_COLOR_BUFFER_BIT); -} - -static gboolean -gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) -{ - GtkGstGLWidget *gst_widget = GTK_GST_GL_WIDGET (widget); - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); - - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - const GstGLFuncs *gl; - - GTK_GST_BASE_WIDGET_LOCK (widget); - - /* Draw black with GDK context when priv is not available yet. - GTK calls render with GDK context already active. */ - if (!priv->context || !priv->other_context || base_widget->ignore_textures) { - _draw_black_with_gdk (context); - goto done; - } - - gst_gl_context_activate (priv->other_context, TRUE); - - if (!priv->initiated || !base_widget->negotiated) { - if (!priv->initiated) - gtk_gst_gl_widget_init_redisplay (gst_widget); - - _draw_black (priv->other_context); - goto done; - } - - /* Upload latest buffer */ - if (base_widget->pending_buffer) { - GstBuffer *buffer = base_widget->pending_buffer; - GstVideoFrame gl_frame; - GstGLSyncMeta *sync_meta; - - if (!gst_video_frame_map (&gl_frame, &base_widget->v_info, buffer, - GST_MAP_READ | GST_MAP_GL)) { - _draw_black (priv->other_context); - goto done; - } - - priv->current_tex = *(guint *) gl_frame.data[0]; - gst_gl_overlay_compositor_upload_overlays (priv->overlay_compositor, - buffer); - - sync_meta = gst_buffer_get_gl_sync_meta (buffer); - if (sync_meta) { - /* XXX: the set_sync() seems to be needed for resizing */ - gst_gl_sync_meta_set_sync_point (sync_meta, priv->context); - gst_gl_sync_meta_wait (sync_meta, priv->other_context); - } - - gst_video_frame_unmap (&gl_frame); - - if (base_widget->buffer) - gst_buffer_unref (base_widget->buffer); - - /* Keep the buffer to ensure current_tex stay valid */ - base_widget->buffer = buffer; - base_widget->pending_buffer = NULL; - } - - GST_DEBUG ("rendering buffer %p with gdk context %p", - base_widget->buffer, context); - - /* Draw texture */ - gl = priv->context->gl_vtable; - - if (base_widget->force_aspect_ratio) { - GstVideoRectangle src, dst, result; - - gl->ClearColor (0.0, 0.0, 0.0, 1.0); - gl->Clear (GL_COLOR_BUFFER_BIT); - - src.x = 0; - src.y = 0; - src.w = base_widget->display_width; - src.h = base_widget->display_height; - - dst.x = 0; - dst.y = 0; - dst.w = base_widget->scaled_width; - dst.h = base_widget->scaled_height; - - gst_video_sink_center_rect (src, dst, &result, TRUE); - - gl->Viewport (result.x, result.y, result.w, result.h); - } - - gst_gl_shader_use (priv->shader); - - if (gl->BindVertexArray) - gl->BindVertexArray (priv->vao); - - gtk_gst_gl_widget_bind_buffer (gst_widget); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, priv->current_tex); - gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0); - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); - - if (gl->BindVertexArray) - gl->BindVertexArray (0); - else - gtk_gst_gl_widget_unbind_buffer (gst_widget); - - gl->BindTexture (GL_TEXTURE_2D, 0); - - /* Draw subtitles */ - gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor); - -done: - if (priv->other_context) - gst_gl_context_activate (priv->other_context, FALSE); - - GTK_GST_BASE_WIDGET_UNLOCK (widget); - return FALSE; -} - -static void -_reset_gl (GtkGstGLWidget * gst_widget) -{ - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - const GstGLFuncs *gl = priv->other_context->gl_vtable; - - if (!priv->gdk_context) - priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (gst_widget)); - - if (priv->gdk_context == NULL) - return; - - gdk_gl_context_make_current (priv->gdk_context); - gst_gl_context_activate (priv->other_context, TRUE); - - if (priv->vao) { - gl->DeleteVertexArrays (1, &priv->vao); - priv->vao = 0; - } - - if (priv->vertex_buffer) { - gl->DeleteBuffers (1, &priv->vertex_buffer); - priv->vertex_buffer = 0; - } - - if (priv->upload) { - gst_object_unref (priv->upload); - priv->upload = NULL; - } - - if (priv->shader) { - gst_object_unref (priv->shader); - priv->shader = NULL; - } - - if (priv->overlay_compositor) - gst_object_unref (priv->overlay_compositor); - - gst_gl_context_activate (priv->other_context, FALSE); - - gst_object_unref (priv->other_context); - priv->other_context = NULL; - - gdk_gl_context_clear_current (); - - g_object_unref (priv->gdk_context); - priv->gdk_context = NULL; -} - -static void -gtk_gst_gl_widget_finalize (GObject * object) -{ - GtkGstGLWidgetPrivate *priv = GTK_GST_GL_WIDGET (object)->priv; - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (object); - - if (priv->other_context) - gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _reset_gl, base_widget); - - if (priv->context) - gst_object_unref (priv->context); - - if (priv->display) - gst_object_unref (priv->display); - - gtk_gst_base_widget_finalize (object); - G_OBJECT_CLASS (gtk_gst_gl_widget_parent_class)->finalize (object); -} - -static void -gtk_gst_gl_widget_class_init (GtkGstGLWidgetClass * klass) -{ - GObjectClass *gobject_klass = (GObjectClass *) klass; - GtkGLAreaClass *gl_widget_klass = (GtkGLAreaClass *) klass; - - gtk_gst_base_widget_class_init (GTK_GST_BASE_WIDGET_CLASS (klass)); - - gobject_klass->finalize = gtk_gst_gl_widget_finalize; - gl_widget_klass->render = gtk_gst_gl_widget_render; -} - -static void -gtk_gst_gl_widget_init (GtkGstGLWidget * gst_widget) -{ - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (gst_widget); - GdkDisplay *display; - GtkGstGLWidgetPrivate *priv; - - gtk_gst_base_widget_init (base_widget); - - gst_widget->priv = priv = gtk_gst_gl_widget_get_instance_private (gst_widget); - - display = gdk_display_get_default (); - -#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) - if (GDK_IS_X11_DISPLAY (display)) { - priv->display = (GstGLDisplay *) - gst_gl_display_x11_new_with_display (gdk_x11_display_get_xdisplay - (display)); - } -#endif -#if GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND) - if (GDK_IS_WAYLAND_DISPLAY (display)) { - struct wl_display *wayland_display = - gdk_wayland_display_get_wl_display (display); - priv->display = (GstGLDisplay *) - gst_gl_display_wayland_new_with_display (wayland_display); - } -#endif - - (void) display; - - if (!priv->display) - priv->display = gst_gl_display_new (); - - GST_INFO ("Created %" GST_PTR_FORMAT, priv->display); - - gtk_gl_area_set_auto_render (GTK_GL_AREA (gst_widget), FALSE); -} - -static void -_get_gl_context (GtkGstGLWidget * gst_widget) -{ - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - GstGLPlatform platform = GST_GL_PLATFORM_NONE; - GstGLAPI gl_api = GST_GL_API_NONE; - guintptr gl_handle = 0; - - gtk_widget_realize (GTK_WIDGET (gst_widget)); - - if (priv->other_context) - gst_object_unref (priv->other_context); - priv->other_context = NULL; - - if (priv->gdk_context) - g_object_unref (priv->gdk_context); - - priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (gst_widget)); - if (priv->gdk_context == NULL) { - GError *error = gtk_gl_area_get_error (GTK_GL_AREA (gst_widget)); - - GST_ERROR_OBJECT (gst_widget, "Error creating GdkGLContext : %s", - error ? error->message : "No error set by Gdk"); - g_clear_error (&error); - return; - } - - g_object_ref (priv->gdk_context); - - gdk_gl_context_make_current (priv->gdk_context); - -#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) - if (GST_IS_GL_DISPLAY_X11 (priv->display)) { -#if GST_GL_HAVE_PLATFORM_GLX - if (!gl_handle) { - platform = GST_GL_PLATFORM_GLX; - gl_handle = gst_gl_context_get_current_gl_context (platform); - } -#endif - -#if GST_GL_HAVE_PLATFORM_EGL - if (!gl_handle) { - platform = GST_GL_PLATFORM_EGL; - gl_handle = gst_gl_context_get_current_gl_context (platform); - } -#endif - - if (gl_handle) { - gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL); - priv->other_context = - gst_gl_context_new_wrapped (priv->display, gl_handle, - platform, gl_api); - } - } -#endif -#if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (GDK_WINDOWING_WAYLAND) - if (GST_IS_GL_DISPLAY_WAYLAND (priv->display)) { - platform = GST_GL_PLATFORM_EGL; - gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL); - gl_handle = gst_gl_context_get_current_gl_context (platform); - if (gl_handle) - priv->other_context = - gst_gl_context_new_wrapped (priv->display, gl_handle, - platform, gl_api); - } -#endif - - (void) platform; - (void) gl_api; - (void) gl_handle; - - if (priv->other_context) { - GError *error = NULL; - - GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT, - priv->other_context); - gst_gl_context_activate (priv->other_context, TRUE); - if (!gst_gl_context_fill_info (priv->other_context, &error)) { - GST_ERROR ("failed to retrieve gdk context info: %s", error->message); - g_clear_error (&error); - g_object_unref (priv->other_context); - priv->other_context = NULL; - } else { - gst_gl_context_activate (priv->other_context, FALSE); - } - } else { - GST_WARNING ("Could not retrieve Gdk OpenGL context"); - } -} - -GtkWidget * -gtk_gst_gl_widget_new (void) -{ - return (GtkWidget *) g_object_new (GTK_TYPE_GST_GL_WIDGET, NULL); -} - -gboolean -gtk_gst_gl_widget_init_winsys (GtkGstGLWidget * gst_widget) -{ - GtkGstGLWidgetPrivate *priv = gst_widget->priv; - GError *error = NULL; - - g_return_val_if_fail (GTK_IS_GST_GL_WIDGET (gst_widget), FALSE); - g_return_val_if_fail (priv->display != NULL, FALSE); - - GTK_GST_BASE_WIDGET_LOCK (gst_widget); - - if (priv->display && priv->gdk_context && priv->other_context) { - GST_TRACE ("have already initialized contexts"); - GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); - return TRUE; - } - - if (!priv->other_context) { - GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); - gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _get_gl_context, gst_widget); - GTK_GST_BASE_WIDGET_LOCK (gst_widget); - } - - if (!GST_IS_GL_CONTEXT (priv->other_context)) { - GST_FIXME ("Could not retrieve Gdk OpenGL context"); - GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); - return FALSE; - } - - GST_OBJECT_LOCK (priv->display); - if (!gst_gl_display_create_context (priv->display, priv->other_context, - &priv->context, &error)) { - GST_WARNING ("Could not create OpenGL context: %s", - error ? error->message : "Unknown"); - g_clear_error (&error); - GST_OBJECT_UNLOCK (priv->display); - GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); - return FALSE; - } - gst_gl_display_add_context (priv->display, priv->context); - GST_OBJECT_UNLOCK (priv->display); - - GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); - return TRUE; -} - -GstGLContext * -gtk_gst_gl_widget_get_gtk_context (GtkGstGLWidget * gst_widget) -{ - if (!gst_widget->priv->other_context) - return NULL; - - return gst_object_ref (gst_widget->priv->other_context); -} - -GstGLContext * -gtk_gst_gl_widget_get_context (GtkGstGLWidget * gst_widget) -{ - if (!gst_widget->priv->context) - return NULL; - - return gst_object_ref (gst_widget->priv->context); -} - -GstGLDisplay * -gtk_gst_gl_widget_get_display (GtkGstGLWidget * gst_widget) -{ - if (!gst_widget->priv->display) - return NULL; - - return gst_object_ref (gst_widget->priv->display); -} diff --git a/lib/gst/clapper/gtk4/gtkgstglwidget.h b/lib/gst/clapper/gtk4/gtkgstglwidget.h deleted file mode 100644 index 7f055c48..00000000 --- a/lib/gst/clapper/gtk4/gtkgstglwidget.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters - * - * 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_GST_GL_WIDGET_H__ -#define __GTK_GST_GL_WIDGET_H__ - -#include -#include -#include - -#include "gtkgstbasewidget.h" - -G_BEGIN_DECLS - -GType gtk_gst_gl_widget_get_type (void); -#define GTK_TYPE_GST_GL_WIDGET (gtk_gst_gl_widget_get_type()) -#define GTK_GST_GL_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GTK_TYPE_GST_GL_WIDGET,GtkGstGLWidget)) -#define GTK_GST_GL_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GTK_TYPE_GST_GL_WIDGET,GtkGstGLWidgetClass)) -#define GTK_IS_GST_GL_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GTK_TYPE_GST_GL_WIDGET)) -#define GTK_IS_GST_GL_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GTK_TYPE_GST_GL_WIDGET)) -#define GTK_GST_GL_WIDGET_CAST(obj) ((GtkGstGLWidget*)(obj)) - -typedef struct _GtkGstGLWidget GtkGstGLWidget; -typedef struct _GtkGstGLWidgetClass GtkGstGLWidgetClass; -typedef struct _GtkGstGLWidgetPrivate GtkGstGLWidgetPrivate; - -/** - * GtkGstGLWidget: - * - * Opaque #GtkGstGLWidget object - */ -struct _GtkGstGLWidget -{ - /* */ - GtkGstBaseWidget base; - - GtkGstGLWidgetPrivate *priv; -}; - -/** - * GtkGstGLWidgetClass: - * - * The #GtkGstGLWidgetClass struct only contains private data - */ -struct _GtkGstGLWidgetClass -{ - /* */ - GtkGstBaseWidgetClass base_class; -}; - -GtkWidget * gtk_gst_gl_widget_new (void); - -gboolean gtk_gst_gl_widget_init_winsys (GtkGstGLWidget * widget); -GstGLDisplay * gtk_gst_gl_widget_get_display (GtkGstGLWidget * widget); -GstGLContext * gtk_gst_gl_widget_get_context (GtkGstGLWidget * widget); -GstGLContext * gtk_gst_gl_widget_get_gtk_context (GtkGstGLWidget * widget); - -G_END_DECLS - -#endif /* __GTK_GST_GL_WIDGET_H__ */ diff --git a/lib/gst/clapper/meson.build b/lib/gst/clapper/meson.build index bbf910fa..4905c102 100644 --- a/lib/gst/clapper/meson.build +++ b/lib/gst/clapper/meson.build @@ -11,7 +11,6 @@ gstclapper_sources = [ 'gtk4/gstgtkbasesink.c', 'gtk4/gstgtkutils.c', 'gtk4/gtkgstbasewidget.c', - 'gtk4/gtkgstglwidget.c', ] gstclapper_headers = [ 'clapper.h', From e3c9b112e2244c660c136407c5b4dc08c41fb275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 5 Mar 2021 23:27:08 +0100 Subject: [PATCH 07/10] Sink: remove gtkconfig header Remove another leftover meant for GTK3 compatibility --- lib/gst/clapper/gtk4/gstgtkbasesink.c | 5 ++--- lib/gst/clapper/gtk4/gtkconfig.h | 24 ------------------------ 2 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 lib/gst/clapper/gtk4/gtkconfig.h diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.c b/lib/gst/clapper/gtk4/gstgtkbasesink.c index 9dd973cd..17bab91a 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.c +++ b/lib/gst/clapper/gtk4/gstgtkbasesink.c @@ -31,7 +31,6 @@ #include -#include "gtkconfig.h" #include "gstgtkbasesink.h" #include "gstgtkutils.h" @@ -154,10 +153,10 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) gstvideosink_class->show_frame = gst_gtk_base_sink_show_frame; gstgtkbasesink_class->create_widget = gtk_gst_base_widget_new; - gstgtkbasesink_class->window_title = GTKCONFIG_NAME " GL Renderer"; + gstgtkbasesink_class->window_title = "GTK4 GL Renderer"; gst_element_class_set_metadata (gstelement_class, - GTKCONFIG_NAME " GL Video Sink", + "GTK4 GL Video Sink", "Sink/Video", "A video sink that renders to a GtkWidget using OpenGL", "Matthew Waters , " "Rafał Dzięgiel "); diff --git a/lib/gst/clapper/gtk4/gtkconfig.h b/lib/gst/clapper/gtk4/gtkconfig.h deleted file mode 100644 index 76ee9d11..00000000 --- a/lib/gst/clapper/gtk4/gtkconfig.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2020 Rafał Dzięgiel - * - * 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. - */ - -#define GTKCONFIG_PLUGIN gtk4 -#define GTKCONFIG_NAME "GTK4" -#define GTKCONFIG_SINK "gtk4sink" -#define GTKCONFIG_GLSINK "gtk4glsink" From 9c12afbf809ab075dc70e5b8865dd4a42aa31de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Sat, 6 Mar 2021 00:24:31 +0100 Subject: [PATCH 08/10] Sink: rename into GstClapperGLSink The customized GTK4 sink version has few differences from the one shipped as part of GStreamer. Rename custom sink to GstClapperGLSink to avoid confusion. --- lib/gst/clapper/gstclapper-gtk4-plugin.c | 4 +- .../{gstgtkbasesink.c => gstclapperglsink.c} | 398 ++++++++------- lib/gst/clapper/gtk4/gstclapperglsink.h | 106 ++++ lib/gst/clapper/gtk4/gstgtkbasesink.h | 107 ---- ...tkgstbasewidget.c => gtkclapperglwidget.c} | 457 +++++++++--------- lib/gst/clapper/gtk4/gtkclapperglwidget.h | 107 ++++ lib/gst/clapper/gtk4/gtkgstbasewidget.h | 107 ---- lib/gst/clapper/meson.build | 4 +- 8 files changed, 642 insertions(+), 648 deletions(-) rename lib/gst/clapper/gtk4/{gstgtkbasesink.c => gstclapperglsink.c} (53%) create mode 100644 lib/gst/clapper/gtk4/gstclapperglsink.h delete mode 100644 lib/gst/clapper/gtk4/gstgtkbasesink.h rename lib/gst/clapper/gtk4/{gtkgstbasewidget.c => gtkclapperglwidget.c} (59%) create mode 100644 lib/gst/clapper/gtk4/gtkclapperglwidget.h delete mode 100644 lib/gst/clapper/gtk4/gtkgstbasewidget.h diff --git a/lib/gst/clapper/gstclapper-gtk4-plugin.c b/lib/gst/clapper/gstclapper-gtk4-plugin.c index 43e60873..8fc50c3b 100644 --- a/lib/gst/clapper/gstclapper-gtk4-plugin.c +++ b/lib/gst/clapper/gstclapper-gtk4-plugin.c @@ -30,7 +30,7 @@ #endif #include "gstclapper-gtk4-plugin.h" -#include "gtk4/gstgtkbasesink.h" +#include "gtk4/gstclapperglsink.h" enum { @@ -78,7 +78,7 @@ gst_clapper_gtk4_plugin_constructed (GObject * object) GstClapperGtk4Plugin *self = GST_CLAPPER_GTK4_PLUGIN (object); if (!self->video_sink) - self->video_sink = g_object_new (GST_TYPE_GTK_BASE_SINK, NULL); + self->video_sink = g_object_new (GST_TYPE_CLAPPER_GL_SINK, NULL); gst_object_ref_sink (self->video_sink); diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.c b/lib/gst/clapper/gtk4/gstclapperglsink.c similarity index 53% rename from lib/gst/clapper/gtk4/gstgtkbasesink.c rename to lib/gst/clapper/gtk4/gstclapperglsink.c index 17bab91a..a97dcdc9 100644 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.c +++ b/lib/gst/clapper/gtk4/gstclapperglsink.c @@ -20,8 +20,8 @@ */ /** - * SECTION:gtkgstsink - * @title: GstGtkBaseSink + * SECTION:gstclapperglsink + * @title: GstClapperGLSink * */ @@ -31,18 +31,18 @@ #include -#include "gstgtkbasesink.h" +#include "gstclapperglsink.h" #include "gstgtkutils.h" -GST_DEBUG_CATEGORY (gst_debug_gtk_base_sink); -#define GST_CAT_DEFAULT gst_debug_gtk_base_sink +GST_DEBUG_CATEGORY (gst_debug_clapper_gl_sink); +#define GST_CAT_DEFAULT gst_debug_clapper_gl_sink #define DEFAULT_FORCE_ASPECT_RATIO TRUE #define DEFAULT_PAR_N 0 #define DEFAULT_PAR_D 1 #define DEFAULT_IGNORE_TEXTURES FALSE -static GstStaticPadTemplate gst_gtk_base_sink_template = +static GstStaticPadTemplate gst_clapper_gl_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -52,33 +52,33 @@ static GstStaticPadTemplate gst_gtk_base_sink_template = (GST_CAPS_FEATURE_MEMORY_GL_MEMORY ", " GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, "RGBA"))); -static void gst_gtk_base_sink_finalize (GObject * object); -static void gst_gtk_base_sink_set_property (GObject * object, guint prop_id, +static void gst_clapper_gl_sink_finalize (GObject * object); +static void gst_clapper_gl_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * param_spec); -static void gst_gtk_base_sink_get_property (GObject * object, guint prop_id, +static void gst_clapper_gl_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * param_spec); -static gboolean gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, +static gboolean gst_clapper_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query); -static gboolean gst_gtk_base_sink_query (GstBaseSink * bsink, GstQuery * query); -static gboolean gst_gtk_base_sink_start (GstBaseSink * bsink); -static gboolean gst_gtk_base_sink_stop (GstBaseSink * bsink); +static gboolean gst_clapper_gl_sink_query (GstBaseSink * bsink, GstQuery * query); +static gboolean gst_clapper_gl_sink_start (GstBaseSink * bsink); +static gboolean gst_clapper_gl_sink_stop (GstBaseSink * bsink); static GstStateChangeReturn -gst_gtk_base_sink_change_state (GstElement * element, +gst_clapper_gl_sink_change_state (GstElement * element, GstStateChange transition); -static void gst_gtk_base_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, +static void gst_clapper_gl_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, GstClockTime * start, GstClockTime * end); -static GstCaps *gst_gtk_base_sink_get_caps (GstBaseSink * bsink, +static GstCaps *gst_clapper_gl_sink_get_caps (GstBaseSink * bsink, GstCaps * filter); -static gboolean gst_gtk_base_sink_set_caps (GstBaseSink * bsink, +static gboolean gst_clapper_gl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps); -static GstFlowReturn gst_gtk_base_sink_show_frame (GstVideoSink * bsink, +static GstFlowReturn gst_clapper_gl_sink_show_frame (GstVideoSink * bsink, GstBuffer * buf); static void -gst_gtk_base_sink_navigation_interface_init (GstNavigationInterface * iface); +gst_clapper_gl_sink_navigation_interface_init (GstNavigationInterface * iface); enum { @@ -89,31 +89,31 @@ enum PROP_IGNORE_TEXTURES, }; -#define gst_gtk_base_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGtkBaseSink, gst_gtk_base_sink, +#define gst_clapper_gl_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstClapperGLSink, gst_clapper_gl_sink, GST_TYPE_VIDEO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, - gst_gtk_base_sink_navigation_interface_init); - GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_sink, - "gtkbasesink", 0, "GTK Video Sink base class")); + gst_clapper_gl_sink_navigation_interface_init); + GST_DEBUG_CATEGORY_INIT (gst_debug_clapper_gl_sink, + "clapperglsink", 0, "Clapper GL Sink")); static void -gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) +gst_clapper_gl_sink_class_init (GstClapperGLSinkClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; GstBaseSinkClass *gstbasesink_class; GstVideoSinkClass *gstvideosink_class; - GstGtkBaseSinkClass *gstgtkbasesink_class; + GstClapperGLSinkClass *gstclapperglsink_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; gstbasesink_class = (GstBaseSinkClass *) klass; gstvideosink_class = (GstVideoSinkClass *) klass; - gstgtkbasesink_class = (GstGtkBaseSinkClass *) klass; + gstclapperglsink_class = (GstClapperGLSinkClass *) klass; - gobject_class->set_property = gst_gtk_base_sink_set_property; - gobject_class->get_property = gst_gtk_base_sink_get_property; + gobject_class->set_property = gst_clapper_gl_sink_set_property; + gobject_class->get_property = gst_clapper_gl_sink_get_property; g_object_class_install_property (gobject_class, PROP_WIDGET, g_param_spec_object ("widget", "GTK Widget", @@ -138,22 +138,22 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) "When enabled, textures will be ignored and not drawn", DEFAULT_IGNORE_TEXTURES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gobject_class->finalize = gst_gtk_base_sink_finalize; + gobject_class->finalize = gst_clapper_gl_sink_finalize; - gstelement_class->change_state = gst_gtk_base_sink_change_state; + gstelement_class->change_state = gst_clapper_gl_sink_change_state; - gstbasesink_class->get_caps = gst_gtk_base_sink_get_caps; - gstbasesink_class->set_caps = gst_gtk_base_sink_set_caps; - gstbasesink_class->get_times = gst_gtk_base_sink_get_times; - gstbasesink_class->propose_allocation = gst_gtk_base_sink_propose_allocation; - gstbasesink_class->query = gst_gtk_base_sink_query; - gstbasesink_class->start = gst_gtk_base_sink_start; - gstbasesink_class->stop = gst_gtk_base_sink_stop; + gstbasesink_class->get_caps = gst_clapper_gl_sink_get_caps; + gstbasesink_class->set_caps = gst_clapper_gl_sink_set_caps; + gstbasesink_class->get_times = gst_clapper_gl_sink_get_times; + gstbasesink_class->propose_allocation = gst_clapper_gl_sink_propose_allocation; + gstbasesink_class->query = gst_clapper_gl_sink_query; + gstbasesink_class->start = gst_clapper_gl_sink_start; + gstbasesink_class->stop = gst_clapper_gl_sink_stop; - gstvideosink_class->show_frame = gst_gtk_base_sink_show_frame; + gstvideosink_class->show_frame = gst_clapper_gl_sink_show_frame; - gstgtkbasesink_class->create_widget = gtk_gst_base_widget_new; - gstgtkbasesink_class->window_title = "GTK4 GL Renderer"; + gstclapperglsink_class->create_widget = gtk_clapper_gl_widget_new; + gstclapperglsink_class->window_title = "GTK4 GL Renderer"; gst_element_class_set_metadata (gstelement_class, "GTK4 GL Video Sink", @@ -162,136 +162,136 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass) "Rafał Dzięgiel "); gst_element_class_add_static_pad_template (gstelement_class, - &gst_gtk_base_sink_template); + &gst_clapper_gl_sink_template); - gst_type_mark_as_plugin_api (GST_TYPE_GTK_BASE_SINK, 0); + gst_type_mark_as_plugin_api (GST_TYPE_CLAPPER_GL_SINK, 0); } static void -gst_gtk_base_sink_init (GstGtkBaseSink * gtk_sink) +gst_clapper_gl_sink_init (GstClapperGLSink * clapper_sink) { - gtk_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; - gtk_sink->par_n = DEFAULT_PAR_N; - gtk_sink->par_d = DEFAULT_PAR_D; - gtk_sink->ignore_textures = DEFAULT_IGNORE_TEXTURES; + clapper_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; + clapper_sink->par_n = DEFAULT_PAR_N; + clapper_sink->par_d = DEFAULT_PAR_D; + clapper_sink->ignore_textures = DEFAULT_IGNORE_TEXTURES; } static void -gst_gtk_base_sink_finalize (GObject * object) +gst_clapper_gl_sink_finalize (GObject * object) { - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (object); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (object); - GST_DEBUG ("finalizing base sink"); + GST_DEBUG ("Finalizing Clapper GL sink"); - GST_OBJECT_LOCK (base_sink); - if (base_sink->window && base_sink->window_destroy_id) - g_signal_handler_disconnect (base_sink->window, base_sink->window_destroy_id); - if (base_sink->widget && base_sink->widget_destroy_id) - g_signal_handler_disconnect (base_sink->widget, base_sink->widget_destroy_id); + GST_OBJECT_LOCK (clapper_sink); + if (clapper_sink->window && clapper_sink->window_destroy_id) + g_signal_handler_disconnect (clapper_sink->window, clapper_sink->window_destroy_id); + if (clapper_sink->widget && clapper_sink->widget_destroy_id) + g_signal_handler_disconnect (clapper_sink->widget, clapper_sink->widget_destroy_id); - g_clear_object (&base_sink->widget); - GST_OBJECT_UNLOCK (base_sink); + g_clear_object (&clapper_sink->widget); + GST_OBJECT_UNLOCK (clapper_sink); G_OBJECT_CLASS (parent_class)->finalize (object); } static void -widget_destroy_cb (GtkWidget * widget, GstGtkBaseSink * gtk_sink) +widget_destroy_cb (GtkWidget * widget, GstClapperGLSink * clapper_sink) { - GST_OBJECT_LOCK (gtk_sink); - g_clear_object (>k_sink->widget); - GST_OBJECT_UNLOCK (gtk_sink); + GST_OBJECT_LOCK (clapper_sink); + g_clear_object (&clapper_sink->widget); + GST_OBJECT_UNLOCK (clapper_sink); } static void -window_destroy_cb (GtkWidget * widget, GstGtkBaseSink * gtk_sink) +window_destroy_cb (GtkWidget * widget, GstClapperGLSink * clapper_sink) { - GST_OBJECT_LOCK (gtk_sink); - if (gtk_sink->widget) { - if (gtk_sink->widget_destroy_id) { - g_signal_handler_disconnect (gtk_sink->widget, - gtk_sink->widget_destroy_id); - gtk_sink->widget_destroy_id = 0; + GST_OBJECT_LOCK (clapper_sink); + if (clapper_sink->widget) { + if (clapper_sink->widget_destroy_id) { + g_signal_handler_disconnect (clapper_sink->widget, + clapper_sink->widget_destroy_id); + clapper_sink->widget_destroy_id = 0; } - g_clear_object (>k_sink->widget); + g_clear_object (&clapper_sink->widget); } - gtk_sink->window = NULL; - GST_OBJECT_UNLOCK (gtk_sink); + clapper_sink->window = NULL; + GST_OBJECT_UNLOCK (clapper_sink); } -static GtkGstBaseWidget * -gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink) +static GtkClapperGLWidget * +gst_clapper_gl_sink_get_widget (GstClapperGLSink * clapper_sink) { - if (gtk_sink->widget != NULL) - return gtk_sink->widget; + if (clapper_sink->widget != NULL) + return clapper_sink->widget; /* Ensure GTK is initialized, this has no side effect if it was already * initialized. Also, we do that lazily, so the application can be first */ if (!gtk_init_check ()) { - GST_ERROR_OBJECT (gtk_sink, "Could not ensure GTK initialization."); + GST_ERROR_OBJECT (clapper_sink, "Could not ensure GTK initialization."); return NULL; } - g_assert (GST_GTK_BASE_SINK_GET_CLASS (gtk_sink)->create_widget); - gtk_sink->widget = (GtkGstBaseWidget *) - GST_GTK_BASE_SINK_GET_CLASS (gtk_sink)->create_widget (); + g_assert (GST_CLAPPER_GL_SINK_GET_CLASS (clapper_sink)->create_widget); + clapper_sink->widget = (GtkClapperGLWidget *) + GST_CLAPPER_GL_SINK_GET_CLASS (clapper_sink)->create_widget (); - gtk_sink->bind_aspect_ratio = - g_object_bind_property (gtk_sink, "force-aspect-ratio", gtk_sink->widget, + clapper_sink->bind_aspect_ratio = + g_object_bind_property (clapper_sink, "force-aspect-ratio", clapper_sink->widget, "force-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - gtk_sink->bind_pixel_aspect_ratio = - g_object_bind_property (gtk_sink, "pixel-aspect-ratio", gtk_sink->widget, + clapper_sink->bind_pixel_aspect_ratio = + g_object_bind_property (clapper_sink, "pixel-aspect-ratio", clapper_sink->widget, "pixel-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - gtk_sink->bind_ignore_textures = - g_object_bind_property (gtk_sink, "ignore-textures", gtk_sink->widget, + clapper_sink->bind_ignore_textures = + g_object_bind_property (clapper_sink, "ignore-textures", clapper_sink->widget, "ignore-textures", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); /* Take the floating ref, other wise the destruction of the container will * make this widget disappear possibly before we are done. */ - gst_object_ref_sink (gtk_sink->widget); + gst_object_ref_sink (clapper_sink->widget); - gtk_sink->widget_destroy_id = g_signal_connect (gtk_sink->widget, "destroy", - G_CALLBACK (widget_destroy_cb), gtk_sink); + clapper_sink->widget_destroy_id = g_signal_connect (clapper_sink->widget, "destroy", + G_CALLBACK (widget_destroy_cb), clapper_sink); /* back pointer */ - gtk_gst_base_widget_set_element (GTK_GST_BASE_WIDGET (gtk_sink->widget), - GST_ELEMENT (gtk_sink)); + gtk_clapper_gl_widget_set_element (GTK_CLAPPER_GL_WIDGET (clapper_sink->widget), + GST_ELEMENT (clapper_sink)); - return gtk_sink->widget; + return clapper_sink->widget; } static void -gst_gtk_base_sink_get_property (GObject * object, guint prop_id, +gst_clapper_gl_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstGtkBaseSink *gtk_sink = GST_GTK_BASE_SINK (object); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (object); switch (prop_id) { case PROP_WIDGET: { GObject *widget = NULL; - GST_OBJECT_LOCK (gtk_sink); - if (gtk_sink->widget != NULL) - widget = G_OBJECT (gtk_sink->widget); - GST_OBJECT_UNLOCK (gtk_sink); + GST_OBJECT_LOCK (clapper_sink); + if (clapper_sink->widget != NULL) + widget = G_OBJECT (clapper_sink->widget); + GST_OBJECT_UNLOCK (clapper_sink); if (!widget) widget = - gst_gtk_invoke_on_main ((GThreadFunc) gst_gtk_base_sink_get_widget, - gtk_sink); + gst_gtk_invoke_on_main ((GThreadFunc) gst_clapper_gl_sink_get_widget, + clapper_sink); g_value_set_object (value, widget); break; } case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean (value, gtk_sink->force_aspect_ratio); + g_value_set_boolean (value, clapper_sink->force_aspect_ratio); break; case PROP_PIXEL_ASPECT_RATIO: - gst_value_set_fraction (value, gtk_sink->par_n, gtk_sink->par_d); + gst_value_set_fraction (value, clapper_sink->par_n, clapper_sink->par_d); break; case PROP_IGNORE_TEXTURES: - g_value_set_boolean (value, gtk_sink->ignore_textures); + g_value_set_boolean (value, clapper_sink->ignore_textures); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -300,21 +300,21 @@ gst_gtk_base_sink_get_property (GObject * object, guint prop_id, } static void -gst_gtk_base_sink_set_property (GObject * object, guint prop_id, +gst_clapper_gl_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstGtkBaseSink *gtk_sink = GST_GTK_BASE_SINK (object); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (object); switch (prop_id) { case PROP_FORCE_ASPECT_RATIO: - gtk_sink->force_aspect_ratio = g_value_get_boolean (value); + clapper_sink->force_aspect_ratio = g_value_get_boolean (value); break; case PROP_PIXEL_ASPECT_RATIO: - gtk_sink->par_n = gst_value_get_fraction_numerator (value); - gtk_sink->par_d = gst_value_get_fraction_denominator (value); + clapper_sink->par_n = gst_value_get_fraction_numerator (value); + clapper_sink->par_d = gst_value_get_fraction_denominator (value); break; case PROP_IGNORE_TEXTURES: - gtk_sink->ignore_textures = g_value_get_boolean (value); + clapper_sink->ignore_textures = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -323,10 +323,10 @@ gst_gtk_base_sink_set_property (GObject * object, guint prop_id, } static void -gst_gtk_base_sink_navigation_send_event (GstNavigation * navigation, +gst_clapper_gl_sink_navigation_send_event (GstNavigation * navigation, GstStructure * structure) { - GstGtkBaseSink *sink = GST_GTK_BASE_SINK (navigation); + GstClapperGLSink *sink = GST_CLAPPER_GL_SINK (navigation); GstEvent *event; GstPad *pad; @@ -348,15 +348,15 @@ gst_gtk_base_sink_navigation_send_event (GstNavigation * navigation, } static void -gst_gtk_base_sink_navigation_interface_init (GstNavigationInterface * iface) +gst_clapper_gl_sink_navigation_interface_init (GstNavigationInterface * iface) { - iface->send_event = gst_gtk_base_sink_navigation_send_event; + iface->send_event = gst_clapper_gl_sink_navigation_send_event; } static gboolean -gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) +gst_clapper_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink); GstBufferPool *pool = NULL; GstStructure *config; GstCaps *caps; @@ -366,7 +366,7 @@ gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) GstStructure *allocation_meta = NULL; gint display_width, display_height; - if (!base_sink->display || !base_sink->context) + if (!clapper_sink->display || !clapper_sink->context) return FALSE; gst_query_parse_allocation (query, &caps, &need_pool); @@ -381,8 +381,8 @@ gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) size = info.size; if (need_pool) { - GST_DEBUG_OBJECT (base_sink, "create new pool"); - pool = gst_gl_buffer_pool_new (base_sink->context); + GST_DEBUG_OBJECT (clapper_sink, "create new pool"); + pool = gst_gl_buffer_pool_new (clapper_sink->context); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, 0, 0); @@ -398,13 +398,13 @@ gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) if (pool) gst_object_unref (pool); - GST_OBJECT_LOCK (base_sink); - display_width = base_sink->display_width; - display_height = base_sink->display_height; - GST_OBJECT_UNLOCK (base_sink); + GST_OBJECT_LOCK (clapper_sink); + display_width = clapper_sink->display_width; + display_height = clapper_sink->display_height; + GST_OBJECT_UNLOCK (clapper_sink); if (display_width != 0 && display_height != 0) { - GST_DEBUG_OBJECT (base_sink, "sending alloc query with size %dx%d", + GST_DEBUG_OBJECT (clapper_sink, "sending alloc query with size %dx%d", display_width, display_height); allocation_meta = gst_structure_new ("GstVideoOverlayCompositionMeta", "width", G_TYPE_UINT, display_width, @@ -420,7 +420,7 @@ gst_gtk_base_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); - if (base_sink->context->gl_vtable->FenceSync) + if (clapper_sink->context->gl_vtable->FenceSync) gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0); return TRUE; @@ -444,16 +444,16 @@ config_failed: } static gboolean -gst_gtk_base_sink_query (GstBaseSink * bsink, GstQuery * query) +gst_clapper_gl_sink_query (GstBaseSink * bsink, GstQuery * query) { - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink); gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONTEXT: { - if (gst_gl_handle_context_query ((GstElement *) base_sink, query, - base_sink->display, base_sink->context, base_sink->gtk_context)) + if (gst_gl_handle_context_query ((GstElement *) clapper_sink, query, + clapper_sink->display, clapper_sink->context, clapper_sink->gtk_context)) return TRUE; break; } @@ -466,17 +466,17 @@ gst_gtk_base_sink_query (GstBaseSink * bsink, GstQuery * query) } static gboolean -gst_gtk_base_sink_start_on_main (GstBaseSink * bsink) +gst_clapper_gl_sink_start_on_main (GstBaseSink * bsink) { - GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink); - GstGtkBaseSinkClass *klass = GST_GTK_BASE_SINK_GET_CLASS (bsink); + GstClapperGLSink *gst_sink = GST_CLAPPER_GL_SINK (bsink); + GstClapperGLSinkClass *klass = GST_CLAPPER_GL_SINK_GET_CLASS (bsink); GtkWidget *toplevel; GtkRoot *root; - if (gst_gtk_base_sink_get_widget (gst_sink) == NULL) + if (gst_clapper_gl_sink_get_widget (gst_sink) == NULL) return FALSE; - /* After this point, base_sink->widget will always be set */ + /* After this point, clapper_sink->widget will always be set */ root = gtk_widget_get_root (GTK_WIDGET (gst_sink->widget)); if (!GTK_IS_ROOT (root)) { @@ -507,47 +507,47 @@ gst_gtk_base_sink_start_on_main (GstBaseSink * bsink) } static gboolean -gst_gtk_base_sink_start (GstBaseSink * bsink) +gst_clapper_gl_sink_start (GstBaseSink * bsink) { - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); - GtkGstBaseWidget *base_widget; + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink); + GtkClapperGLWidget *clapper_widget; if (!(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) - gst_gtk_base_sink_start_on_main, bsink))) + gst_clapper_gl_sink_start_on_main, bsink))) return FALSE; - /* After this point, base_sink->widget will always be set */ - base_widget = GTK_GST_BASE_WIDGET (base_sink->widget); + /* After this point, clapper_sink->widget will always be set */ + clapper_widget = GTK_CLAPPER_GL_WIDGET (clapper_sink->widget); - if (!gtk_gst_base_widget_init_winsys (base_widget)) { + if (!gtk_clapper_gl_widget_init_winsys (clapper_widget)) { GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", "Failed to initialize OpenGL with GTK"), (NULL)); return FALSE; } - if (!base_sink->display) - base_sink->display = gtk_gst_base_widget_get_display (base_widget); - if (!base_sink->context) - base_sink->context = gtk_gst_base_widget_get_context (base_widget); - if (!base_sink->gtk_context) - base_sink->gtk_context = gtk_gst_base_widget_get_gtk_context (base_widget); + if (!clapper_sink->display) + clapper_sink->display = gtk_clapper_gl_widget_get_display (clapper_widget); + if (!clapper_sink->context) + clapper_sink->context = gtk_clapper_gl_widget_get_context (clapper_widget); + if (!clapper_sink->gtk_context) + clapper_sink->gtk_context = gtk_clapper_gl_widget_get_gtk_context (clapper_widget); - if (!base_sink->display || !base_sink->context || !base_sink->gtk_context) { + if (!clapper_sink->display || !clapper_sink->context || !clapper_sink->gtk_context) { GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s", "Failed to retrieve OpenGL context from GTK"), (NULL)); return FALSE; } gst_gl_element_propagate_display_context (GST_ELEMENT (bsink), - base_sink->display); + clapper_sink->display); return TRUE; } static gboolean -gst_gtk_base_sink_stop_on_main (GstBaseSink * bsink) +gst_clapper_gl_sink_stop_on_main (GstBaseSink * bsink) { - GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink); + GstClapperGLSink *gst_sink = GST_CLAPPER_GL_SINK (bsink); if (gst_sink->window) { gtk_window_destroy (GTK_WINDOW (gst_sink->window)); @@ -559,25 +559,25 @@ gst_gtk_base_sink_stop_on_main (GstBaseSink * bsink) } static gboolean -gst_gtk_base_sink_stop (GstBaseSink * bsink) +gst_clapper_gl_sink_stop (GstBaseSink * bsink) { - GstGtkBaseSink *base_sink = GST_GTK_BASE_SINK (bsink); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink); - if (base_sink->display) { - gst_object_unref (base_sink->display); - base_sink->display = NULL; + if (clapper_sink->display) { + gst_object_unref (clapper_sink->display); + clapper_sink->display = NULL; } - if (base_sink->context) { - gst_object_unref (base_sink->context); - base_sink->context = NULL; + if (clapper_sink->context) { + gst_object_unref (clapper_sink->context); + clapper_sink->context = NULL; } - if (base_sink->gtk_context) { - gst_object_unref (base_sink->gtk_context); - base_sink->gtk_context = NULL; + if (clapper_sink->gtk_context) { + gst_object_unref (clapper_sink->gtk_context); + clapper_sink->gtk_context = NULL; } - if (base_sink->window) + if (clapper_sink->window) return ! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) - gst_gtk_base_sink_stop_on_main, bsink); + gst_clapper_gl_sink_stop_on_main, bsink); return TRUE; } @@ -590,9 +590,9 @@ gst_gtk_window_show_all_and_unref (GtkWidget * window) } static GstStateChangeReturn -gst_gtk_base_sink_change_state (GstElement * element, GstStateChange transition) +gst_clapper_gl_sink_change_state (GstElement * element, GstStateChange transition) { - GstGtkBaseSink *gtk_sink = GST_GTK_BASE_SINK (element); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (element); GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GST_DEBUG_OBJECT (element, "changing state: %s => %s", @@ -608,10 +608,10 @@ gst_gtk_base_sink_change_state (GstElement * element, GstStateChange transition) { GtkWindow *window = NULL; - GST_OBJECT_LOCK (gtk_sink); - if (gtk_sink->window) - window = g_object_ref (GTK_WINDOW (gtk_sink->window)); - GST_OBJECT_UNLOCK (gtk_sink); + GST_OBJECT_LOCK (clapper_sink); + if (clapper_sink->window) + window = g_object_ref (GTK_WINDOW (clapper_sink->window)); + GST_OBJECT_UNLOCK (clapper_sink); if (window) { gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) @@ -620,10 +620,10 @@ gst_gtk_base_sink_change_state (GstElement * element, GstStateChange transition) break; } case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_OBJECT_LOCK (gtk_sink); - if (gtk_sink->widget) - gtk_gst_base_widget_set_buffer (gtk_sink->widget, NULL); - GST_OBJECT_UNLOCK (gtk_sink); + GST_OBJECT_LOCK (clapper_sink); + if (clapper_sink->widget) + gtk_clapper_gl_widget_set_buffer (clapper_sink->widget, NULL); + GST_OBJECT_UNLOCK (clapper_sink); break; default: break; @@ -633,30 +633,28 @@ gst_gtk_base_sink_change_state (GstElement * element, GstStateChange transition) } static void -gst_gtk_base_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, +gst_clapper_gl_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, GstClockTime * start, GstClockTime * end) { - GstGtkBaseSink *gtk_sink; - - gtk_sink = GST_GTK_BASE_SINK (bsink); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink); if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { *start = GST_BUFFER_TIMESTAMP (buf); if (GST_BUFFER_DURATION_IS_VALID (buf)) *end = *start + GST_BUFFER_DURATION (buf); else { - if (GST_VIDEO_INFO_FPS_N (>k_sink->v_info) > 0) { + if (GST_VIDEO_INFO_FPS_N (&clapper_sink->v_info) > 0) { *end = *start + gst_util_uint64_scale_int (GST_SECOND, - GST_VIDEO_INFO_FPS_D (>k_sink->v_info), - GST_VIDEO_INFO_FPS_N (>k_sink->v_info)); + GST_VIDEO_INFO_FPS_D (&clapper_sink->v_info), + GST_VIDEO_INFO_FPS_N (&clapper_sink->v_info)); } } } } static GstCaps * -gst_gtk_base_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) +gst_clapper_gl_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) { GstCaps *tmp = NULL; GstCaps *result = NULL; @@ -681,54 +679,54 @@ gst_gtk_base_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) } static gboolean -gst_gtk_base_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) +gst_clapper_gl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { - GstGtkBaseSink *gtk_sink = GST_GTK_BASE_SINK (bsink); + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink); GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); - if (!gst_video_info_from_caps (>k_sink->v_info, caps)) + if (!gst_video_info_from_caps (&clapper_sink->v_info, caps)) return FALSE; - GST_OBJECT_LOCK (gtk_sink); + GST_OBJECT_LOCK (clapper_sink); - if (gtk_sink->widget == NULL) { - GST_OBJECT_UNLOCK (gtk_sink); - GST_ELEMENT_ERROR (gtk_sink, RESOURCE, NOT_FOUND, + if (clapper_sink->widget == NULL) { + GST_OBJECT_UNLOCK (clapper_sink); + GST_ELEMENT_ERROR (clapper_sink, RESOURCE, NOT_FOUND, ("%s", "Output widget was destroyed"), (NULL)); return FALSE; } - if (!gtk_gst_base_widget_set_format (gtk_sink->widget, >k_sink->v_info)) { - GST_OBJECT_UNLOCK (gtk_sink); + if (!gtk_clapper_gl_widget_set_format (clapper_sink->widget, &clapper_sink->v_info)) { + GST_OBJECT_UNLOCK (clapper_sink); return FALSE; } - GST_OBJECT_UNLOCK (gtk_sink); + GST_OBJECT_UNLOCK (clapper_sink); return TRUE; } static GstFlowReturn -gst_gtk_base_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) +gst_clapper_gl_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) { - GstGtkBaseSink *gtk_sink; + GstClapperGLSink *clapper_sink; GST_TRACE ("rendering buffer:%p", buf); - gtk_sink = GST_GTK_BASE_SINK (vsink); + clapper_sink = GST_CLAPPER_GL_SINK (vsink); - GST_OBJECT_LOCK (gtk_sink); + GST_OBJECT_LOCK (clapper_sink); - if (gtk_sink->widget == NULL) { - GST_OBJECT_UNLOCK (gtk_sink); - GST_ELEMENT_ERROR (gtk_sink, RESOURCE, NOT_FOUND, + if (clapper_sink->widget == NULL) { + GST_OBJECT_UNLOCK (clapper_sink); + GST_ELEMENT_ERROR (clapper_sink, RESOURCE, NOT_FOUND, ("%s", "Output widget was destroyed"), (NULL)); return GST_FLOW_ERROR; } - gtk_gst_base_widget_set_buffer (gtk_sink->widget, buf); + gtk_clapper_gl_widget_set_buffer (clapper_sink->widget, buf); - GST_OBJECT_UNLOCK (gtk_sink); + GST_OBJECT_UNLOCK (clapper_sink); return GST_FLOW_OK; } diff --git a/lib/gst/clapper/gtk4/gstclapperglsink.h b/lib/gst/clapper/gtk4/gstclapperglsink.h new file mode 100644 index 00000000..32796dbc --- /dev/null +++ b/lib/gst/clapper/gtk4/gstclapperglsink.h @@ -0,0 +1,106 @@ +/* + * GStreamer + * Copyright (C) 2015 Matthew Waters + * Copyright (C) 2020 Rafał Dzięgiel + * + * 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_CLAPPER_GL_SINK_H__ +#define __GST_CLAPPER_GL_SINK_H__ + +#include +#include +#include +#include +#include + +#include "gtkclapperglwidget.h" + +#define GST_TYPE_CLAPPER_GL_SINK (gst_clapper_gl_sink_get_type()) +#define GST_CLAPPER_GL_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CLAPPER_GL_SINK,GstClapperGLSink)) +#define GST_CLAPPER_GL_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CLAPPER_GL_SINK,GstClapperGLClass)) +#define GST_CLAPPER_GL_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_GL_SINK, GstClapperGLSinkClass)) +#define GST_IS_CLAPPER_GL_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CLAPPER_GL_SINK)) +#define GST_IS_CLAPPER_GL_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CLAPPER_GL_SINK)) +#define GST_CLAPPER_GL_SINK_CAST(obj) ((GstClapperGLSink*)(obj)) + +G_BEGIN_DECLS +typedef struct _GstClapperGLSink GstClapperGLSink; +typedef struct _GstClapperGLSinkClass GstClapperGLSinkClass; + +GType gst_clapper_gl_sink_get_type (void); + +/** + * GstClapperGLSink: + * + * Opaque #GstClapperGLSink object + */ +struct _GstClapperGLSink +{ + /* */ + GstVideoSink parent; + + GstVideoInfo v_info; + + GtkClapperGLWidget *widget; + + /* properties */ + gboolean force_aspect_ratio; + GBinding *bind_aspect_ratio; + + gint par_n, par_d; + GBinding *bind_pixel_aspect_ratio; + + gboolean ignore_textures; + GBinding *bind_ignore_textures; + + GtkWidget *window; + gulong widget_destroy_id; + gulong window_destroy_id; + + GstGLDisplay *display; + GstGLContext *context; + GstGLContext *gtk_context; + + GstGLUpload *upload; + GstBuffer *uploaded_buffer; + + /* read/write with object lock */ + gint display_width, display_height; +}; + +/** + * GstClapperGLSinkClass: + * + * The #GstClapperGLSinkClass struct only contains private data + */ +struct _GstClapperGLSinkClass +{ + GstVideoSinkClass object_class; + + /* metadata */ + const gchar *window_title; + + /* virtuals */ + GtkWidget* (*create_widget) (void); +}; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperGLSink, gst_object_unref) + +G_END_DECLS + +#endif /* __GST_CLAPPER_GL_SINK_H__ */ diff --git a/lib/gst/clapper/gtk4/gstgtkbasesink.h b/lib/gst/clapper/gtk4/gstgtkbasesink.h deleted file mode 100644 index bac19ac7..00000000 --- a/lib/gst/clapper/gtk4/gstgtkbasesink.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters - * - * 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_GTK_BASE_SINK_H__ -#define __GST_GTK_BASE_SINK_H__ - -#include -#include -#include -#include -#include - -#include "gtkgstbasewidget.h" - -#define GST_TYPE_GTK_BASE_SINK (gst_gtk_base_sink_get_type()) -#define GST_GTK_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GTK_BASE_SINK,GstGtkBaseSink)) -#define GST_GTK_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GTK_BASE_SINK,GstGtkBaseSinkClass)) -#define GST_GTK_BASE_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GTK_BASE_SINK, GstGtkBaseSinkClass)) -#define GST_IS_GTK_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GTK_BASE_SINK)) -#define GST_IS_GTK_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GTK_BASE_SINK)) -#define GST_GTK_BASE_SINK_CAST(obj) ((GstGtkBaseSink*)(obj)) - -G_BEGIN_DECLS -typedef struct _GstGtkBaseSink GstGtkBaseSink; -typedef struct _GstGtkBaseSinkClass GstGtkBaseSinkClass; - -GType gst_gtk_base_sink_get_type (void); - -/** - * GstGtkBaseSink: - * - * Opaque #GstGtkBaseSink object - */ -struct _GstGtkBaseSink -{ - /* */ - GstVideoSink parent; - - GstVideoInfo v_info; - - GtkGstBaseWidget *widget; - - /* properties */ - gboolean force_aspect_ratio; - GBinding *bind_aspect_ratio; - - gint par_n; - gint par_d; - GBinding *bind_pixel_aspect_ratio; - - gboolean ignore_textures; - GBinding *bind_ignore_textures; - - GtkWidget *window; - gulong widget_destroy_id; - gulong window_destroy_id; - - GstGLDisplay *display; - GstGLContext *context; - GstGLContext *gtk_context; - - GstGLUpload *upload; - GstBuffer *uploaded_buffer; - - /* read/write with object lock */ - gint display_width; - gint display_height; -}; - -/** - * GstGtkBaseSinkClass: - * - * The #GstGtkBaseSinkClass struct only contains private data - */ -struct _GstGtkBaseSinkClass -{ - GstVideoSinkClass object_class; - - /* metadata */ - const gchar *window_title; - - /* virtuals */ - GtkWidget* (*create_widget) (void); -}; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstGtkBaseSink, gst_object_unref) - -G_END_DECLS - -#endif /* __GST_GTK_BASE_SINK_H__ */ diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.c b/lib/gst/clapper/gtk4/gtkclapperglwidget.c similarity index 59% rename from lib/gst/clapper/gtk4/gtkgstbasewidget.c rename to lib/gst/clapper/gtk4/gtkclapperglwidget.c index 03ce8793..108f555e 100644 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.c +++ b/lib/gst/clapper/gtk4/gtkclapperglwidget.c @@ -27,7 +27,7 @@ #include #include -#include "gtkgstbasewidget.h" +#include "gtkclapperglwidget.h" #include "gstgtkutils.h" #if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) @@ -41,23 +41,23 @@ #endif /** - * SECTION:gtkgstbasewidget - * @title: GtkGstBaseWidget + * SECTION:gtkclapperglwidget + * @title: GtkClapperGLWidget * @short_description: a #GtkGLArea that renders GStreamer video #GstBuffers * @see_also: #GtkGLArea, #GstBuffer * - * #GtkGstBaseWidget is an #GtkWidget that renders GStreamer video buffers. + * #GtkClapperGLWidget is a #GtkWidget that renders GStreamer video buffers. */ -GST_DEBUG_CATEGORY (gst_debug_gtk_base_widget); -#define GST_CAT_DEFAULT gst_debug_gtk_base_widget +GST_DEBUG_CATEGORY (gst_debug_clapper_gl_widget); +#define GST_CAT_DEFAULT gst_debug_clapper_gl_widget #define DEFAULT_FORCE_ASPECT_RATIO TRUE #define DEFAULT_PAR_N 0 #define DEFAULT_PAR_D 1 #define DEFAULT_IGNORE_TEXTURES FALSE -struct _GtkGstBaseWidgetPrivate +struct _GtkClapperGLWidgetPrivate { gboolean initiated; GstGLDisplay *display; @@ -85,10 +85,10 @@ static const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; -G_DEFINE_TYPE_WITH_CODE (GtkGstBaseWidget, gtk_gst_base_widget, GTK_TYPE_GL_AREA, - G_ADD_PRIVATE (GtkGstBaseWidget) - GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkgstbasewidget", 0, - "GTK Gst Base Widget")); +G_DEFINE_TYPE_WITH_CODE (GtkClapperGLWidget, gtk_clapper_gl_widget, GTK_TYPE_GL_AREA, + G_ADD_PRIVATE (GtkClapperGLWidget) + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkclapperglwidget", 0, + "GTK Clapper GL Widget")); enum { @@ -99,13 +99,13 @@ enum }; static void -gtk_gst_base_widget_get_preferred_width (GtkWidget * widget, gint * min, +gtk_clapper_gl_widget_get_preferred_width (GtkWidget * widget, gint * min, gint * natural) { - GtkGstBaseWidget *base_widget = (GtkGstBaseWidget *) widget; - gint video_width = base_widget->display_width; + GtkClapperGLWidget *clapper_widget = (GtkClapperGLWidget *) widget; + gint video_width = clapper_widget->display_width; - if (!base_widget->negotiated) + if (!clapper_widget->negotiated) video_width = 10; if (min) @@ -115,13 +115,13 @@ gtk_gst_base_widget_get_preferred_width (GtkWidget * widget, gint * min, } static void -gtk_gst_base_widget_get_preferred_height (GtkWidget * widget, gint * min, +gtk_clapper_gl_widget_get_preferred_height (GtkWidget * widget, gint * min, gint * natural) { - GtkGstBaseWidget *base_widget = (GtkGstBaseWidget *) widget; - gint video_height = base_widget->display_height; + GtkClapperGLWidget *clapper_widget = (GtkClapperGLWidget *) widget; + gint video_height = clapper_widget->display_height; - if (!base_widget->negotiated) + if (!clapper_widget->negotiated) video_height = 10; if (min) @@ -131,52 +131,52 @@ gtk_gst_base_widget_get_preferred_height (GtkWidget * widget, gint * min, } static void -gtk_gst_base_widget_measure (GtkWidget * widget, GtkOrientation orientation, +gtk_clapper_gl_widget_measure (GtkWidget * widget, GtkOrientation orientation, gint for_size, gint * min, gint * natural, gint * minimum_baseline, gint * natural_baseline) { if (orientation == GTK_ORIENTATION_HORIZONTAL) - gtk_gst_base_widget_get_preferred_width (widget, min, natural); + gtk_clapper_gl_widget_get_preferred_width (widget, min, natural); else - gtk_gst_base_widget_get_preferred_height (widget, min, natural); + gtk_clapper_gl_widget_get_preferred_height (widget, min, natural); *minimum_baseline = -1; *natural_baseline = -1; } static void -gtk_gst_base_widget_size_allocate (GtkWidget * widget, +gtk_clapper_gl_widget_size_allocate (GtkWidget * widget, gint width, gint height, gint baseline) { - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (widget); gint scale_factor = gtk_widget_get_scale_factor (widget); - GTK_GST_BASE_WIDGET_LOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget); - base_widget->scaled_width = width * scale_factor; - base_widget->scaled_height = height * scale_factor; + clapper_widget->scaled_width = width * scale_factor; + clapper_widget->scaled_height = height * scale_factor; - GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); gtk_gl_area_queue_render (GTK_GL_AREA (widget)); } static void -gtk_gst_base_widget_set_property (GObject * object, guint prop_id, +gtk_clapper_gl_widget_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GtkGstBaseWidget *gtk_widget = GTK_GST_BASE_WIDGET (object); + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (object); switch (prop_id) { case PROP_FORCE_ASPECT_RATIO: - gtk_widget->force_aspect_ratio = g_value_get_boolean (value); + clapper_widget->force_aspect_ratio = g_value_get_boolean (value); break; case PROP_PIXEL_ASPECT_RATIO: - gtk_widget->par_n = gst_value_get_fraction_numerator (value); - gtk_widget->par_d = gst_value_get_fraction_denominator (value); + clapper_widget->par_n = gst_value_get_fraction_numerator (value); + clapper_widget->par_d = gst_value_get_fraction_denominator (value); break; case PROP_IGNORE_TEXTURES: - gtk_widget->ignore_textures = g_value_get_boolean (value); + clapper_widget->ignore_textures = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -185,20 +185,20 @@ gtk_gst_base_widget_set_property (GObject * object, guint prop_id, } static void -gtk_gst_base_widget_get_property (GObject * object, guint prop_id, +gtk_clapper_gl_widget_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GtkGstBaseWidget *gtk_widget = GTK_GST_BASE_WIDGET (object); + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (object); switch (prop_id) { case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean (value, gtk_widget->force_aspect_ratio); + g_value_set_boolean (value, clapper_widget->force_aspect_ratio); break; case PROP_PIXEL_ASPECT_RATIO: - gst_value_set_fraction (value, gtk_widget->par_n, gtk_widget->par_d); + gst_value_set_fraction (value, clapper_widget->par_n, clapper_widget->par_d); break; case PROP_IGNORE_TEXTURES: - g_value_set_boolean (value, gtk_widget->ignore_textures); + g_value_set_boolean (value, clapper_widget->ignore_textures); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -207,7 +207,7 @@ gtk_gst_base_widget_get_property (GObject * object, guint prop_id, } static gboolean -_calculate_par (GtkGstBaseWidget * widget, GstVideoInfo * info) +_calculate_par (GtkClapperGLWidget * clapper_widget, GstVideoInfo * info) { gboolean ok; gint width, height; @@ -224,16 +224,16 @@ _calculate_par (GtkGstBaseWidget * widget, GstVideoInfo * info) par_n = 1; /* get display's PAR */ - if (widget->par_n != 0 && widget->par_d != 0) { - display_par_n = widget->par_n; - display_par_d = widget->par_d; + if (clapper_widget->par_n != 0 && clapper_widget->par_d != 0) { + display_par_n = clapper_widget->par_n; + display_par_d = clapper_widget->par_d; } else { display_par_n = 1; display_par_d = 1; } - ok = gst_video_calculate_display_ratio (&widget->display_ratio_num, - &widget->display_ratio_den, width, height, par_n, par_d, display_par_n, + ok = gst_video_calculate_display_ratio (&clapper_widget->display_ratio_num, + &clapper_widget->display_ratio_den, width, height, par_n, par_d, display_par_n, display_par_d); if (ok) { @@ -246,59 +246,59 @@ _calculate_par (GtkGstBaseWidget * widget, GstVideoInfo * info) } static void -_apply_par (GtkGstBaseWidget * widget) +_apply_par (GtkClapperGLWidget * clapper_widget) { guint display_ratio_num, display_ratio_den; gint width, height; - width = GST_VIDEO_INFO_WIDTH (&widget->v_info); - height = GST_VIDEO_INFO_HEIGHT (&widget->v_info); + width = GST_VIDEO_INFO_WIDTH (&clapper_widget->v_info); + height = GST_VIDEO_INFO_HEIGHT (&clapper_widget->v_info); - display_ratio_num = widget->display_ratio_num; - display_ratio_den = widget->display_ratio_den; + display_ratio_num = clapper_widget->display_ratio_num; + display_ratio_den = clapper_widget->display_ratio_den; if (height % display_ratio_den == 0) { GST_DEBUG ("keeping video height"); - widget->display_width = (guint) + clapper_widget->display_width = (guint) gst_util_uint64_scale_int (height, display_ratio_num, display_ratio_den); - widget->display_height = height; + clapper_widget->display_height = height; } else if (width % display_ratio_num == 0) { GST_DEBUG ("keeping video width"); - widget->display_width = width; - widget->display_height = (guint) + clapper_widget->display_width = width; + clapper_widget->display_height = (guint) gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num); } else { GST_DEBUG ("approximating while keeping video height"); - widget->display_width = (guint) + clapper_widget->display_width = (guint) gst_util_uint64_scale_int (height, display_ratio_num, display_ratio_den); - widget->display_height = height; + clapper_widget->display_height = height; } - GST_DEBUG ("scaling to %dx%d", widget->display_width, widget->display_height); + GST_DEBUG ("scaling to %dx%d", clapper_widget->display_width, clapper_widget->display_height); } static gboolean -_queue_draw (GtkGstBaseWidget * widget) +_queue_draw (GtkClapperGLWidget * clapper_widget) { - GTK_GST_BASE_WIDGET_LOCK (widget); - widget->draw_id = 0; + GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget); + clapper_widget->draw_id = 0; - if (widget->pending_resize) { - widget->pending_resize = FALSE; + if (clapper_widget->pending_resize) { + clapper_widget->pending_resize = FALSE; - widget->v_info = widget->pending_v_info; - widget->negotiated = TRUE; + clapper_widget->v_info = clapper_widget->pending_v_info; + clapper_widget->negotiated = TRUE; - _apply_par (widget); + _apply_par (clapper_widget); - gtk_widget_queue_resize (GTK_WIDGET (widget)); + gtk_widget_queue_resize (GTK_WIDGET (clapper_widget)); } else { - gtk_gl_area_queue_render (GTK_GL_AREA (widget)); + gtk_gl_area_queue_render (GTK_GL_AREA (clapper_widget)); } - GTK_GST_BASE_WIDGET_UNLOCK (widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return G_SOURCE_REMOVE; } @@ -322,15 +322,15 @@ _gdk_key_to_navigation_string (guint keyval) } static gboolean -gtk_gst_base_widget_key_event (GtkEventControllerKey * key_controller, +gtk_clapper_gl_widget_key_event (GtkEventControllerKey * key_controller, guint keyval, guint keycode, GdkModifierType state) { GtkEventController *controller = GTK_EVENT_CONTROLLER (key_controller); GtkWidget *widget = gtk_event_controller_get_widget (controller); - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (widget); GstElement *element; - if ((element = g_weak_ref_get (&base_widget->element))) { + if ((element = g_weak_ref_get (&clapper_widget->element))) { if (GST_IS_NAVIGATION (element)) { GdkEvent *event = gtk_event_controller_get_current_event (controller); const gchar *str = _gdk_key_to_navigation_string (keyval); @@ -349,41 +349,41 @@ gtk_gst_base_widget_key_event (GtkEventControllerKey * key_controller, } static void -_fit_stream_to_allocated_size (GtkGstBaseWidget * base_widget, GstVideoRectangle * result) +_fit_stream_to_allocated_size (GtkClapperGLWidget * clapper_widget, GstVideoRectangle * result) { - if (base_widget->force_aspect_ratio) { + if (clapper_widget->force_aspect_ratio) { GstVideoRectangle src, dst; src.x = 0; src.y = 0; - src.w = base_widget->display_width; - src.h = base_widget->display_height; + src.w = clapper_widget->display_width; + src.h = clapper_widget->display_height; dst.x = 0; dst.y = 0; - dst.w = base_widget->scaled_width; - dst.h = base_widget->scaled_height; + dst.w = clapper_widget->scaled_width; + dst.h = clapper_widget->scaled_height; gst_video_sink_center_rect (src, dst, result, TRUE); } else { result->x = 0; result->y = 0; - result->w = base_widget->scaled_width; - result->h = base_widget->scaled_height; + result->w = clapper_widget->scaled_width; + result->h = clapper_widget->scaled_height; } } static void -_display_size_to_stream_size (GtkGstBaseWidget * base_widget, gdouble x, +_display_size_to_stream_size (GtkClapperGLWidget * clapper_widget, gdouble x, gdouble y, gdouble * stream_x, gdouble * stream_y) { gdouble stream_width, stream_height; GstVideoRectangle result; - _fit_stream_to_allocated_size (base_widget, &result); + _fit_stream_to_allocated_size (clapper_widget, &result); - stream_width = (gdouble) GST_VIDEO_INFO_WIDTH (&base_widget->v_info); - stream_height = (gdouble) GST_VIDEO_INFO_HEIGHT (&base_widget->v_info); + stream_width = (gdouble) GST_VIDEO_INFO_WIDTH (&clapper_widget->v_info); + stream_height = (gdouble) GST_VIDEO_INFO_HEIGHT (&clapper_widget->v_info); /* from display coordinates to stream coordinates */ if (result.w > 0) @@ -394,8 +394,8 @@ _display_size_to_stream_size (GtkGstBaseWidget * base_widget, gdouble x, /* clip to stream size */ if (*stream_x < 0.) *stream_x = 0.; - if (*stream_x > GST_VIDEO_INFO_WIDTH (&base_widget->v_info)) - *stream_x = GST_VIDEO_INFO_WIDTH (&base_widget->v_info); + if (*stream_x > GST_VIDEO_INFO_WIDTH (&clapper_widget->v_info)) + *stream_x = GST_VIDEO_INFO_WIDTH (&clapper_widget->v_info); /* same for y-axis */ if (result.h > 0) @@ -405,22 +405,22 @@ _display_size_to_stream_size (GtkGstBaseWidget * base_widget, gdouble x, if (*stream_y < 0.) *stream_y = 0.; - if (*stream_y > GST_VIDEO_INFO_HEIGHT (&base_widget->v_info)) - *stream_y = GST_VIDEO_INFO_HEIGHT (&base_widget->v_info); + if (*stream_y > GST_VIDEO_INFO_HEIGHT (&clapper_widget->v_info)) + *stream_y = GST_VIDEO_INFO_HEIGHT (&clapper_widget->v_info); GST_TRACE ("transform %fx%f into %fx%f", x, y, *stream_x, *stream_y); } static gboolean -gtk_gst_base_widget_button_event (GtkGestureClick * gesture, +gtk_clapper_gl_widget_button_event (GtkGestureClick * gesture, gint n_press, gdouble x, gdouble y) { GtkEventController *controller = GTK_EVENT_CONTROLLER (gesture); GtkWidget *widget = gtk_event_controller_get_widget (controller); - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (widget); GstElement *element; - if ((element = g_weak_ref_get (&base_widget->element))) { + if ((element = g_weak_ref_get (&clapper_widget->element))) { if (GST_IS_NAVIGATION (element)) { GdkEvent *event = gtk_event_controller_get_current_event (controller); const gchar *key_type = @@ -428,7 +428,7 @@ gtk_gst_base_widget_button_event (GtkGestureClick * gesture, ? "mouse-button-press" : "mouse-button-release"; gdouble stream_x, stream_y; - _display_size_to_stream_size (base_widget, x, y, &stream_x, &stream_y); + _display_size_to_stream_size (clapper_widget, x, y, &stream_x, &stream_y); gst_navigation_send_mouse_event (GST_NAVIGATION (element), key_type, /* Gesture is set to ignore other buttons so we do not have to check */ @@ -442,19 +442,19 @@ gtk_gst_base_widget_button_event (GtkGestureClick * gesture, } static gboolean -gtk_gst_base_widget_motion_event (GtkEventControllerMotion * motion_controller, +gtk_clapper_gl_widget_motion_event (GtkEventControllerMotion * motion_controller, gdouble x, gdouble y) { GtkEventController *controller = GTK_EVENT_CONTROLLER (motion_controller); GtkWidget *widget = gtk_event_controller_get_widget (controller); - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (widget); GstElement *element; - if ((element = g_weak_ref_get (&base_widget->element))) { + if ((element = g_weak_ref_get (&clapper_widget->element))) { if (GST_IS_NAVIGATION (element)) { gdouble stream_x, stream_y; - _display_size_to_stream_size (base_widget, x, y, &stream_x, &stream_y); + _display_size_to_stream_size (clapper_widget, x, y, &stream_x, &stream_y); gst_navigation_send_mouse_event (GST_NAVIGATION (element), "mouse-move", 0, stream_x, stream_y); @@ -466,9 +466,9 @@ gtk_gst_base_widget_motion_event (GtkEventControllerMotion * motion_controller, } static void -gtk_gst_base_widget_bind_buffer (GtkGstBaseWidget * base_widget) +gtk_clapper_gl_widget_bind_buffer (GtkClapperGLWidget * clapper_widget) { - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; const GstGLFuncs *gl = priv->context->gl_vtable; gl->BindBuffer (GL_ARRAY_BUFFER, priv->vertex_buffer); @@ -486,9 +486,9 @@ gtk_gst_base_widget_bind_buffer (GtkGstBaseWidget * base_widget) } static void -gtk_gst_base_widget_unbind_buffer (GtkGstBaseWidget * base_widget) +gtk_clapper_gl_widget_unbind_buffer (GtkClapperGLWidget * clapper_widget) { - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; const GstGLFuncs *gl = priv->context->gl_vtable; gl->BindBuffer (GL_ARRAY_BUFFER, 0); @@ -498,9 +498,9 @@ gtk_gst_base_widget_unbind_buffer (GtkGstBaseWidget * base_widget) } static void -gtk_gst_base_widget_init_redisplay (GtkGstBaseWidget * base_widget) +gtk_clapper_gl_widget_init_redisplay (GtkClapperGLWidget * clapper_widget) { - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; const GstGLFuncs *gl = priv->context->gl_vtable; GError *error = NULL; @@ -526,7 +526,7 @@ gtk_gst_base_widget_init_redisplay (GtkGstBaseWidget * base_widget) GL_STATIC_DRAW); if (gl->GenVertexArrays) { - gtk_gst_base_widget_bind_buffer (base_widget); + gtk_clapper_gl_widget_bind_buffer (clapper_widget); gl->BindVertexArray (0); } @@ -557,39 +557,39 @@ _draw_black_with_gdk (GdkGLContext * gdk_context) } static gboolean -gtk_gst_base_widget_render (GtkGLArea * widget, GdkGLContext * context) +gtk_clapper_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) { - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (widget); - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; const GstGLFuncs *gl; - GTK_GST_BASE_WIDGET_LOCK (widget); + GTK_CLAPPER_GL_WIDGET_LOCK (widget); /* Draw black with GDK context when priv is not available yet. GTK calls render with GDK context already active. */ - if (!priv->context || !priv->other_context || base_widget->ignore_textures) { + if (!priv->context || !priv->other_context || clapper_widget->ignore_textures) { _draw_black_with_gdk (context); goto done; } gst_gl_context_activate (priv->other_context, TRUE); - if (!priv->initiated || !base_widget->negotiated) { + if (!priv->initiated || !clapper_widget->negotiated) { if (!priv->initiated) - gtk_gst_base_widget_init_redisplay (base_widget); + gtk_clapper_gl_widget_init_redisplay (clapper_widget); _draw_black (priv->other_context); goto done; } /* Upload latest buffer */ - if (base_widget->pending_buffer) { - GstBuffer *buffer = base_widget->pending_buffer; + if (clapper_widget->pending_buffer) { + GstBuffer *buffer = clapper_widget->pending_buffer; GstVideoFrame gl_frame; GstGLSyncMeta *sync_meta; - if (!gst_video_frame_map (&gl_frame, &base_widget->v_info, buffer, + if (!gst_video_frame_map (&gl_frame, &clapper_widget->v_info, buffer, GST_MAP_READ | GST_MAP_GL)) { _draw_black (priv->other_context); goto done; @@ -608,21 +608,21 @@ gtk_gst_base_widget_render (GtkGLArea * widget, GdkGLContext * context) gst_video_frame_unmap (&gl_frame); - if (base_widget->buffer) - gst_buffer_unref (base_widget->buffer); + if (clapper_widget->buffer) + gst_buffer_unref (clapper_widget->buffer); /* Keep the buffer to ensure current_tex stay valid */ - base_widget->buffer = buffer; - base_widget->pending_buffer = NULL; + clapper_widget->buffer = buffer; + clapper_widget->pending_buffer = NULL; } GST_DEBUG ("rendering buffer %p with gdk context %p", - base_widget->buffer, context); + clapper_widget->buffer, context); /* Draw texture */ gl = priv->context->gl_vtable; - if (base_widget->force_aspect_ratio) { + if (clapper_widget->force_aspect_ratio) { GstVideoRectangle src, dst, result; gl->ClearColor (0.0, 0.0, 0.0, 1.0); @@ -630,13 +630,13 @@ gtk_gst_base_widget_render (GtkGLArea * widget, GdkGLContext * context) src.x = 0; src.y = 0; - src.w = base_widget->display_width; - src.h = base_widget->display_height; + src.w = clapper_widget->display_width; + src.h = clapper_widget->display_height; dst.x = 0; dst.y = 0; - dst.w = base_widget->scaled_width; - dst.h = base_widget->scaled_height; + dst.w = clapper_widget->scaled_width; + dst.h = clapper_widget->scaled_height; gst_video_sink_center_rect (src, dst, &result, TRUE); @@ -648,7 +648,7 @@ gtk_gst_base_widget_render (GtkGLArea * widget, GdkGLContext * context) if (gl->BindVertexArray) gl->BindVertexArray (priv->vao); - gtk_gst_base_widget_bind_buffer (base_widget); + gtk_clapper_gl_widget_bind_buffer (clapper_widget); gl->ActiveTexture (GL_TEXTURE0); gl->BindTexture (GL_TEXTURE_2D, priv->current_tex); @@ -659,7 +659,7 @@ gtk_gst_base_widget_render (GtkGLArea * widget, GdkGLContext * context) if (gl->BindVertexArray) gl->BindVertexArray (0); else - gtk_gst_base_widget_unbind_buffer (base_widget); + gtk_clapper_gl_widget_unbind_buffer (clapper_widget); gl->BindTexture (GL_TEXTURE_2D, 0); @@ -670,18 +670,18 @@ done: if (priv->other_context) gst_gl_context_activate (priv->other_context, FALSE); - GTK_GST_BASE_WIDGET_UNLOCK (widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (widget); return FALSE; } static void -_reset_gl (GtkGstBaseWidget * base_widget) +_reset_gl (GtkClapperGLWidget * clapper_widget) { - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; const GstGLFuncs *gl = priv->other_context->gl_vtable; if (!priv->gdk_context) - priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (base_widget)); + priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (clapper_widget)); if (priv->gdk_context == NULL) return; @@ -724,13 +724,13 @@ _reset_gl (GtkGstBaseWidget * base_widget) } static void -gtk_gst_base_widget_finalize (GObject * object) +gtk_clapper_gl_widget_finalize (GObject * object) { - GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (object); - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (object); + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; if (priv->other_context) - gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _reset_gl, base_widget); + gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _reset_gl, clapper_widget); if (priv->context) gst_object_unref (priv->context); @@ -738,75 +738,75 @@ gtk_gst_base_widget_finalize (GObject * object) if (priv->display) gst_object_unref (priv->display); - if (base_widget->draw_id) - g_source_remove (base_widget->draw_id); + if (clapper_widget->draw_id) + g_source_remove (clapper_widget->draw_id); - gst_buffer_replace (&base_widget->pending_buffer, NULL); - gst_buffer_replace (&base_widget->buffer, NULL); - g_mutex_clear (&base_widget->lock); - g_weak_ref_clear (&base_widget->element); + gst_buffer_replace (&clapper_widget->pending_buffer, NULL); + gst_buffer_replace (&clapper_widget->buffer, NULL); + g_mutex_clear (&clapper_widget->lock); + g_weak_ref_clear (&clapper_widget->element); - G_OBJECT_CLASS (gtk_gst_base_widget_parent_class)->finalize (object); + G_OBJECT_CLASS (gtk_clapper_gl_widget_parent_class)->finalize (object); } void -gtk_gst_base_widget_set_element (GtkGstBaseWidget * widget, +gtk_clapper_gl_widget_set_element (GtkClapperGLWidget * clapper_widget, GstElement * element) { - g_weak_ref_set (&widget->element, element); + g_weak_ref_set (&clapper_widget->element, element); } gboolean -gtk_gst_base_widget_set_format (GtkGstBaseWidget * widget, +gtk_clapper_gl_widget_set_format (GtkClapperGLWidget * clapper_widget, GstVideoInfo * v_info) { - GTK_GST_BASE_WIDGET_LOCK (widget); + GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget); - if (gst_video_info_is_equal (&widget->pending_v_info, v_info)) { - GTK_GST_BASE_WIDGET_UNLOCK (widget); + if (gst_video_info_is_equal (&clapper_widget->pending_v_info, v_info)) { + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return TRUE; } - if (!_calculate_par (widget, v_info)) { - GTK_GST_BASE_WIDGET_UNLOCK (widget); + if (!_calculate_par (clapper_widget, v_info)) { + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return FALSE; } - widget->pending_resize = TRUE; - widget->pending_v_info = *v_info; + clapper_widget->pending_resize = TRUE; + clapper_widget->pending_v_info = *v_info; - GTK_GST_BASE_WIDGET_UNLOCK (widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return TRUE; } void -gtk_gst_base_widget_set_buffer (GtkGstBaseWidget * widget, GstBuffer * buffer) +gtk_clapper_gl_widget_set_buffer (GtkClapperGLWidget * clapper_widget, + GstBuffer * buffer) { - /* As we have no type, this is better then no check */ - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_IS_CLAPPER_GL_WIDGET (clapper_widget)); - GTK_GST_BASE_WIDGET_LOCK (widget); + GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget); - gst_buffer_replace (&widget->pending_buffer, buffer); + gst_buffer_replace (&clapper_widget->pending_buffer, buffer); - if (!widget->draw_id) { - widget->draw_id = g_idle_add_full (G_PRIORITY_DEFAULT, - (GSourceFunc) _queue_draw, widget, NULL); + if (!clapper_widget->draw_id) { + clapper_widget->draw_id = g_idle_add_full (G_PRIORITY_DEFAULT, + (GSourceFunc) _queue_draw, clapper_widget, NULL); } - GTK_GST_BASE_WIDGET_UNLOCK (widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); } static void -_get_gl_context (GtkGstBaseWidget * base_widget) +_get_gl_context (GtkClapperGLWidget * clapper_widget) { - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; GstGLPlatform platform = GST_GL_PLATFORM_NONE; GstGLAPI gl_api = GST_GL_API_NONE; guintptr gl_handle = 0; - gtk_widget_realize (GTK_WIDGET (base_widget)); + gtk_widget_realize (GTK_WIDGET (clapper_widget)); if (priv->other_context) gst_object_unref (priv->other_context); @@ -815,11 +815,11 @@ _get_gl_context (GtkGstBaseWidget * base_widget) if (priv->gdk_context) g_object_unref (priv->gdk_context); - priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (base_widget)); + priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (clapper_widget)); if (priv->gdk_context == NULL) { - GError *error = gtk_gl_area_get_error (GTK_GL_AREA (base_widget)); + GError *error = gtk_gl_area_get_error (GTK_GL_AREA (clapper_widget)); - GST_ERROR_OBJECT (base_widget, "Error creating GdkGLContext : %s", + GST_ERROR_OBJECT (clapper_widget, "Error creating GdkGLContext : %s", error ? error->message : "No error set by Gdk"); g_clear_error (&error); return; @@ -889,15 +889,15 @@ _get_gl_context (GtkGstBaseWidget * base_widget) } static void -gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) +gtk_clapper_gl_widget_class_init (GtkClapperGLWidgetClass * klass) { GObjectClass *gobject_klass = (GObjectClass *) klass; GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass; GtkGLAreaClass *gl_area_klass = (GtkGLAreaClass *) klass; - gobject_klass->set_property = gtk_gst_base_widget_set_property; - gobject_klass->get_property = gtk_gst_base_widget_get_property; - gobject_klass->finalize = gtk_gst_base_widget_finalize; + gobject_klass->set_property = gtk_clapper_gl_widget_set_property; + gobject_klass->get_property = gtk_clapper_gl_widget_get_property; + gobject_klass->finalize = gtk_clapper_gl_widget_finalize; g_object_class_install_property (gobject_klass, PROP_FORCE_ASPECT_RATIO, g_param_spec_boolean ("force-aspect-ratio", @@ -916,65 +916,62 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) "When enabled, textures will be ignored and not drawn", DEFAULT_IGNORE_TEXTURES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - widget_klass->measure = gtk_gst_base_widget_measure; - widget_klass->size_allocate = gtk_gst_base_widget_size_allocate; + widget_klass->measure = gtk_clapper_gl_widget_measure; + widget_klass->size_allocate = gtk_clapper_gl_widget_size_allocate; - gl_area_klass->render = gtk_gst_base_widget_render; - - GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_widget, "gtkbasewidget", 0, - "GTK Video Base Widget"); + gl_area_klass->render = gtk_clapper_gl_widget_render; } static void -gtk_gst_base_widget_init (GtkGstBaseWidget * widget) +gtk_clapper_gl_widget_init (GtkClapperGLWidget * clapper_widget) { GdkDisplay *display; - GtkGstBaseWidgetPrivate *priv; + GtkClapperGLWidgetPrivate *priv; + GtkWidget *widget = GTK_WIDGET (clapper_widget); - widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; - widget->par_n = DEFAULT_PAR_N; - widget->par_d = DEFAULT_PAR_D; - widget->ignore_textures = DEFAULT_IGNORE_TEXTURES; + clapper_widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; + clapper_widget->par_n = DEFAULT_PAR_N; + clapper_widget->par_d = DEFAULT_PAR_D; + clapper_widget->ignore_textures = DEFAULT_IGNORE_TEXTURES; - gst_video_info_init (&widget->v_info); - gst_video_info_init (&widget->pending_v_info); + gst_video_info_init (&clapper_widget->v_info); + gst_video_info_init (&clapper_widget->pending_v_info); - g_weak_ref_init (&widget->element, NULL); - g_mutex_init (&widget->lock); + g_weak_ref_init (&clapper_widget->element, NULL); + g_mutex_init (&clapper_widget->lock); - widget->key_controller = gtk_event_controller_key_new (); - g_signal_connect (widget->key_controller, "key-pressed", - G_CALLBACK (gtk_gst_base_widget_key_event), NULL); - g_signal_connect (widget->key_controller, "key-released", - G_CALLBACK (gtk_gst_base_widget_key_event), NULL); + clapper_widget->key_controller = gtk_event_controller_key_new (); + g_signal_connect (clapper_widget->key_controller, "key-pressed", + G_CALLBACK (gtk_clapper_gl_widget_key_event), NULL); + g_signal_connect (clapper_widget->key_controller, "key-released", + G_CALLBACK (gtk_clapper_gl_widget_key_event), NULL); - widget->motion_controller = gtk_event_controller_motion_new (); - g_signal_connect (widget->motion_controller, "motion", - G_CALLBACK (gtk_gst_base_widget_motion_event), NULL); + clapper_widget->motion_controller = gtk_event_controller_motion_new (); + g_signal_connect (clapper_widget->motion_controller, "motion", + G_CALLBACK (gtk_clapper_gl_widget_motion_event), NULL); - widget->click_gesture = gtk_gesture_click_new (); - g_signal_connect (widget->click_gesture, "pressed", - G_CALLBACK (gtk_gst_base_widget_button_event), NULL); - g_signal_connect (widget->click_gesture, "released", - G_CALLBACK (gtk_gst_base_widget_button_event), NULL); + clapper_widget->click_gesture = gtk_gesture_click_new (); + g_signal_connect (clapper_widget->click_gesture, "pressed", + G_CALLBACK (gtk_clapper_gl_widget_button_event), NULL); + g_signal_connect (clapper_widget->click_gesture, "released", + G_CALLBACK (gtk_clapper_gl_widget_button_event), NULL); /* Otherwise widget in grid will appear as a 1x1px * video which might be misleading for users */ - gtk_widget_set_hexpand (GTK_WIDGET (widget), TRUE); - gtk_widget_set_vexpand (GTK_WIDGET (widget), TRUE); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_vexpand (widget, TRUE); - gtk_widget_set_focusable (GTK_WIDGET (widget), TRUE); - gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (widget->click_gesture), + gtk_widget_set_focusable (widget, TRUE); + gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (clapper_widget->click_gesture), GDK_BUTTON_PRIMARY); - gtk_widget_add_controller (GTK_WIDGET (widget), widget->key_controller); - gtk_widget_add_controller (GTK_WIDGET (widget), widget->motion_controller); - gtk_widget_add_controller (GTK_WIDGET (widget), - GTK_EVENT_CONTROLLER (widget->click_gesture)); + gtk_widget_add_controller (widget, clapper_widget->key_controller); + gtk_widget_add_controller (widget, clapper_widget->motion_controller); + gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (clapper_widget->click_gesture)); - gtk_widget_set_can_focus (GTK_WIDGET (widget), TRUE); + gtk_widget_set_can_focus (widget, TRUE); - widget->priv = priv = gtk_gst_base_widget_get_instance_private (widget); + clapper_widget->priv = priv = gtk_clapper_gl_widget_get_instance_private (clapper_widget); display = gdk_display_get_default (); @@ -1005,37 +1002,37 @@ gtk_gst_base_widget_init (GtkGstBaseWidget * widget) } GtkWidget * -gtk_gst_base_widget_new (void) +gtk_clapper_gl_widget_new (void) { - return (GtkWidget *) g_object_new (GTK_TYPE_GST_BASE_WIDGET, NULL); + return (GtkWidget *) g_object_new (GTK_TYPE_CLAPPER_GL_WIDGET, NULL); } gboolean -gtk_gst_base_widget_init_winsys (GtkGstBaseWidget * base_widget) +gtk_clapper_gl_widget_init_winsys (GtkClapperGLWidget * clapper_widget) { - GtkGstBaseWidgetPrivate *priv = base_widget->priv; + GtkClapperGLWidgetPrivate *priv = clapper_widget->priv; GError *error = NULL; - g_return_val_if_fail (GTK_IS_GST_BASE_WIDGET (base_widget), FALSE); + g_return_val_if_fail (GTK_IS_CLAPPER_GL_WIDGET (clapper_widget), FALSE); g_return_val_if_fail (priv->display != NULL, FALSE); - GTK_GST_BASE_WIDGET_LOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget); if (priv->display && priv->gdk_context && priv->other_context) { GST_TRACE ("have already initialized contexts"); - GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return TRUE; } if (!priv->other_context) { - GTK_GST_BASE_WIDGET_UNLOCK (base_widget); - gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _get_gl_context, base_widget); - GTK_GST_BASE_WIDGET_LOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); + gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _get_gl_context, clapper_widget); + GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget); } if (!GST_IS_GL_CONTEXT (priv->other_context)) { GST_FIXME ("Could not retrieve Gdk OpenGL context"); - GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return FALSE; } @@ -1046,39 +1043,39 @@ gtk_gst_base_widget_init_winsys (GtkGstBaseWidget * base_widget) error ? error->message : "Unknown"); g_clear_error (&error); GST_OBJECT_UNLOCK (priv->display); - GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return FALSE; } gst_gl_display_add_context (priv->display, priv->context); GST_OBJECT_UNLOCK (priv->display); - GTK_GST_BASE_WIDGET_UNLOCK (base_widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); return TRUE; } GstGLContext * -gtk_gst_base_widget_get_gtk_context (GtkGstBaseWidget * base_widget) +gtk_clapper_gl_widget_get_gtk_context (GtkClapperGLWidget * clapper_widget) { - if (!base_widget->priv->other_context) + if (!clapper_widget->priv->other_context) return NULL; - return gst_object_ref (base_widget->priv->other_context); + return gst_object_ref (clapper_widget->priv->other_context); } GstGLContext * -gtk_gst_base_widget_get_context (GtkGstBaseWidget * base_widget) +gtk_clapper_gl_widget_get_context (GtkClapperGLWidget * clapper_widget) { - if (!base_widget->priv->context) + if (!clapper_widget->priv->context) return NULL; - return gst_object_ref (base_widget->priv->context); + return gst_object_ref (clapper_widget->priv->context); } GstGLDisplay * -gtk_gst_base_widget_get_display (GtkGstBaseWidget * base_widget) +gtk_clapper_gl_widget_get_display (GtkClapperGLWidget * clapper_widget) { - if (!base_widget->priv->display) + if (!clapper_widget->priv->display) return NULL; - return gst_object_ref (base_widget->priv->display); + return gst_object_ref (clapper_widget->priv->display); } diff --git a/lib/gst/clapper/gtk4/gtkclapperglwidget.h b/lib/gst/clapper/gtk4/gtkclapperglwidget.h new file mode 100644 index 00000000..34317b5e --- /dev/null +++ b/lib/gst/clapper/gtk4/gtkclapperglwidget.h @@ -0,0 +1,107 @@ +/* + * GStreamer + * Copyright (C) 2015 Matthew Waters + * Copyright (C) 2020 Rafał Dzięgiel + * + * 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_CLAPPER_GL_WIDGET_H__ +#define __GTK_CLAPPER_GL_WIDGET_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +GType gtk_clapper_gl_widget_get_type (void); +#define GTK_TYPE_CLAPPER_GL_WIDGET (gtk_clapper_gl_widget_get_type()) +#define GTK_CLAPPER_GL_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GTK_TYPE_CLAPPER_GL_WIDGET,GtkClapperGLWidget)) +#define GTK_CLAPPER_GL_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GTK_TYPE_CLAPPER_GL_WIDGET,GtkClapperGLWidgetClass)) +#define GTK_IS_CLAPPER_GL_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GTK_TYPE_CLAPPER_GL_WIDGET)) +#define GTK_IS_CLAPPER_GL_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GTK_TYPE_CLAPPER_GL_WIDGET)) +#define GTK_CLAPPER_GL_WIDGET_CAST(obj) ((GtkClapperGLWidget*)(obj)) +#define GTK_CLAPPER_GL_WIDGET_LOCK(w) g_mutex_lock(&((GtkClapperGLWidget*)(w))->lock) +#define GTK_CLAPPER_GL_WIDGET_UNLOCK(w) g_mutex_unlock(&((GtkClapperGLWidget*)(w))->lock) + +typedef struct _GtkClapperGLWidget GtkClapperGLWidget; +typedef struct _GtkClapperGLWidgetClass GtkClapperGLWidgetClass; +typedef struct _GtkClapperGLWidgetPrivate GtkClapperGLWidgetPrivate; + +struct _GtkClapperGLWidget +{ + /* */ + GtkGLArea parent; + GtkClapperGLWidgetPrivate *priv; + + /* properties */ + gboolean force_aspect_ratio; + gint par_n, par_d; + gboolean ignore_textures; + + gint display_width; + gint display_height; + + /* Widget dimensions */ + gint scaled_width; + gint scaled_height; + + gboolean negotiated; + GstBuffer *pending_buffer; + GstBuffer *buffer; + GstVideoInfo v_info; + + /* resize */ + gboolean pending_resize; + GstVideoInfo pending_v_info; + guint display_ratio_num; + guint display_ratio_den; + + /*< private >*/ + GMutex lock; + GWeakRef element; + + /* event controllers */ + GtkEventController *key_controller; + GtkEventController *motion_controller; + GtkGesture *click_gesture; + + /* Pending draw idles callback */ + guint draw_id; +}; + +struct _GtkClapperGLWidgetClass +{ + GtkGLAreaClass parent_class; +}; + +/* API */ +gboolean gtk_clapper_gl_widget_set_format (GtkClapperGLWidget * widget, GstVideoInfo * v_info); +void gtk_clapper_gl_widget_set_buffer (GtkClapperGLWidget * widget, GstBuffer * buffer); +void gtk_clapper_gl_widget_set_element (GtkClapperGLWidget * widget, GstElement * element); + +GtkWidget * gtk_clapper_gl_widget_new (void); + +gboolean gtk_clapper_gl_widget_init_winsys (GtkClapperGLWidget * widget); +GstGLDisplay * gtk_clapper_gl_widget_get_display (GtkClapperGLWidget * widget); +GstGLContext * gtk_clapper_gl_widget_get_context (GtkClapperGLWidget * widget); +GstGLContext * gtk_clapper_gl_widget_get_gtk_context (GtkClapperGLWidget * widget); + +G_END_DECLS + +#endif /* __GTK_CLAPPER_GL_WIDGET_H__ */ diff --git a/lib/gst/clapper/gtk4/gtkgstbasewidget.h b/lib/gst/clapper/gtk4/gtkgstbasewidget.h deleted file mode 100644 index c7a1e6d3..00000000 --- a/lib/gst/clapper/gtk4/gtkgstbasewidget.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters - * Copyright (C) 2020 Rafał Dzięgiel - * - * 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_GST_BASE_WIDGET_H__ -#define __GTK_GST_BASE_WIDGET_H__ - -#include -#include -#include -#include - -G_BEGIN_DECLS - -GType gtk_gst_base_widget_get_type (void); -#define GTK_TYPE_GST_BASE_WIDGET (gtk_gst_base_widget_get_type()) -#define GTK_GST_BASE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GTK_TYPE_GST_BASE_WIDGET,GtkGstBaseWidget)) -#define GTK_GST_BASE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GTK_TYPE_GST_BASE_WIDGET,GtkGstBaseWidgetClass)) -#define GTK_IS_GST_BASE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GTK_TYPE_GST_BASE_WIDGET)) -#define GTK_IS_GST_BASE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GTK_TYPE_GST_BASE_WIDGET)) -#define GTK_GST_BASE_WIDGET_CAST(obj) ((GtkGstBaseWidget*)(obj)) -#define GTK_GST_BASE_WIDGET_LOCK(w) g_mutex_lock(&((GtkGstBaseWidget*)(w))->lock) -#define GTK_GST_BASE_WIDGET_UNLOCK(w) g_mutex_unlock(&((GtkGstBaseWidget*)(w))->lock) - -typedef struct _GtkGstBaseWidget GtkGstBaseWidget; -typedef struct _GtkGstBaseWidgetClass GtkGstBaseWidgetClass; -typedef struct _GtkGstBaseWidgetPrivate GtkGstBaseWidgetPrivate; - -struct _GtkGstBaseWidget -{ - /* */ - GtkGLArea parent; - GtkGstBaseWidgetPrivate *priv; - - /* properties */ - gboolean force_aspect_ratio; - gint par_n, par_d; - gboolean ignore_textures; - - gint display_width; - gint display_height; - - /* Widget dimensions */ - gint scaled_width; - gint scaled_height; - - gboolean negotiated; - GstBuffer *pending_buffer; - GstBuffer *buffer; - GstVideoInfo v_info; - - /* resize */ - gboolean pending_resize; - GstVideoInfo pending_v_info; - guint display_ratio_num; - guint display_ratio_den; - - /*< private >*/ - GMutex lock; - GWeakRef element; - - /* event controllers */ - GtkEventController *key_controller; - GtkEventController *motion_controller; - GtkGesture *click_gesture; - - /* Pending draw idles callback */ - guint draw_id; -}; - -struct _GtkGstBaseWidgetClass -{ - GtkGLAreaClass parent_class; -}; - -/* API */ -gboolean gtk_gst_base_widget_set_format (GtkGstBaseWidget * widget, GstVideoInfo * v_info); -void gtk_gst_base_widget_set_buffer (GtkGstBaseWidget * widget, GstBuffer * buffer); -void gtk_gst_base_widget_set_element (GtkGstBaseWidget * widget, GstElement * element); - -GtkWidget * gtk_gst_base_widget_new (void); - -gboolean gtk_gst_base_widget_init_winsys (GtkGstBaseWidget * widget); -GstGLDisplay * gtk_gst_base_widget_get_display (GtkGstBaseWidget * widget); -GstGLContext * gtk_gst_base_widget_get_context (GtkGstBaseWidget * widget); -GstGLContext * gtk_gst_base_widget_get_gtk_context (GtkGstBaseWidget * widget); - -G_END_DECLS - -#endif /* __GTK_GST_BASE_WIDGET_H__ */ diff --git a/lib/gst/clapper/meson.build b/lib/gst/clapper/meson.build index 4905c102..e4248b53 100644 --- a/lib/gst/clapper/meson.build +++ b/lib/gst/clapper/meson.build @@ -8,9 +8,9 @@ gstclapper_sources = [ 'gstclapper-visualization.c', 'gstclapper-gtk4-plugin.c', - 'gtk4/gstgtkbasesink.c', + 'gtk4/gstclapperglsink.c', 'gtk4/gstgtkutils.c', - 'gtk4/gtkgstbasewidget.c', + 'gtk4/gtkclapperglwidget.c', ] gstclapper_headers = [ 'clapper.h', From 39da52dd6246412f686dcb7076963ae310e1822a Mon Sep 17 00:00:00 2001 From: Rafostar <40623528+Rafostar@users.noreply.github.com> Date: Sat, 6 Mar 2021 19:16:28 +0100 Subject: [PATCH 09/10] Sink: unlock widget before setting queue Let GTK handle setting queue resize/render on the widget. We are not accessing widget values at this time, so it can be unlocked. It will be locked back during the render. --- lib/gst/clapper/gtk4/gtkclapperglwidget.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/gst/clapper/gtk4/gtkclapperglwidget.c b/lib/gst/clapper/gtk4/gtkclapperglwidget.c index 108f555e..fc7e5feb 100644 --- a/lib/gst/clapper/gtk4/gtkclapperglwidget.c +++ b/lib/gst/clapper/gtk4/gtkclapperglwidget.c @@ -293,13 +293,15 @@ _queue_draw (GtkClapperGLWidget * clapper_widget) _apply_par (clapper_widget); + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); + gtk_widget_queue_resize (GTK_WIDGET (clapper_widget)); } else { + GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); + gtk_gl_area_queue_render (GTK_GL_AREA (clapper_widget)); } - GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget); - return G_SOURCE_REMOVE; } From 0cd82b1b8a6702168648362c2024c4cf566a7660 Mon Sep 17 00:00:00 2001 From: Rafostar <40623528+Rafostar@users.noreply.github.com> Date: Sat, 6 Mar 2021 22:09:27 +0100 Subject: [PATCH 10/10] API: remove video sink plugin selection Clapper only has and supports one video sink. I would rather replace it than forcing support for multiple plugins. --- lib/gst/clapper/gstclapper-gtk4-plugin.c | 26 ++---------------------- lib/gst/clapper/gstclapper-gtk4-plugin.h | 16 +-------------- 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/lib/gst/clapper/gstclapper-gtk4-plugin.c b/lib/gst/clapper/gstclapper-gtk4-plugin.c index 8fc50c3b..18c14375 100644 --- a/lib/gst/clapper/gstclapper-gtk4-plugin.c +++ b/lib/gst/clapper/gstclapper-gtk4-plugin.c @@ -77,9 +77,7 @@ gst_clapper_gtk4_plugin_constructed (GObject * object) { GstClapperGtk4Plugin *self = GST_CLAPPER_GTK4_PLUGIN (object); - if (!self->video_sink) - self->video_sink = g_object_new (GST_TYPE_CLAPPER_GL_SINK, NULL); - + self->video_sink = g_object_new (GST_TYPE_CLAPPER_GL_SINK, NULL); gst_object_ref_sink (self->video_sink); G_OBJECT_CLASS (parent_class)->constructed (object); @@ -111,35 +109,15 @@ gst_clapper_gtk4_plugin_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } -#define C_ENUM(v) ((gint) v) - -GType -gst_clapper_gtk4_plugin_type_get_type (void) -{ - static gsize id = 0; - static const GEnumValue values[] = { - {C_ENUM (GST_CLAPPER_GTK4_PLUGIN_TYPE_GLAREA), "GST_CLAPPER_GTK4_PLUGIN_TYPE_GLAREA", "glarea"}, - {0, NULL, NULL} - }; - - if (g_once_init_enter (&id)) { - GType tmp = g_enum_register_static ("GstClapperGtk4PluginType", values); - g_once_init_leave (&id, tmp); - } - - return (GType) id; -} - /** * gst_clapper_gtk4_plugin_new: - * @plugin_type: (allow-none): Requested GstClapperGtk4PluginType * * Creates a new GTK4 plugin. * * Returns: (transfer full): the new GstClapperGtk4Plugin */ GstClapperGtk4Plugin * -gst_clapper_gtk4_plugin_new (G_GNUC_UNUSED const GstClapperGtk4PluginType plugin_type) +gst_clapper_gtk4_plugin_new (void) { return g_object_new (GST_TYPE_CLAPPER_GTK4_PLUGIN, NULL); } diff --git a/lib/gst/clapper/gstclapper-gtk4-plugin.h b/lib/gst/clapper/gstclapper-gtk4-plugin.h index a729d9f6..448045dc 100644 --- a/lib/gst/clapper/gstclapper-gtk4-plugin.h +++ b/lib/gst/clapper/gstclapper-gtk4-plugin.h @@ -26,20 +26,6 @@ G_BEGIN_DECLS -/* PluginType */ -GST_CLAPPER_API -GType gst_clapper_gtk4_plugin_type_get_type (void); -#define GST_TYPE_CLAPPER_GTK4_PLUGIN_TYPE (gst_clapper_gtk4_plugin_type_get_type ()) - -/** - * GstClapperGtk4PluginType: - * @GST_CLAPPER_GTK4_PLUGIN_TYPE_GLAREA: GTK4 GLArea sink. - */ -typedef enum -{ - GST_CLAPPER_GTK4_PLUGIN_TYPE_GLAREA, -} GstClapperGtk4PluginType; - #define GST_TYPE_CLAPPER_GTK4_PLUGIN (gst_clapper_gtk4_plugin_get_type ()) #define GST_IS_CLAPPER_GTK4_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_GTK4_PLUGIN)) #define GST_IS_CLAPPER_GTK4_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_GTK4_PLUGIN)) @@ -79,7 +65,7 @@ GST_CLAPPER_API GType gst_clapper_gtk4_plugin_get_type (void); GST_CLAPPER_API -GstClapperGtk4Plugin * gst_clapper_gtk4_plugin_new (const GstClapperGtk4PluginType plugin_type); +GstClapperGtk4Plugin * gst_clapper_gtk4_plugin_new (void); G_END_DECLS