decodebin2: Hold new buffering_post lock while posting msgs

There's a small window between decodebin choosing a buffering level
to post and another thread choosing a different buffering level
where things can race. Close that window by holding a new lock
that's only for posting buffering messages - like what was done
in multiqueue.

https://bugzilla.gnome.org/show_bug.cgi?id=764020
This commit is contained in:
Jan Schmidt 2016-03-24 14:59:48 +11:00 committed by Sebastian Dröge
parent f4fb623aba
commit fd92bdf894

View file

@ -187,6 +187,7 @@ struct _GstDecodeBin
GList *buffering_status; /* element currently buffering messages */ GList *buffering_status; /* element currently buffering messages */
GMutex buffering_lock; GMutex buffering_lock;
GMutex buffering_post_lock;
}; };
struct _GstDecodeBinClass struct _GstDecodeBinClass
@ -1113,6 +1114,7 @@ gst_decode_bin_init (GstDecodeBin * decode_bin)
g_mutex_init (&decode_bin->subtitle_lock); g_mutex_init (&decode_bin->subtitle_lock);
g_mutex_init (&decode_bin->buffering_lock); g_mutex_init (&decode_bin->buffering_lock);
g_mutex_init (&decode_bin->buffering_post_lock);
decode_bin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING); decode_bin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
decode_bin->caps = gst_static_caps_get (&default_raw_caps); decode_bin->caps = gst_static_caps_get (&default_raw_caps);
@ -1167,6 +1169,7 @@ gst_decode_bin_finalize (GObject * object)
g_mutex_clear (&decode_bin->dyn_lock); g_mutex_clear (&decode_bin->dyn_lock);
g_mutex_clear (&decode_bin->subtitle_lock); g_mutex_clear (&decode_bin->subtitle_lock);
g_mutex_clear (&decode_bin->buffering_lock); g_mutex_clear (&decode_bin->buffering_lock);
g_mutex_clear (&decode_bin->buffering_post_lock);
g_mutex_clear (&decode_bin->factories_lock); g_mutex_clear (&decode_bin->factories_lock);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
@ -5376,6 +5379,10 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
BUFFERING_LOCK (dbin); BUFFERING_LOCK (dbin);
gst_message_parse_buffering (msg, &msg_perc); gst_message_parse_buffering (msg, &msg_perc);
GST_DEBUG_OBJECT (dbin, "Got buffering msg %" GST_PTR_FORMAT, msg);
g_mutex_lock (&dbin->buffering_post_lock);
/* /*
* Single loop for 2 things: * Single loop for 2 things:
* 1) Look for a message with the same source * 1) Look for a message with the same source
@ -5387,6 +5394,8 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
if (GST_MESSAGE_SRC (bufstats) == GST_MESSAGE_SRC (msg)) { if (GST_MESSAGE_SRC (bufstats) == GST_MESSAGE_SRC (msg)) {
found = iter; found = iter;
if (msg_perc < 100) { if (msg_perc < 100) {
GST_DEBUG_OBJECT (dbin, "Replacing old buffering msg %"
GST_PTR_FORMAT, iter->data);
gst_message_unref (iter->data); gst_message_unref (iter->data);
bufstats = iter->data = gst_message_ref (msg); bufstats = iter->data = gst_message_ref (msg);
} else { } else {
@ -5395,6 +5404,9 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
/* remove the element here and avoid confusing the loop */ /* remove the element here and avoid confusing the loop */
iter = g_list_next (iter); iter = g_list_next (iter);
GST_DEBUG_OBJECT (dbin, "Deleting old buffering msg %"
GST_PTR_FORMAT, current->data);
gst_message_unref (current->data); gst_message_unref (current->data);
dbin->buffering_status = dbin->buffering_status =
g_list_delete_link (dbin->buffering_status, current); g_list_delete_link (dbin->buffering_status, current);
@ -5416,6 +5428,7 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
smaller_perc = msg_perc; smaller_perc = msg_perc;
smaller = msg; smaller = msg;
} }
GST_DEBUG_OBJECT (dbin, "Storing buffering msg %" GST_PTR_FORMAT, msg);
dbin->buffering_status = dbin->buffering_status =
g_list_prepend (dbin->buffering_status, gst_message_ref (msg)); g_list_prepend (dbin->buffering_status, gst_message_ref (msg));
} }
@ -5428,13 +5441,21 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
gst_message_replace (&msg, smaller); gst_message_replace (&msg, smaller);
} }
BUFFERING_UNLOCK (dbin); BUFFERING_UNLOCK (dbin);
GST_DEBUG_OBJECT (dbin, "Forwarding buffering msg %" GST_PTR_FORMAT, msg);
GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
g_mutex_unlock (&dbin->buffering_post_lock);
return;
} }
if (drop) if (drop) {
gst_message_unref (msg); gst_message_unref (msg);
else } else {
GST_DEBUG_OBJECT (dbin, "Forwarding msg %" GST_PTR_FORMAT, msg);
GST_BIN_CLASS (parent_class)->handle_message (bin, msg); GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
} }
}
static gboolean static gboolean
gst_decode_bin_remove_element (GstBin * bin, GstElement * element) gst_decode_bin_remove_element (GstBin * bin, GstElement * element)