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)))
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);
}

View file

@ -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);
};

View file

@ -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,

View file

@ -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 <ds@schleef.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_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);

View file

@ -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;

View file

@ -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