summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Schmidt <jan@centricular.com>2016-03-24 14:59:48 +1100
committerTim-Philipp Müller <tim@centricular.com>2016-04-06 13:08:57 +0100
commit1cdd30ecaf767e32c21940db686a33c4f05303bc (patch)
tree0ebc7ceb3ca4d2b448ee41712afb7482e2f80c65
parent128edf816355f890048a81d383176582bea02eb9 (diff)
downloadgstreamer-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.c25
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