From 13ae5cb2f5dd316665eeca716c86c1fdf38272fa Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Thu, 16 Jul 2015 14:30:42 -0400 Subject: [PATCH] gtkglsink: Port to GtkGstBaseWidget https://bugzilla.gnome.org/show_bug.cgi?id=752441 --- ext/gtk/gstgtkglsink.c | 38 +++- ext/gtk/gstgtkglsink.h | 2 +- ext/gtk/gtkgstglwidget.c | 581 +++++++++++++---------------------------------- ext/gtk/gtkgstglwidget.h | 8 +- 4 files changed, 183 insertions(+), 446 deletions(-) diff --git a/ext/gtk/gstgtkglsink.c b/ext/gtk/gstgtkglsink.c index cbb0e94..8d380c3 100644 --- a/ext/gtk/gstgtkglsink.c +++ b/ext/gtk/gstgtkglsink.c @@ -169,7 +169,7 @@ widget_destroy_cb (GtkWidget * widget, GstGtkGLSink * gtk_sink) GST_OBJECT_UNLOCK (gtk_sink); } -static GtkGstGLWidget * +static GtkGstBaseWidget * gst_gtk_gl_sink_get_widget (GstGtkGLSink * gtk_sink) { if (gtk_sink->widget != NULL) @@ -182,7 +182,7 @@ gst_gtk_gl_sink_get_widget (GstGtkGLSink * gtk_sink) return NULL; } - gtk_sink->widget = (GtkGstGLWidget *) gtk_gst_gl_widget_new (); + gtk_sink->widget = (GtkGstBaseWidget *) gtk_gst_gl_widget_new (); gtk_sink->bind_force_aspect_ratio = g_object_bind_property (gtk_sink, "force-aspect-ratio", gtk_sink->widget, "force-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); @@ -323,13 +323,16 @@ gst_gtk_gl_sink_change_state (GstElement * element, GstStateChange transition) gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: + case GST_STATE_CHANGE_NULL_TO_READY:{ + GtkGstGLWidget *gst_widget; + if (gst_gtk_gl_sink_get_widget (gtk_sink) == NULL) return GST_STATE_CHANGE_FAILURE; /* After this point, gtk_sink->widget will always be set */ + gst_widget = GTK_GST_GL_WIDGET (gtk_sink->widget); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (gtk_sink->widget)); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (gst_widget)); if (!gtk_widget_is_toplevel (toplevel)) { GtkWidget *window; @@ -342,17 +345,17 @@ gst_gtk_gl_sink_change_state (GstElement * element, GstStateChange transition) gtk_widget_show_all (window); } - if (!gtk_gst_gl_widget_init_winsys (gtk_sink->widget)) + if (!gtk_gst_gl_widget_init_winsys (gst_widget)) return GST_STATE_CHANGE_FAILURE; - gtk_sink->display = gtk_gst_gl_widget_get_display (gtk_sink->widget); - gtk_sink->context = gtk_gst_gl_widget_get_context (gtk_sink->widget); - gtk_sink->gtk_context = - gtk_gst_gl_widget_get_gtk_context (gtk_sink->widget); + gtk_sink->display = gtk_gst_gl_widget_get_display (gst_widget); + gtk_sink->context = gtk_gst_gl_widget_get_context (gst_widget); + gtk_sink->gtk_context = gtk_gst_gl_widget_get_gtk_context (gst_widget); if (!gtk_sink->display || !gtk_sink->context || !gtk_sink->gtk_context) return GST_STATE_CHANGE_FAILURE; break; + } case GST_STATE_CHANGE_READY_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: @@ -371,7 +374,7 @@ gst_gtk_gl_sink_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PAUSED_TO_READY: GST_OBJECT_LOCK (gtk_sink); if (gtk_sink->widget) - gtk_gst_gl_widget_set_buffer (gtk_sink->widget, NULL); + gtk_gst_base_widget_set_buffer (gtk_sink->widget, NULL); GST_OBJECT_UNLOCK (gtk_sink); break; case GST_STATE_CHANGE_READY_TO_NULL: @@ -430,9 +433,20 @@ gst_gtk_gl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) if (!gst_video_info_from_caps (>k_sink->v_info, caps)) return FALSE; - if (!gtk_gst_gl_widget_set_caps (gtk_sink->widget, caps)) + GST_OBJECT_LOCK (gtk_sink); + + if (gtk_sink->widget == NULL) { + GST_OBJECT_UNLOCK (gtk_sink); + GST_ELEMENT_ERROR (gtk_sink, RESOURCE, NOT_FOUND, + ("%s", "Output widget was destroyed"), (NULL)); + return FALSE; + } + + if (!gtk_gst_base_widget_set_caps (gtk_sink->widget, caps)) return FALSE; + GST_OBJECT_UNLOCK (gtk_sink); + return TRUE; } @@ -454,7 +468,7 @@ gst_gtk_gl_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) return GST_FLOW_ERROR; } - gtk_gst_gl_widget_set_buffer (gtk_sink->widget, buf); + gtk_gst_base_widget_set_buffer (gtk_sink->widget, buf); GST_OBJECT_UNLOCK (vsink); diff --git a/ext/gtk/gstgtkglsink.h b/ext/gtk/gstgtkglsink.h index 985486f..fdc6272 100644 --- a/ext/gtk/gstgtkglsink.h +++ b/ext/gtk/gstgtkglsink.h @@ -52,7 +52,7 @@ struct _GstGtkGLSink /* */ GstVideoSink parent; - GtkGstGLWidget *widget; + GtkGstBaseWidget *widget; GstVideoInfo v_info; GstBufferPool *pool; diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c index 67993f2..b721984 100644 --- a/ext/gtk/gtkgstglwidget.c +++ b/ext/gtk/gtkgstglwidget.c @@ -56,35 +56,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkGstGLWidget, gtk_gst_gl_widget, GTK_TYPE_GL_AREA, #define GTK_GST_GL_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ GTK_TYPE_GST_GL_WIDGET, GtkGstGLWidgetPrivate)) -#define DEFAULT_FORCE_ASPECT_RATIO TRUE -#define DEFAULT_PAR_N 0 -#define DEFAULT_PAR_D 1 -#define DEFAULT_IGNORE_ALPHA TRUE - -enum -{ - PROP_0, - PROP_FORCE_ASPECT_RATIO, - PROP_PIXEL_ASPECT_RATIO, - PROP_IGNORE_ALPHA, -}; - struct _GtkGstGLWidgetPrivate { - GMutex lock; - /* properties */ - gboolean force_aspect_ratio; - gint par_n, par_d; - gboolean ignore_alpha; - - gint display_width; - gint display_height; - - gboolean negotiated; - GstBuffer *buffer; - GstCaps *caps; - GstVideoInfo v_info; gboolean new_buffer; gboolean initted; @@ -99,44 +73,8 @@ struct _GtkGstGLWidgetPrivate GLint attr_position; GLint attr_texture; GLuint current_tex; - - /* Pending queued idles callback */ - guint draw_id; - guint resize_id; }; -static void -gtk_gst_gl_widget_get_preferred_width (GtkWidget * widget, gint * min, - gint * natural) -{ - GtkGstGLWidget *gst_widget = (GtkGstGLWidget *) widget; - gint video_width = gst_widget->priv->display_width; - - if (!gst_widget->priv->negotiated) - video_width = 10; - - if (min) - *min = 1; - if (natural) - *natural = video_width; -} - -static void -gtk_gst_gl_widget_get_preferred_height (GtkWidget * widget, gint * min, - gint * natural) -{ - GtkGstGLWidget *gst_widget = (GtkGstGLWidget *) widget; - gint video_height = gst_widget->priv->display_height; - - if (!gst_widget->priv->negotiated) - video_height = 10; - - if (min) - *min = 1; - if (natural) - *natural = video_height; -} - static const GLfloat vertices[] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, @@ -147,51 +85,53 @@ static const GLfloat vertices[] = { static void gtk_gst_gl_widget_bind_buffer (GtkGstGLWidget * gst_widget) { - const GstGLFuncs *gl = gst_widget->priv->context->gl_vtable; + GtkGstGLWidgetPrivate *priv = gst_widget->priv; + const GstGLFuncs *gl = priv->context->gl_vtable; - gl->BindBuffer (GL_ARRAY_BUFFER, gst_widget->priv->vertex_buffer); + gl->BindBuffer (GL_ARRAY_BUFFER, priv->vertex_buffer); /* Load the vertex position */ - gl->VertexAttribPointer (gst_widget->priv->attr_position, 3, GL_FLOAT, - GL_FALSE, 5 * sizeof (GLfloat), (void *) 0); + gl->VertexAttribPointer (priv->attr_position, 3, GL_FLOAT, GL_FALSE, + 5 * sizeof (GLfloat), (void *) 0); /* Load the texture coordinate */ - gl->VertexAttribPointer (gst_widget->priv->attr_texture, 2, GL_FLOAT, - GL_FALSE, 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); + gl->VertexAttribPointer (priv->attr_texture, 2, GL_FLOAT, GL_FALSE, + 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); - gl->EnableVertexAttribArray (gst_widget->priv->attr_position); - gl->EnableVertexAttribArray (gst_widget->priv->attr_texture); + gl->EnableVertexAttribArray (priv->attr_position); + gl->EnableVertexAttribArray (priv->attr_texture); } static void gtk_gst_gl_widget_unbind_buffer (GtkGstGLWidget * gst_widget) { - const GstGLFuncs *gl = gst_widget->priv->context->gl_vtable; + GtkGstGLWidgetPrivate *priv = gst_widget->priv; + const GstGLFuncs *gl = priv->context->gl_vtable; gl->BindBuffer (GL_ARRAY_BUFFER, 0); - gl->DisableVertexAttribArray (gst_widget->priv->attr_position); - gl->DisableVertexAttribArray (gst_widget->priv->attr_texture); + gl->DisableVertexAttribArray (priv->attr_position); + gl->DisableVertexAttribArray (priv->attr_texture); } static void gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget) { - const GstGLFuncs *gl = gst_widget->priv->context->gl_vtable; + GtkGstGLWidgetPrivate *priv = gst_widget->priv; + const GstGLFuncs *gl = priv->context->gl_vtable; - gst_widget->priv->shader = gst_gl_shader_new (gst_widget->priv->context); + priv->shader = gst_gl_shader_new (priv->context); - gst_gl_shader_compile_with_default_vf_and_check - (gst_widget->priv->shader, &gst_widget->priv->attr_position, - &gst_widget->priv->attr_texture); + gst_gl_shader_compile_with_default_vf_and_check (priv->shader, + &priv->attr_position, &priv->attr_texture); if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &gst_widget->priv->vao); - gl->BindVertexArray (gst_widget->priv->vao); + gl->GenVertexArrays (1, &priv->vao); + gl->BindVertexArray (priv->vao); } - gl->GenBuffers (1, &gst_widget->priv->vertex_buffer); - gl->BindBuffer (GL_ARRAY_BUFFER, gst_widget->priv->vertex_buffer); + 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); @@ -202,16 +142,17 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget) gl->BindBuffer (GL_ARRAY_BUFFER, 0); - gst_widget->priv->initted = TRUE; + priv->initted = TRUE; } static void _redraw_texture (GtkGstGLWidget * gst_widget, guint tex) { - const GstGLFuncs *gl = gst_widget->priv->context->gl_vtable; + GtkGstGLWidgetPrivate *priv = gst_widget->priv; + const GstGLFuncs *gl = priv->context->gl_vtable; const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; - if (gst_widget->priv->force_aspect_ratio) { + if (gst_widget->base.force_aspect_ratio) { GstVideoRectangle src, dst, result; gint widget_width, widget_height, widget_scale; @@ -224,8 +165,8 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex) src.x = 0; src.y = 0; - src.w = gst_widget->priv->display_width; - src.h = gst_widget->priv->display_height; + src.w = gst_widget->base.display_width; + src.h = gst_widget->base.display_height; dst.x = 0; dst.y = 0; @@ -237,16 +178,16 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex) gl->Viewport (result.x, result.y, result.w, result.h); } - gst_gl_shader_use (gst_widget->priv->shader); + gst_gl_shader_use (priv->shader); if (gl->BindVertexArray) - gl->BindVertexArray (gst_widget->priv->vao); + gl->BindVertexArray (priv->vao); else gtk_gst_gl_widget_bind_buffer (gst_widget); gl->ActiveTexture (GL_TEXTURE0); gl->BindTexture (GL_TEXTURE_2D, tex); - gst_gl_shader_set_uniform_1i (gst_widget->priv->shader, "tex", 0); + gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0); gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); @@ -261,42 +202,42 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex) static gboolean gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) { - GtkGstGLWidget *gst_widget = (GtkGstGLWidget *) widget; + GtkGstGLWidgetPrivate *priv = GTK_GST_GL_WIDGET (widget)->priv; + GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget); - g_mutex_lock (&gst_widget->priv->lock); + GTK_GST_BASE_WIDGET_LOCK (widget); - if (!gst_widget->priv->initted && gst_widget->priv->context) - gtk_gst_gl_widget_init_redisplay (gst_widget); + if (!priv->initted && priv->context) + gtk_gst_gl_widget_init_redisplay (GTK_GST_GL_WIDGET (widget)); - if (gst_widget->priv->initted && gst_widget->priv->negotiated - && gst_widget->priv->buffer) { + if (priv->initted && base_widget->negotiated && base_widget->buffer) { GST_DEBUG ("rendering buffer %p with gdk context %p", - gst_widget->priv->buffer, context); + base_widget->buffer, context); - gst_gl_context_activate (gst_widget->priv->other_context, TRUE); + gst_gl_context_activate (priv->other_context, TRUE); - if (gst_widget->priv->new_buffer || gst_widget->priv->current_tex == 0) { + if (base_widget->new_buffer || priv->current_tex == 0) { GstVideoFrame gl_frame; GstGLSyncMeta *sync_meta; - if (!gst_video_frame_map (&gl_frame, &gst_widget->priv->v_info, - gst_widget->priv->buffer, GST_MAP_READ | GST_MAP_GL)) { + if (!gst_video_frame_map (&gl_frame, &base_widget->v_info, + base_widget->buffer, GST_MAP_READ | GST_MAP_GL)) { goto error; } - sync_meta = gst_buffer_get_gl_sync_meta (gst_widget->priv->buffer); + sync_meta = gst_buffer_get_gl_sync_meta (base_widget->buffer); if (sync_meta) { - gst_gl_sync_meta_set_sync_point (sync_meta, gst_widget->priv->context); - gst_gl_sync_meta_wait (sync_meta, gst_widget->priv->other_context); + gst_gl_sync_meta_set_sync_point (sync_meta, priv->context); + gst_gl_sync_meta_wait (sync_meta, priv->other_context); } - gst_widget->priv->current_tex = *(guint *) gl_frame.data[0]; + priv->current_tex = *(guint *) gl_frame.data[0]; gst_video_frame_unmap (&gl_frame); } - _redraw_texture (gst_widget, gst_widget->priv->current_tex); - gst_widget->priv->new_buffer = FALSE; + _redraw_texture (GTK_GST_GL_WIDGET (widget), priv->current_tex); + base_widget->new_buffer = FALSE; } else { error: /* FIXME: nothing to display */ @@ -304,10 +245,10 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) glClear (GL_COLOR_BUFFER_BIT); } - if (gst_widget->priv->other_context) - gst_gl_context_activate (gst_widget->priv->other_context, FALSE); + if (priv->other_context) + gst_gl_context_activate (priv->other_context, FALSE); - g_mutex_unlock (&gst_widget->priv->lock); + GTK_GST_BASE_WIDGET_UNLOCK (widget); return FALSE; } @@ -360,196 +301,117 @@ _invoke_on_main (ThreadFunc func, gpointer data) static void _reset_gl (GtkGstGLWidget * gst_widget) { - const GstGLFuncs *gl = gst_widget->priv->other_context->gl_vtable; + GtkGstGLWidgetPrivate *priv = gst_widget->priv; + const GstGLFuncs *gl = priv->other_context->gl_vtable; - if (!gst_widget->priv->gdk_context) - gst_widget->priv->gdk_context = - gtk_gl_area_get_context (GTK_GL_AREA (gst_widget)); - if (gst_widget->priv->gdk_context == NULL) + 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 (gst_widget->priv->gdk_context); - gst_gl_context_activate (gst_widget->priv->other_context, TRUE); + gdk_gl_context_make_current (priv->gdk_context); + gst_gl_context_activate (priv->other_context, TRUE); - if (gst_widget->priv->vao) { - gl->DeleteVertexArrays (1, &gst_widget->priv->vao); - gst_widget->priv->vao = 0; + if (priv->vao) { + gl->DeleteVertexArrays (1, &priv->vao); + priv->vao = 0; } - if (gst_widget->priv->vertex_buffer) { - gl->DeleteBuffers (1, &gst_widget->priv->vertex_buffer); - gst_widget->priv->vertex_buffer = 0; + if (priv->vertex_buffer) { + gl->DeleteBuffers (1, &priv->vertex_buffer); + priv->vertex_buffer = 0; } - if (gst_widget->priv->upload) { - gst_object_unref (gst_widget->priv->upload); - gst_widget->priv->upload = NULL; + if (priv->upload) { + gst_object_unref (priv->upload); + priv->upload = NULL; } - if (gst_widget->priv->shader) { - gst_object_unref (gst_widget->priv->shader); - gst_widget->priv->shader = NULL; + if (priv->shader) { + gst_object_unref (priv->shader); + priv->shader = NULL; } - gst_gl_context_activate (gst_widget->priv->other_context, FALSE); + gst_gl_context_activate (priv->other_context, FALSE); - gst_object_unref (gst_widget->priv->other_context); - gst_widget->priv->other_context = NULL; + gst_object_unref (priv->other_context); + priv->other_context = NULL; gdk_gl_context_clear_current (); - g_object_unref (gst_widget->priv->gdk_context); - gst_widget->priv->gdk_context = NULL; + g_object_unref (priv->gdk_context); + priv->gdk_context = NULL; } static void -_reset (GtkGstGLWidget * gst_widget) +_reset (GtkGstBaseWidget * base_widget) { - gst_buffer_replace (&gst_widget->priv->buffer, NULL); - - gst_caps_replace (&gst_widget->priv->caps, NULL); - - gst_widget->priv->negotiated = FALSE; - gst_widget->priv->initted = FALSE; - gst_widget->priv->vao = 0; - gst_widget->priv->vertex_buffer = 0; - gst_widget->priv->attr_position = 0; - gst_widget->priv->attr_texture = 0; - gst_widget->priv->current_tex = 0; - gst_widget->priv->new_buffer = TRUE; + GtkGstGLWidgetPrivate *priv = GTK_GST_GL_WIDGET (base_widget)->priv; + + priv->initted = FALSE; + priv->vao = 0; + priv->vertex_buffer = 0; + priv->attr_position = 0; + priv->attr_texture = 0; + priv->current_tex = 0; + + gtk_gl_area_set_has_alpha (GTK_GL_AREA (base_widget), + !base_widget->ignore_alpha); } static void gtk_gst_gl_widget_finalize (GObject * object) { - GtkGstGLWidget *widget = GTK_GST_GL_WIDGET_CAST (object); - - g_mutex_clear (&widget->priv->lock); - - _reset (widget); - - if (widget->priv->other_context) { - _invoke_on_main ((ThreadFunc) _reset_gl, widget); - } + GtkGstGLWidgetPrivate *priv = GTK_GST_GL_WIDGET (object)->priv; + GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (object); - if (widget->priv->context) - gst_object_unref (widget->priv->context); + _reset (base_widget); - if (widget->priv->display) - gst_object_unref (widget->priv->display); + if (priv->other_context) + _invoke_on_main ((ThreadFunc) _reset_gl, base_widget); - if (widget->priv->draw_id) - g_source_remove (widget->priv->draw_id); + if (priv->context) + gst_object_unref (priv->context); - if (widget->priv->resize_id) - g_source_remove (widget->priv->resize_id); + 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_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GtkGstGLWidget *gtk_widget = GTK_GST_GL_WIDGET (object); - - switch (prop_id) { - case PROP_FORCE_ASPECT_RATIO: - gtk_widget->priv->force_aspect_ratio = g_value_get_boolean (value); - break; - case PROP_PIXEL_ASPECT_RATIO: - gtk_widget->priv->par_n = gst_value_get_fraction_numerator (value); - gtk_widget->priv->par_d = gst_value_get_fraction_denominator (value); - break; - case PROP_IGNORE_ALPHA: - gtk_widget->priv->ignore_alpha = g_value_get_boolean (value); - gtk_gl_area_set_has_alpha ((GtkGLArea *) gtk_widget, - !gtk_widget->priv->ignore_alpha); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtk_gst_gl_widget_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GtkGstGLWidget *gtk_widget = GTK_GST_GL_WIDGET (object); - - switch (prop_id) { - case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean (value, gtk_widget->priv->force_aspect_ratio); - break; - case PROP_PIXEL_ASPECT_RATIO: - gst_value_set_fraction (value, gtk_widget->priv->par_n, - gtk_widget->priv->par_d); - break; - case PROP_IGNORE_ALPHA: - g_value_set_boolean (value, gtk_widget->priv->ignore_alpha); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void gtk_gst_gl_widget_class_init (GtkGstGLWidgetClass * klass) { GObjectClass *gobject_klass = (GObjectClass *) klass; - GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass; GtkGLAreaClass *gl_widget_klass = (GtkGLAreaClass *) klass; + GtkGstBaseWidget *base_widget_klass = (GtkGstBaseWidget *) klass; g_type_class_add_private (klass, sizeof (GtkGstGLWidgetPrivate)); + gtk_gst_base_widget_class_init (GTK_GST_BASE_WIDGET_CLASS (klass)); - gobject_klass->set_property = gtk_gst_gl_widget_set_property; - gobject_klass->get_property = gtk_gst_gl_widget_get_property; gobject_klass->finalize = gtk_gst_gl_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_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)); - gl_widget_klass->render = gtk_gst_gl_widget_render; - - widget_klass->get_preferred_width = gtk_gst_gl_widget_get_preferred_width; - widget_klass->get_preferred_height = gtk_gst_gl_widget_get_preferred_height; + base_widget_klass->reset = _reset; } static void -gtk_gst_gl_widget_init (GtkGstGLWidget * widget) +gtk_gst_gl_widget_init (GtkGstGLWidget * gst_widget) { + GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (gst_widget); GdkDisplay *display; + GtkGstGLWidgetPrivate *priv; - widget->priv = GTK_GST_GL_WIDGET_GET_PRIVATE (widget); - - widget->priv->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; - widget->priv->par_n = DEFAULT_PAR_N; - widget->priv->par_d = DEFAULT_PAR_D; - widget->priv->ignore_alpha = DEFAULT_IGNORE_ALPHA; + gtk_gst_base_widget_init (base_widget); - g_mutex_init (&widget->priv->lock); + gst_widget->priv = priv = GTK_GST_GL_WIDGET_GET_PRIVATE (gst_widget); display = gdk_display_get_default (); #if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11) if (GDK_IS_X11_DISPLAY (display)) - widget->priv->display = (GstGLDisplay *) + priv->display = (GstGLDisplay *) gst_gl_display_x11_new_with_display (gdk_x11_display_get_xdisplay (display)); #endif @@ -557,97 +419,63 @@ gtk_gst_gl_widget_init (GtkGstGLWidget * widget) if (GDK_IS_WAYLAND_DISPLAY (display)) { struct wl_display *wayland_display = gdk_wayland_display_get_wl_display (display); - widget->priv->display = (GstGLDisplay *) + priv->display = (GstGLDisplay *) gst_gl_display_wayland_new_with_display (wayland_display); } #endif (void) display; - if (!widget->priv->display) - widget->priv->display = gst_gl_display_new (); - - gtk_gl_area_set_has_alpha ((GtkGLArea *) widget, !widget->priv->ignore_alpha); -} - -GtkWidget * -gtk_gst_gl_widget_new (void) -{ - return (GtkWidget *) g_object_new (GTK_TYPE_GST_GL_WIDGET, NULL); -} - -static gboolean -_queue_draw (GtkGstGLWidget * widget) -{ - g_mutex_lock (&widget->priv->lock); - widget->priv->draw_id = 0; - g_mutex_unlock (&widget->priv->lock); - - gtk_widget_queue_draw (GTK_WIDGET (widget)); + if (!priv->display) + priv->display = gst_gl_display_new (); - return G_SOURCE_REMOVE; + gtk_gl_area_set_has_alpha (GTK_GL_AREA (gst_widget), + !base_widget->ignore_alpha); } -void -gtk_gst_gl_widget_set_buffer (GtkGstGLWidget * widget, GstBuffer * buffer) -{ - g_return_if_fail (GTK_IS_GST_GL_WIDGET (widget)); - g_return_if_fail (buffer == NULL || widget->priv->negotiated); - - g_mutex_lock (&widget->priv->lock); - - gst_buffer_replace (&widget->priv->buffer, buffer); - widget->priv->new_buffer = TRUE; - - if (!widget->priv->draw_id) { - widget->priv->draw_id = g_idle_add_full (G_PRIORITY_DEFAULT, - (GSourceFunc) _queue_draw, widget, NULL); - } - g_mutex_unlock (&widget->priv->lock); -} static void _get_gl_context (GtkGstGLWidget * gst_widget) { + GtkGstGLWidgetPrivate *priv = gst_widget->priv; GstGLPlatform platform; GstGLAPI gl_api; guintptr gl_handle; gtk_widget_realize (GTK_WIDGET (gst_widget)); - if (gst_widget->priv->gdk_context) - g_object_unref (gst_widget->priv->gdk_context); - gst_widget->priv->gdk_context = - gtk_gl_area_get_context (GTK_GL_AREA (gst_widget)); - if (gst_widget->priv->gdk_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) { g_assert_not_reached (); return; } - g_object_ref (gst_widget->priv->gdk_context); + g_object_ref (priv->gdk_context); - gdk_gl_context_make_current (gst_widget->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 (gst_widget->priv->display)) { + if (GST_IS_GL_DISPLAY_X11 (priv->display)) { platform = GST_GL_PLATFORM_GLX; gl_api = gst_gl_context_get_current_gl_api (NULL, NULL); gl_handle = gst_gl_context_get_current_gl_context (platform); if (gl_handle) - gst_widget->priv->other_context = - gst_gl_context_new_wrapped (gst_widget->priv->display, gl_handle, + priv->other_context = + gst_gl_context_new_wrapped (priv->display, gl_handle, platform, gl_api); } #endif #if GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND) - if (GST_IS_GL_DISPLAY_WAYLAND (gst_widget->priv->display)) { + if (GST_IS_GL_DISPLAY_WAYLAND (priv->display)) { platform = GST_GL_PLATFORM_EGL; gl_api = gst_gl_context_get_current_gl_api (NULL, NULL); gl_handle = gst_gl_context_get_current_gl_context (platform); if (gl_handle) - gst_widget->priv->other_context = - gst_gl_context_new_wrapped (gst_widget->priv->display, gl_handle, + priv->other_context = + gst_gl_context_new_wrapped (priv->display, gl_handle, platform, gl_api); } #endif @@ -656,166 +484,61 @@ _get_gl_context (GtkGstGLWidget * gst_widget) (void) gl_api; (void) gl_handle; - if (gst_widget->priv->other_context) { + if (priv->other_context) { GError *error = NULL; - gst_gl_context_activate (gst_widget->priv->other_context, TRUE); - if (!gst_gl_context_fill_info (gst_widget->priv->other_context, &error)) { + gst_gl_context_activate (priv->other_context, TRUE); + if (!gst_gl_context_fill_info (priv->other_context, &error)) { GST_ERROR ("failed to retreive gdk context info: %s", error->message); - g_object_unref (gst_widget->priv->other_context); - gst_widget->priv->other_context = NULL; + g_object_unref (priv->other_context); + priv->other_context = NULL; } else { - gst_gl_context_activate (gst_widget->priv->other_context, FALSE); + gst_gl_context_activate (priv->other_context, FALSE); } } } -static gboolean -_queue_resize (GtkGstGLWidget * widget) +GtkWidget * +gtk_gst_gl_widget_new (void) { - g_mutex_lock (&widget->priv->lock); - widget->priv->resize_id = 0; - g_mutex_unlock (&widget->priv->lock); - - gtk_widget_queue_resize (GTK_WIDGET (widget)); - - return G_SOURCE_REMOVE; + return (GtkWidget *) g_object_new (GTK_TYPE_GST_GL_WIDGET, NULL); } gboolean -gtk_gst_gl_widget_init_winsys (GtkGstGLWidget * widget) +gtk_gst_gl_widget_init_winsys (GtkGstGLWidget * gst_widget) { - g_return_val_if_fail (GTK_IS_GST_GL_WIDGET (widget), FALSE); + GtkGstGLWidgetPrivate *priv = gst_widget->priv; + + g_return_val_if_fail (GTK_IS_GST_GL_WIDGET (gst_widget), FALSE); - g_mutex_lock (&widget->priv->lock); + GTK_GST_BASE_WIDGET_LOCK (gst_widget); - if (widget->priv->display && widget->priv->gdk_context - && widget->priv->other_context) { - g_mutex_unlock (&widget->priv->lock); + if (priv->display && priv->gdk_context && priv->other_context) { + GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); return TRUE; } - if (!widget->priv->other_context) { - g_mutex_unlock (&widget->priv->lock); - _invoke_on_main ((ThreadFunc) _get_gl_context, widget); - g_mutex_lock (&widget->priv->lock); + if (!priv->other_context) { + GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); + _invoke_on_main ((ThreadFunc) _get_gl_context, gst_widget); + GTK_GST_BASE_WIDGET_LOCK (gst_widget); } - if (!GST_GL_IS_CONTEXT (widget->priv->other_context)) { - g_mutex_unlock (&widget->priv->lock); + if (!GST_GL_IS_CONTEXT (priv->other_context)) { + GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); return FALSE; } - widget->priv->context = gst_gl_context_new (widget->priv->display); + priv->context = gst_gl_context_new (priv->display); - if (!widget->priv->context) { - g_mutex_unlock (&widget->priv->lock); + if (!priv->context) { + GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); return FALSE; } - gst_gl_context_create (widget->priv->context, widget->priv->other_context, - NULL); - - g_mutex_unlock (&widget->priv->lock); - return TRUE; -} - -static gboolean -_calculate_par (GtkGstGLWidget * widget, GstVideoInfo * info) -{ - gboolean ok; - gint width, height; - gint par_n, par_d; - gint display_par_n, display_par_d; - guint display_ratio_num, display_ratio_den; - - width = GST_VIDEO_INFO_WIDTH (info); - height = GST_VIDEO_INFO_HEIGHT (info); - - par_n = GST_VIDEO_INFO_PAR_N (info); - par_d = GST_VIDEO_INFO_PAR_D (info); - - if (!par_n) - par_n = 1; - - /* get display's PAR */ - if (widget->priv->par_n != 0 && widget->priv->par_d != 0) { - display_par_n = widget->priv->par_n; - display_par_d = widget->priv->par_d; - } else { - display_par_n = 1; - display_par_d = 1; - } - - ok = gst_video_calculate_display_ratio (&display_ratio_num, - &display_ratio_den, width, height, par_n, par_d, display_par_n, - display_par_d); - - if (!ok) - return FALSE; - - GST_LOG ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n, display_par_d); - - if (height % display_ratio_den == 0) { - GST_DEBUG ("keeping video height"); - widget->priv->display_width = (guint) - gst_util_uint64_scale_int (height, display_ratio_num, - display_ratio_den); - widget->priv->display_height = height; - } else if (width % display_ratio_num == 0) { - GST_DEBUG ("keeping video width"); - widget->priv->display_width = width; - widget->priv->display_height = (guint) - gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num); - } else { - GST_DEBUG ("approximating while keeping video height"); - widget->priv->display_width = (guint) - gst_util_uint64_scale_int (height, display_ratio_num, - display_ratio_den); - widget->priv->display_height = height; - } - GST_DEBUG ("scaling to %dx%d", widget->priv->display_width, - widget->priv->display_height); - - return TRUE; -} - -gboolean -gtk_gst_gl_widget_set_caps (GtkGstGLWidget * widget, GstCaps * caps) -{ - GstVideoInfo v_info; - - g_return_val_if_fail (GTK_IS_GST_GL_WIDGET (widget), FALSE); - g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); - g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); - - if (widget->priv->caps && gst_caps_is_equal_fixed (widget->priv->caps, caps)) - return TRUE; - - if (!gst_video_info_from_caps (&v_info, caps)) - return FALSE; - - g_mutex_lock (&widget->priv->lock); - - _reset (widget); - - gst_caps_replace (&widget->priv->caps, caps); - - if (!_calculate_par (widget, &v_info)) { - g_mutex_unlock (&widget->priv->lock); - return FALSE; - } - - widget->priv->v_info = v_info; - widget->priv->negotiated = TRUE; - - if (!widget->priv->resize_id) { - widget->priv->resize_id = g_idle_add_full (G_PRIORITY_DEFAULT, - (GSourceFunc) _queue_resize, widget, NULL); - } - - g_mutex_unlock (&widget->priv->lock); + gst_gl_context_create (priv->context, priv->other_context, NULL); + GTK_GST_BASE_WIDGET_UNLOCK (gst_widget); return TRUE; } diff --git a/ext/gtk/gtkgstglwidget.h b/ext/gtk/gtkgstglwidget.h index 923b5f3..7f055c4 100644 --- a/ext/gtk/gtkgstglwidget.h +++ b/ext/gtk/gtkgstglwidget.h @@ -25,6 +25,8 @@ #include #include +#include "gtkgstbasewidget.h" + G_BEGIN_DECLS GType gtk_gst_gl_widget_get_type (void); @@ -47,7 +49,7 @@ typedef struct _GtkGstGLWidgetPrivate GtkGstGLWidgetPrivate; struct _GtkGstGLWidget { /* */ - GtkGLArea parent; + GtkGstBaseWidget base; GtkGstGLWidgetPrivate *priv; }; @@ -60,14 +62,12 @@ struct _GtkGstGLWidget struct _GtkGstGLWidgetClass { /* */ - GtkGLAreaClass object_class; + GtkGstBaseWidgetClass base_class; }; GtkWidget * gtk_gst_gl_widget_new (void); gboolean gtk_gst_gl_widget_init_winsys (GtkGstGLWidget * widget); -gboolean gtk_gst_gl_widget_set_caps (GtkGstGLWidget * widget, GstCaps *caps); -void gtk_gst_gl_widget_set_buffer (GtkGstGLWidget * widget, GstBuffer *buffer); 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); -- 2.7.4