From 1cdd30ecaf767e32c21940db686a33c4f05303bc Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 24 Mar 2016 14:59:48 +1100 Subject: 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 --- gst/playback/gstdecodebin2.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c index 90276dfeb..0a80c8621 100644 --- a/gst/playback/gstdecodebin2.c +++ b/gst/playback/gstdecodebin2.c @@ -187,6 +187,7 @@ struct _GstDecodeBin GList *buffering_status; /* element currently buffering messages */ GMutex buffering_lock; + GMutex buffering_post_lock; }; struct _GstDecodeBinClass @@ -1110,6 +1111,7 @@ gst_decode_bin_init (GstDecodeBin * decode_bin) g_mutex_init (&decode_bin->subtitle_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->caps = gst_static_caps_get (&default_raw_caps); @@ -1164,6 +1166,7 @@ gst_decode_bin_finalize (GObject * object) g_mutex_clear (&decode_bin->dyn_lock); g_mutex_clear (&decode_bin->subtitle_lock); g_mutex_clear (&decode_bin->buffering_lock); + g_mutex_clear (&decode_bin->buffering_post_lock); g_mutex_clear (&decode_bin->factories_lock); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -5294,6 +5297,10 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg) BUFFERING_LOCK (dbin); 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: * 1) Look for a message with the same source @@ -5305,6 +5312,8 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg) if (GST_MESSAGE_SRC (bufstats) == GST_MESSAGE_SRC (msg)) { found = iter; if (msg_perc < 100) { + GST_DEBUG_OBJECT (dbin, "Replacing old buffering msg %" + GST_PTR_FORMAT, iter->data); gst_message_unref (iter->data); bufstats = iter->data = gst_message_ref (msg); } else { @@ -5313,6 +5322,9 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg) /* remove the element here and avoid confusing the loop */ iter = g_list_next (iter); + GST_DEBUG_OBJECT (dbin, "Deleting old buffering msg %" + GST_PTR_FORMAT, current->data); + gst_message_unref (current->data); dbin->buffering_status = g_list_delete_link (dbin->buffering_status, current); @@ -5334,6 +5346,7 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg) smaller_perc = msg_perc; smaller = msg; } + GST_DEBUG_OBJECT (dbin, "Storing buffering msg %" GST_PTR_FORMAT, msg); dbin->buffering_status = g_list_prepend (dbin->buffering_status, gst_message_ref (msg)); } @@ -5346,12 +5359,20 @@ gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg) gst_message_replace (&msg, smaller); } 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); - else + } else { + GST_DEBUG_OBJECT (dbin, "Forwarding msg %" GST_PTR_FORMAT, msg); GST_BIN_CLASS (parent_class)->handle_message (bin, msg); + } } static gboolean -- cgit v1.2.1