assrender: Protect libass structures from concurrent access from multiple threads

Fixes bug #608751.
This commit is contained in:
Sebastian Dröge 2010-02-23 18:16:48 +01:00
parent e9990ea6bb
commit 0dbe95a97d
2 changed files with 21 additions and 2 deletions

View file

@ -234,6 +234,7 @@ gst_ass_render_init (GstAssRender * render, GstAssRenderClass * gclass)
gst_segment_init (&render->video_segment, GST_FORMAT_TIME);
gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME);
render->ass_mutex = g_mutex_new ();
render->ass_library = ass_library_init ();
#if defined(LIBASS_VERSION) && LIBASS_VERSION >= 0x00907000
ass_set_message_cb (render->ass_library, _libass_message_cb, render);
@ -274,6 +275,9 @@ gst_ass_render_finalize (GObject * object)
ass_library_done (render->ass_library);
}
if (render->ass_mutex)
g_mutex_free (render->ass_mutex);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -289,7 +293,9 @@ gst_ass_render_set_property (GObject * object, guint prop_id,
break;
case PROP_EMBEDDEDFONTS:
render->embeddedfonts = g_value_get_boolean (value);
g_mutex_lock (render->ass_mutex);
ass_set_extract_fonts (render->ass_library, render->embeddedfonts);
g_mutex_unlock (render->ass_mutex);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -348,9 +354,11 @@ gst_ass_render_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
g_mutex_lock (render->ass_mutex);
if (render->ass_track)
ass_free_track (render->ass_track);
render->ass_track = NULL;
g_mutex_unlock (render->ass_mutex);
render->track_init_ok = FALSE;
render->renderer_init_ok = FALSE;
break;
@ -781,6 +789,7 @@ gst_ass_render_setcaps_video (GstPad * pad, GstCaps * caps)
goto out;
}
g_mutex_lock (render->ass_mutex);
ass_set_frame_size (render->ass_renderer, render->width, render->height);
dar = (((gdouble) par_n) * ((gdouble) render->width))
@ -803,6 +812,7 @@ gst_ass_render_setcaps_video (GstPad * pad, GstCaps * caps)
#endif
ass_set_margins (render->ass_renderer, 0, 0, 0, 0);
ass_set_use_margins (render->ass_renderer, 0);
g_mutex_unlock (render->ass_mutex);
render->renderer_init_ok = TRUE;
@ -832,6 +842,7 @@ gst_ass_render_setcaps_text (GstPad * pad, GstCaps * caps)
value = gst_structure_get_value (structure, "codec_data");
g_mutex_lock (render->ass_mutex);
if (value != NULL) {
priv = gst_value_get_buffer (value);
g_return_val_if_fail (priv != NULL, FALSE);
@ -857,6 +868,7 @@ gst_ass_render_setcaps_text (GstPad * pad, GstCaps * caps)
ret = TRUE;
}
g_mutex_unlock (render->ass_mutex);
gst_object_unref (render);
@ -881,7 +893,9 @@ gst_ass_render_process_text (GstAssRender * render, GstBuffer * buffer,
"Processing subtitles with running time %" GST_TIME_FORMAT
" and duration %" GST_TIME_FORMAT, GST_TIME_ARGS (running_time),
GST_TIME_ARGS (duration));
g_mutex_lock (render->ass_mutex);
ass_process_chunk (render->ass_track, data, size, pts_start, pts_end);
g_mutex_unlock (render->ass_mutex);
gst_buffer_unref (buffer);
}
@ -1008,6 +1022,7 @@ gst_ass_render_chain_video (GstPad * pad, GstBuffer * buffer)
/* libass needs timestamps in ms */
timestamp = running_time / GST_MSECOND;
g_mutex_lock (render->ass_mutex);
#ifndef GST_DISABLE_GST_DEBUG
/* only for testing right now. could possibly be used for optimizations? */
step = ass_step_sub (render->ass_track, timestamp, 1);
@ -1019,6 +1034,7 @@ gst_ass_render_chain_video (GstPad * pad, GstBuffer * buffer)
/* not sure what the last parameter to this call is for (detect_change) */
ass_image = ass_render_frame (render->ass_renderer, render->ass_track,
timestamp, NULL);
g_mutex_unlock (render->ass_mutex);
if (ass_image != NULL) {
buffer = gst_buffer_make_writable (buffer);
@ -1185,9 +1201,11 @@ gst_ass_render_handle_tags (GstAssRender * render, GstTagList * taglist)
}
if (valid_mimetype || valid_extension) {
g_mutex_lock (render->ass_mutex);
ass_add_font (render->ass_library, (gchar *) filename,
(gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
GST_DEBUG_OBJECT (render, "registered new font %s", filename);
g_mutex_unlock (render->ass_mutex);
}
}
}
@ -1307,17 +1325,17 @@ gst_ass_render_event_text (GstPad * pad, GstEvent * event)
break;
case GST_EVENT_FLUSH_START:
GST_DEBUG_OBJECT (render, "begin flushing");
g_mutex_lock (render->ass_mutex);
if (render->ass_track) {
GST_OBJECT_LOCK (render);
/* delete any events on the ass_track */
for (i = 0; i < render->ass_track->n_events; i++) {
GST_DEBUG_OBJECT (render, "deleted event with eid %i", i);
ass_free_event (render->ass_track, i);
}
render->ass_track->n_events = 0;
GST_OBJECT_UNLOCK (render);
GST_DEBUG_OBJECT (render, "done flushing");
}
g_mutex_unlock (render->ass_mutex);
g_mutex_lock (render->subtitle_mutex);
if (render->subtitle_pending)
gst_buffer_unref (render->subtitle_pending);

View file

@ -68,6 +68,7 @@ struct _GstAssRender
gboolean subtitle_flushing;
GstSegment subtitle_segment;
GMutex *ass_mutex;
ASS_Library *ass_library;
ASS_Renderer *ass_renderer;
ASS_Track *ass_track;