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.
This commit is contained in:
Sebastian Dröge 2018-08-27 15:41:31 +03:00
parent 6024b8e46b
commit 2ace14f613
6 changed files with 62 additions and 94 deletions

View file

@ -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))) #define GST_BASE_TEXT_OVERLAY_BROADCAST(ov)(g_cond_broadcast (GST_BASE_TEXT_OVERLAY_GET_COND (ov)))
static GstElementClass *parent_class = NULL; 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_class_init (GstBaseTextOverlayClass * klass);
static void gst_base_text_overlay_init (GstBaseTextOverlay * overlay, static void gst_base_text_overlay_init (GstBaseTextOverlay * overlay,
GstBaseTextOverlayClass * klass); GstBaseTextOverlayClass * klass);
@ -318,7 +317,7 @@ gst_base_text_overlay_get_type (void)
if (g_once_init_enter ((gsize *) & type)) { if (g_once_init_enter ((gsize *) & type)) {
static const GTypeInfo info = { static const GTypeInfo info = {
sizeof (GstBaseTextOverlayClass), sizeof (GstBaseTextOverlayClass),
(GBaseInitFunc) gst_base_text_overlay_base_init, (GBaseInitFunc) NULL,
NULL, NULL,
(GClassInitFunc) gst_base_text_overlay_class_init, (GClassInitFunc) gst_base_text_overlay_class_init,
NULL, NULL,
@ -343,25 +342,6 @@ gst_base_text_overlay_get_text (GstBaseTextOverlay * overlay,
return g_strdup (overlay->default_text); 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 static void
gst_base_text_overlay_class_init (GstBaseTextOverlayClass * klass) gst_base_text_overlay_class_init (GstBaseTextOverlayClass * klass)
{ {
@ -385,9 +365,6 @@ gst_base_text_overlay_class_init (GstBaseTextOverlayClass * klass)
gstelement_class->change_state = gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_base_text_overlay_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; klass->get_text = gst_base_text_overlay_get_text;
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_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; overlay->text_buffer = NULL;
} }
if (overlay->pango_context) {
g_object_unref (overlay->pango_context);
overlay->pango_context = NULL;
}
g_mutex_clear (&overlay->lock); g_mutex_clear (&overlay->lock);
g_cond_clear (&overlay->cond); g_cond_clear (&overlay->cond);
@ -694,6 +676,13 @@ gst_base_text_overlay_init (GstBaseTextOverlay * overlay,
{ {
GstPadTemplate *template; GstPadTemplate *template;
PangoFontDescription *desc; 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 */ /* video sink */
template = gst_static_pad_template_get (&video_sink_template_factory); 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_DEBUG_FUNCPTR (gst_base_text_overlay_src_query));
gst_element_add_pad (GST_ELEMENT (overlay), overlay->srcpad); 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 (overlay->pango_context);
overlay->layout = desc = pango_context_get_font_description (overlay->pango_context);
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);
gst_base_text_overlay_adjust_values_with_fontdesc (overlay, desc); gst_base_text_overlay_adjust_values_with_fontdesc (overlay, desc);
overlay->color = DEFAULT_PROP_COLOR; overlay->color = DEFAULT_PROP_COLOR;
@ -803,7 +787,6 @@ gst_base_text_overlay_init (GstBaseTextOverlay * overlay,
g_mutex_init (&overlay->lock); g_mutex_init (&overlay->lock);
g_cond_init (&overlay->cond); g_cond_init (&overlay->cond);
gst_segment_init (&overlay->segment, GST_FORMAT_TIME); gst_segment_init (&overlay->segment, GST_FORMAT_TIME);
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
} }
static void static void
@ -1101,7 +1084,6 @@ gst_base_text_overlay_set_property (GObject * object, guint prop_id,
const gchar *fontdesc_str; const gchar *fontdesc_str;
fontdesc_str = g_value_get_string (value); 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); desc = pango_font_description_from_string (fontdesc_str);
if (desc) { if (desc) {
GST_LOG_OBJECT (overlay, "font description set: %s", fontdesc_str); 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", GST_WARNING_OBJECT (overlay, "font description parse failed: %s",
fontdesc_str); fontdesc_str);
} }
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
break; break;
} }
case PROP_COLOR: case PROP_COLOR:
@ -1132,10 +1113,8 @@ gst_base_text_overlay_set_property (GObject * object, guint prop_id,
break; break;
case PROP_LINE_ALIGNMENT: case PROP_LINE_ALIGNMENT:
overlay->line_align = g_value_get_enum (value); 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, pango_layout_set_alignment (overlay->layout,
(PangoAlignment) overlay->line_align); (PangoAlignment) overlay->line_align);
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
break; break;
case PROP_WAIT_TEXT: case PROP_WAIT_TEXT:
overlay->wait_text = g_value_get_boolean (value); 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->valign = GST_BASE_TEXT_OVERLAY_VALIGN_TOP;
overlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_RIGHT; overlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_RIGHT;
overlay->line_align = GST_BASE_TEXT_OVERLAY_LINE_ALIGN_LEFT; 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, pango_layout_set_alignment (overlay->layout,
(PangoAlignment) overlay->line_align); (PangoAlignment) overlay->line_align);
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
} }
break; break;
case PROP_SCALE_MODE: case PROP_SCALE_MODE:
@ -1262,14 +1239,12 @@ gst_base_text_overlay_get_property (GObject * object, guint prop_id,
{ {
const PangoFontDescription *desc; const PangoFontDescription *desc;
g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
desc = pango_layout_get_font_description (overlay->layout); desc = pango_layout_get_font_description (overlay->layout);
if (!desc) if (!desc)
g_value_set_string (value, ""); g_value_set_string (value, "");
else { else {
g_value_take_string (value, pango_font_description_to_string (desc)); g_value_take_string (value, pango_font_description_to_string (desc));
} }
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
break; break;
} }
case PROP_TEXT_X: case PROP_TEXT_X:
@ -1755,8 +1730,6 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay,
GstBuffer *buffer; GstBuffer *buffer;
GstMapInfo map; GstMapInfo map;
g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
if (overlay->auto_adjust_size) { if (overlay->auto_adjust_size) {
/* 640 pixel is default */ /* 640 pixel is default */
scalef_x = scalef_y = (double) (overlay->width) / DEFAULT_SCALE_BASIS; 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; scalef_y *= overlay->render_scale;
if (width <= 0 || height <= 0) { if (width <= 0 || height <= 0) {
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
GST_DEBUG_OBJECT (overlay, GST_DEBUG_OBJECT (overlay,
"Overlay is outside video frame. Skipping text rendering"); "Overlay is outside video frame. Skipping text rendering");
return; return;
} }
if (unscaled_height <= 0 || unscaled_width <= 0) { if (unscaled_height <= 0 || unscaled_width <= 0) {
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
GST_DEBUG_OBJECT (overlay, GST_DEBUG_OBJECT (overlay,
"Overlay is outside video frame. Skipping text rendering"); "Overlay is outside video frame. Skipping text rendering");
return; return;
@ -2057,7 +2028,6 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay,
overlay->text_width = width; overlay->text_width = width;
if (height != 0) if (height != 0)
overlay->text_height = height; overlay->text_height = height;
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
gst_base_text_overlay_set_composition (overlay); gst_base_text_overlay_set_composition (overlay);
} }

View file

@ -144,6 +144,8 @@ struct _GstBaseTextOverlay {
GstPad *text_sinkpad; GstPad *text_sinkpad;
GstPad *srcpad; GstPad *srcpad;
PangoContext *pango_context;
GstSegment segment; GstSegment segment;
GstSegment text_segment; GstSegment text_segment;
GstBuffer *text_buffer; GstBuffer *text_buffer;
@ -232,9 +234,6 @@ struct _GstBaseTextOverlay {
struct _GstBaseTextOverlayClass { struct _GstBaseTextOverlayClass {
GstElementClass parent_class; GstElementClass parent_class;
PangoContext *pango_context;
GMutex *pango_lock;
gchar * (*get_text) (GstBaseTextOverlay *overlay, GstBuffer *video_frame); gchar * (*get_text) (GstBaseTextOverlay *overlay, GstBuffer *video_frame);
}; };

View file

@ -138,8 +138,6 @@ gst_clock_overlay_class_init (GstClockOverlayClass * klass)
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class; GstElementClass *gstelement_class;
GstBaseTextOverlayClass *gsttextoverlay_class; GstBaseTextOverlayClass *gsttextoverlay_class;
PangoContext *context;
PangoFontDescription *font_description;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) 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", g_param_spec_string ("time-format", "Date/Time Format",
"Format to use for time and date value, as in strftime.", "Format to use for time and date value, as in strftime.",
DEFAULT_PROP_TIMEFORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 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) gst_clock_overlay_init (GstClockOverlay * overlay)
{ {
GstBaseTextOverlay *textoverlay; GstBaseTextOverlay *textoverlay;
PangoContext *context;
PangoFontDescription *font_description;
textoverlay = GST_BASE_TEXT_OVERLAY (overlay); textoverlay = GST_BASE_TEXT_OVERLAY (overlay);
@ -204,8 +187,22 @@ gst_clock_overlay_init (GstClockOverlay * overlay)
textoverlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_LEFT; textoverlay->halign = GST_BASE_TEXT_OVERLAY_HALIGN_LEFT;
overlay->format = g_strdup (DEFAULT_PROP_TIMEFORMAT); 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 static void
gst_clock_overlay_set_property (GObject * object, guint prop_id, gst_clock_overlay_set_property (GObject * object, guint prop_id,

View file

@ -177,7 +177,6 @@ gst_text_render_class_init (GstTextRenderClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class; GstElementClass *gstelement_class;
PangoFontMap *fontmap;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass; gstelement_class = (GstElementClass *) klass;
@ -199,9 +198,6 @@ gst_text_render_class_init (GstTextRenderClass * klass)
"David Schleef <ds@schleef.org>, " "David Schleef <ds@schleef.org>, "
"GStreamer maintainers <gstreamer-devel@lists.freedesktop.org>"); "GStreamer maintainers <gstreamer-devel@lists.freedesktop.org>");
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_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FONT_DESC,
g_param_spec_string ("font-desc", "font description", g_param_spec_string ("font-desc", "font description",
"Pango font description of font " "Pango font description of font "
@ -631,6 +627,9 @@ gst_text_render_finalize (GObject * object)
if (render->layout) if (render->layout)
g_object_unref (render->layout); g_object_unref (render->layout);
if (render->pango_context)
g_object_unref (render->pango_context);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -638,6 +637,7 @@ static void
gst_text_render_init (GstTextRender * render) gst_text_render_init (GstTextRender * render)
{ {
GstPadTemplate *template; GstPadTemplate *template;
PangoFontMap *fontmap;
/* sink */ /* sink */
template = gst_static_pad_template_get (&sink_template_factory); 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); 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->line_align = DEFAULT_PROP_LINE_ALIGNMENT;
render->layout = render->layout = pango_layout_new (render->pango_context);
pango_layout_new (GST_TEXT_RENDER_GET_CLASS (render)->pango_context);
pango_layout_set_alignment (render->layout, pango_layout_set_alignment (render->layout,
(PangoAlignment) render->line_align); (PangoAlignment) render->line_align);

View file

@ -83,6 +83,8 @@ struct _GstTextRender {
gint baseline_y; gint baseline_y;
gboolean use_ARGB; gboolean use_ARGB;
PangoContext *pango_context;
GstTextRenderVAlign valign; GstTextRenderVAlign valign;
GstTextRenderHAlign halign; GstTextRenderHAlign halign;
GstTextRenderLineAlign line_align; GstTextRenderLineAlign line_align;
@ -95,8 +97,6 @@ struct _GstTextRender {
struct _GstTextRenderClass { struct _GstTextRenderClass {
GstElementClass parent_class; GstElementClass parent_class;
PangoContext *pango_context;
}; };
GType gst_text_render_get_type(void) G_GNUC_CONST; GType gst_text_render_get_type(void) G_GNUC_CONST;

View file

@ -172,8 +172,6 @@ gst_time_overlay_class_init (GstTimeOverlayClass * klass)
GstElementClass *gstelement_class; GstElementClass *gstelement_class;
GstBaseTextOverlayClass *gsttextoverlay_class; GstBaseTextOverlayClass *gsttextoverlay_class;
GObjectClass *gobject_class; GObjectClass *gobject_class;
PangoContext *context;
PangoFontDescription *font_description;
gsttextoverlay_class = (GstBaseTextOverlayClass *) klass; gsttextoverlay_class = (GstBaseTextOverlayClass *) klass;
gstelement_class = (GstElementClass *) 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", g_param_spec_enum ("time-mode", "Time Mode", "What time to show",
GST_TYPE_TIME_OVERLAY_TIME_LINE, DEFAULT_TIME_LINE, GST_TYPE_TIME_OVERLAY_TIME_LINE, DEFAULT_TIME_LINE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
g_mutex_lock (gsttextoverlay_class->pango_lock); static void
context = gsttextoverlay_class->pango_context; 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_language (context, pango_language_from_string ("en_US"));
pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); 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_font_description_set_size (font_description, 18 * PANGO_SCALE);
pango_context_set_font_description (context, font_description); pango_context_set_font_description (context, font_description);
pango_font_description_free (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 static void