From 2ace14f613c69b456d5fda23d8d5156d461cdfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 27 Aug 2018 15:41:31 +0300 Subject: [PATCH] pango: Create one context per instance and remove class mutex PangoCairo is thread-safe as long as the context and fontmap are not shared between threads. Previously each subclass had its own context and a class mutex for this reason, but apart from hurting performance this was also not completely safe yet: the same fontmap might've been used by different classes from different threads as the thread-default fontmap (at time of class initialization) was used. --- ext/pango/gstbasetextoverlay.c | 60 +++++++++------------------------- ext/pango/gstbasetextoverlay.h | 5 ++- ext/pango/gstclockoverlay.c | 37 ++++++++++----------- ext/pango/gsttextrender.c | 16 +++++---- ext/pango/gsttextrender.h | 4 +-- ext/pango/gsttimeoverlay.c | 34 +++++++++---------- 6 files changed, 62 insertions(+), 94 deletions(-) diff --git a/ext/pango/gstbasetextoverlay.c b/ext/pango/gstbasetextoverlay.c index 824bb38bd9..9cfc77dc10 100644 --- a/ext/pango/gstbasetextoverlay.c +++ b/ext/pango/gstbasetextoverlay.c @@ -258,7 +258,6 @@ gst_base_text_overlay_scale_mode_get_type (void) #define GST_BASE_TEXT_OVERLAY_BROADCAST(ov)(g_cond_broadcast (GST_BASE_TEXT_OVERLAY_GET_COND (ov))) static GstElementClass *parent_class = NULL; -static void gst_base_text_overlay_base_init (gpointer g_class); static void gst_base_text_overlay_class_init (GstBaseTextOverlayClass * klass); static void gst_base_text_overlay_init (GstBaseTextOverlay * overlay, GstBaseTextOverlayClass * klass); @@ -318,7 +317,7 @@ gst_base_text_overlay_get_type (void) if (g_once_init_enter ((gsize *) & type)) { static const GTypeInfo info = { sizeof (GstBaseTextOverlayClass), - (GBaseInitFunc) gst_base_text_overlay_base_init, + (GBaseInitFunc) NULL, NULL, (GClassInitFunc) gst_base_text_overlay_class_init, NULL, @@ -343,25 +342,6 @@ gst_base_text_overlay_get_text (GstBaseTextOverlay * overlay, return g_strdup (overlay->default_text); } -static void -gst_base_text_overlay_base_init (gpointer g_class) -{ - GstBaseTextOverlayClass *klass = GST_BASE_TEXT_OVERLAY_CLASS (g_class); - PangoFontMap *fontmap; - - /* Only lock for the subclasses here, the base class - * doesn't have this mutex yet and it's not necessary - * here */ - if (klass->pango_lock) - g_mutex_lock (klass->pango_lock); - fontmap = pango_cairo_font_map_get_default (); - klass->pango_context = - pango_font_map_create_context (PANGO_FONT_MAP (fontmap)); - pango_context_set_base_gravity (klass->pango_context, PANGO_GRAVITY_SOUTH); - if (klass->pango_lock) - g_mutex_unlock (klass->pango_lock); -} - static void gst_base_text_overlay_class_init (GstBaseTextOverlayClass * klass) { @@ -385,9 +365,6 @@ gst_base_text_overlay_class_init (GstBaseTextOverlayClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_base_text_overlay_change_state); - klass->pango_lock = g_slice_new (GMutex); - g_mutex_init (klass->pango_lock); - klass->get_text = gst_base_text_overlay_get_text; g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TEXT, @@ -682,6 +659,11 @@ gst_base_text_overlay_finalize (GObject * object) overlay->text_buffer = NULL; } + if (overlay->pango_context) { + g_object_unref (overlay->pango_context); + overlay->pango_context = NULL; + } + g_mutex_clear (&overlay->lock); g_cond_clear (&overlay->cond); @@ -694,6 +676,13 @@ gst_base_text_overlay_init (GstBaseTextOverlay * overlay, { GstPadTemplate *template; PangoFontDescription *desc; + PangoFontMap *fontmap; + + fontmap = pango_cairo_font_map_new (); + overlay->pango_context = + pango_font_map_create_context (PANGO_FONT_MAP (fontmap)); + g_object_unref (fontmap); + pango_context_set_base_gravity (overlay->pango_context, PANGO_GRAVITY_SOUTH); /* video sink */ template = gst_static_pad_template_get (&video_sink_template_factory); @@ -736,13 +725,8 @@ gst_base_text_overlay_init (GstBaseTextOverlay * overlay, GST_DEBUG_FUNCPTR (gst_base_text_overlay_src_query)); gst_element_add_pad (GST_ELEMENT (overlay), overlay->srcpad); - g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); - overlay->layout = - pango_layout_new (GST_BASE_TEXT_OVERLAY_GET_CLASS - (overlay)->pango_context); - desc = - pango_context_get_font_description (GST_BASE_TEXT_OVERLAY_GET_CLASS - (overlay)->pango_context); + overlay->layout = pango_layout_new (overlay->pango_context); + desc = pango_context_get_font_description (overlay->pango_context); gst_base_text_overlay_adjust_values_with_fontdesc (overlay, desc); overlay->color = DEFAULT_PROP_COLOR; @@ -803,7 +787,6 @@ gst_base_text_overlay_init (GstBaseTextOverlay * overlay, g_mutex_init (&overlay->lock); g_cond_init (&overlay->cond); gst_segment_init (&overlay->segment, GST_FORMAT_TIME); - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); } static void @@ -1101,7 +1084,6 @@ gst_base_text_overlay_set_property (GObject * object, guint prop_id, const gchar *fontdesc_str; fontdesc_str = g_value_get_string (value); - g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); desc = pango_font_description_from_string (fontdesc_str); if (desc) { GST_LOG_OBJECT (overlay, "font description set: %s", fontdesc_str); @@ -1112,7 +1094,6 @@ gst_base_text_overlay_set_property (GObject * object, guint prop_id, GST_WARNING_OBJECT (overlay, "font description parse failed: %s", fontdesc_str); } - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); break; } case PROP_COLOR: @@ -1132,10 +1113,8 @@ gst_base_text_overlay_set_property (GObject * object, guint prop_id, break; case PROP_LINE_ALIGNMENT: overlay->line_align = g_value_get_enum (value); - g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); pango_layout_set_alignment (overlay->layout, (PangoAlignment) overlay->line_align); - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); break; case PROP_WAIT_TEXT: overlay->wait_text = g_value_get_boolean (value); @@ -1149,10 +1128,8 @@ gst_base_text_overlay_set_property (GObject * object, guint prop_id, overlay->valign = GST_BASE_TEXT_OVERLAY_VALIGN_TOP; overlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_RIGHT; overlay->line_align = GST_BASE_TEXT_OVERLAY_LINE_ALIGN_LEFT; - g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); pango_layout_set_alignment (overlay->layout, (PangoAlignment) overlay->line_align); - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); } break; case PROP_SCALE_MODE: @@ -1262,14 +1239,12 @@ gst_base_text_overlay_get_property (GObject * object, guint prop_id, { const PangoFontDescription *desc; - g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); desc = pango_layout_get_font_description (overlay->layout); if (!desc) g_value_set_string (value, ""); else { g_value_take_string (value, pango_font_description_to_string (desc)); } - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); break; } case PROP_TEXT_X: @@ -1755,8 +1730,6 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay, GstBuffer *buffer; GstMapInfo map; - g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); - if (overlay->auto_adjust_size) { /* 640 pixel is default */ scalef_x = scalef_y = (double) (overlay->width) / DEFAULT_SCALE_BASIS; @@ -1918,14 +1891,12 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay, scalef_y *= overlay->render_scale; if (width <= 0 || height <= 0) { - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); GST_DEBUG_OBJECT (overlay, "Overlay is outside video frame. Skipping text rendering"); return; } if (unscaled_height <= 0 || unscaled_width <= 0) { - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); GST_DEBUG_OBJECT (overlay, "Overlay is outside video frame. Skipping text rendering"); return; @@ -2057,7 +2028,6 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay, overlay->text_width = width; if (height != 0) overlay->text_height = height; - g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); gst_base_text_overlay_set_composition (overlay); } diff --git a/ext/pango/gstbasetextoverlay.h b/ext/pango/gstbasetextoverlay.h index 4f009942b5..d3eea68ae1 100644 --- a/ext/pango/gstbasetextoverlay.h +++ b/ext/pango/gstbasetextoverlay.h @@ -144,6 +144,8 @@ struct _GstBaseTextOverlay { GstPad *text_sinkpad; GstPad *srcpad; + PangoContext *pango_context; + GstSegment segment; GstSegment text_segment; GstBuffer *text_buffer; @@ -232,9 +234,6 @@ struct _GstBaseTextOverlay { struct _GstBaseTextOverlayClass { GstElementClass parent_class; - PangoContext *pango_context; - GMutex *pango_lock; - gchar * (*get_text) (GstBaseTextOverlay *overlay, GstBuffer *video_frame); }; diff --git a/ext/pango/gstclockoverlay.c b/ext/pango/gstclockoverlay.c index 21cf1d26da..4b9d9fb5f9 100644 --- a/ext/pango/gstclockoverlay.c +++ b/ext/pango/gstclockoverlay.c @@ -138,8 +138,6 @@ gst_clock_overlay_class_init (GstClockOverlayClass * klass) GObjectClass *gobject_class; GstElementClass *gstelement_class; GstBaseTextOverlayClass *gsttextoverlay_class; - PangoContext *context; - PangoFontDescription *font_description; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; @@ -160,23 +158,6 @@ gst_clock_overlay_class_init (GstClockOverlayClass * klass) g_param_spec_string ("time-format", "Date/Time Format", "Format to use for time and date value, as in strftime.", DEFAULT_PROP_TIMEFORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_mutex_lock (gsttextoverlay_class->pango_lock); - context = gsttextoverlay_class->pango_context; - - pango_context_set_language (context, pango_language_from_string ("en_US")); - pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); - - font_description = pango_font_description_new (); - pango_font_description_set_family_static (font_description, "Monospace"); - pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); - pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); - pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); - pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); - pango_font_description_set_size (font_description, 18 * PANGO_SCALE); - pango_context_set_font_description (context, font_description); - pango_font_description_free (font_description); - g_mutex_unlock (gsttextoverlay_class->pango_lock); } @@ -197,6 +178,8 @@ static void gst_clock_overlay_init (GstClockOverlay * overlay) { GstBaseTextOverlay *textoverlay; + PangoContext *context; + PangoFontDescription *font_description; textoverlay = GST_BASE_TEXT_OVERLAY (overlay); @@ -204,8 +187,22 @@ gst_clock_overlay_init (GstClockOverlay * overlay) textoverlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_LEFT; overlay->format = g_strdup (DEFAULT_PROP_TIMEFORMAT); -} + context = textoverlay->pango_context; + + pango_context_set_language (context, pango_language_from_string ("en_US")); + pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); + + font_description = pango_font_description_new (); + pango_font_description_set_family_static (font_description, "Monospace"); + pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); + pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); + pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); + pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); + pango_font_description_set_size (font_description, 18 * PANGO_SCALE); + pango_context_set_font_description (context, font_description); + pango_font_description_free (font_description); +} static void gst_clock_overlay_set_property (GObject * object, guint prop_id, diff --git a/ext/pango/gsttextrender.c b/ext/pango/gsttextrender.c index 18b7337e47..302cb0d93a 100644 --- a/ext/pango/gsttextrender.c +++ b/ext/pango/gsttextrender.c @@ -177,7 +177,6 @@ gst_text_render_class_init (GstTextRenderClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; - PangoFontMap *fontmap; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; @@ -199,9 +198,6 @@ gst_text_render_class_init (GstTextRenderClass * klass) "David Schleef , " "GStreamer maintainers "); - fontmap = pango_cairo_font_map_get_default (); - klass->pango_context = - pango_font_map_create_context (PANGO_FONT_MAP (fontmap)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FONT_DESC, g_param_spec_string ("font-desc", "font description", "Pango font description of font " @@ -631,6 +627,9 @@ gst_text_render_finalize (GObject * object) if (render->layout) g_object_unref (render->layout); + if (render->pango_context) + g_object_unref (render->pango_context); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -638,6 +637,7 @@ static void gst_text_render_init (GstTextRender * render) { GstPadTemplate *template; + PangoFontMap *fontmap; /* sink */ template = gst_static_pad_template_get (&sink_template_factory); @@ -657,9 +657,13 @@ gst_text_render_init (GstTextRender * render) gst_element_add_pad (GST_ELEMENT (render), render->srcpad); + fontmap = pango_cairo_font_map_new (); + render->pango_context = + pango_font_map_create_context (PANGO_FONT_MAP (fontmap)); + g_object_unref (fontmap); + render->line_align = DEFAULT_PROP_LINE_ALIGNMENT; - render->layout = - pango_layout_new (GST_TEXT_RENDER_GET_CLASS (render)->pango_context); + render->layout = pango_layout_new (render->pango_context); pango_layout_set_alignment (render->layout, (PangoAlignment) render->line_align); diff --git a/ext/pango/gsttextrender.h b/ext/pango/gsttextrender.h index 90ac089e50..535fe109c9 100644 --- a/ext/pango/gsttextrender.h +++ b/ext/pango/gsttextrender.h @@ -83,6 +83,8 @@ struct _GstTextRender { gint baseline_y; gboolean use_ARGB; + PangoContext *pango_context; + GstTextRenderVAlign valign; GstTextRenderHAlign halign; GstTextRenderLineAlign line_align; @@ -95,8 +97,6 @@ struct _GstTextRender { struct _GstTextRenderClass { GstElementClass parent_class; - - PangoContext *pango_context; }; GType gst_text_render_get_type(void) G_GNUC_CONST; diff --git a/ext/pango/gsttimeoverlay.c b/ext/pango/gsttimeoverlay.c index d9892f6ccf..a8ac80ef12 100644 --- a/ext/pango/gsttimeoverlay.c +++ b/ext/pango/gsttimeoverlay.c @@ -172,8 +172,6 @@ gst_time_overlay_class_init (GstTimeOverlayClass * klass) GstElementClass *gstelement_class; GstBaseTextOverlayClass *gsttextoverlay_class; GObjectClass *gobject_class; - PangoContext *context; - PangoFontDescription *font_description; gsttextoverlay_class = (GstBaseTextOverlayClass *) klass; gstelement_class = (GstElementClass *) klass; @@ -193,9 +191,23 @@ gst_time_overlay_class_init (GstTimeOverlayClass * klass) g_param_spec_enum ("time-mode", "Time Mode", "What time to show", GST_TYPE_TIME_OVERLAY_TIME_LINE, DEFAULT_TIME_LINE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} - g_mutex_lock (gsttextoverlay_class->pango_lock); - context = gsttextoverlay_class->pango_context; +static void +gst_time_overlay_init (GstTimeOverlay * overlay) +{ + GstBaseTextOverlay *textoverlay; + PangoContext *context; + PangoFontDescription *font_description; + + textoverlay = GST_BASE_TEXT_OVERLAY (overlay); + + textoverlay->valign = GST_BASE_TEXT_OVERLAY_VALIGN_TOP; + textoverlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_LEFT; + + overlay->time_line = DEFAULT_TIME_LINE; + + context = textoverlay->pango_context; pango_context_set_language (context, pango_language_from_string ("en_US")); pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); @@ -209,20 +221,6 @@ gst_time_overlay_class_init (GstTimeOverlayClass * klass) pango_font_description_set_size (font_description, 18 * PANGO_SCALE); pango_context_set_font_description (context, font_description); pango_font_description_free (font_description); - g_mutex_unlock (gsttextoverlay_class->pango_lock); -} - -static void -gst_time_overlay_init (GstTimeOverlay * overlay) -{ - GstBaseTextOverlay *textoverlay; - - textoverlay = GST_BASE_TEXT_OVERLAY (overlay); - - textoverlay->valign = GST_BASE_TEXT_OVERLAY_VALIGN_TOP; - textoverlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_LEFT; - - overlay->time_line = DEFAULT_TIME_LINE; } static void