diff options
author | Jan Schmidt <jan@centricular.com> | 2016-03-24 14:59:48 +1100 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.com> | 2016-04-06 13:08:57 +0100 |
commit | 1cdd30ecaf767e32c21940db686a33c4f05303bc (patch) | |
tree | 0ebc7ceb3ca4d2b448ee41712afb7482e2f80c65 | |
parent | 128edf816355f890048a81d383176582bea02eb9 (diff) | |
download | gstreamer-plugins-base-1cdd30ecaf767e32c21940db686a33c4f05303bc.tar.gz |
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
-rw-r--r-- | gst/playback/gstdecodebin2.c | 25 |
1 files 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 |