aggregator: Block serialized events/queries until the pad has consumed all buffers
authorSebastian Dröge <sebastian@centricular.com>
Wed, 19 Nov 2014 16:03:41 +0000 (17:03 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 2 Dec 2017 15:10:26 +0000 (15:10 +0000)
Otherwise the caps of the pad might change while the subclass still works with
a buffer of the old caps, assuming the the current pad caps apply to that
buffer. Which then leads to crashes and other nice effects.

https://bugzilla.gnome.org/show_bug.cgi?id=740376

libs/gst/base/gstaggregator.c

index 5a5a06e..6e2f8b0 100644 (file)
@@ -1563,7 +1563,7 @@ _chain (GstPad * pad, GstObject * object, GstBuffer * buffer)
 
   PAD_LOCK_EVENT (aggpad);
 
-  if (aggpad->buffer) {
+  while (aggpad->buffer) {
     GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
     PAD_WAIT_EVENT (aggpad);
   }
@@ -1617,8 +1617,18 @@ eos:
 static gboolean
 pad_query_func (GstPad * pad, GstObject * parent, GstQuery * query)
 {
+  GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
   GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
 
+  if (GST_QUERY_IS_SERIALIZED (query)) {
+    PAD_LOCK_EVENT (aggpad);
+    while (aggpad->buffer) {
+      GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
+      PAD_WAIT_EVENT (aggpad);
+    }
+    PAD_UNLOCK_EVENT (aggpad);
+  }
+
   return klass->sink_query (GST_AGGREGATOR (parent),
       GST_AGGREGATOR_PAD (pad), query);
 }
@@ -1626,8 +1636,19 @@ pad_query_func (GstPad * pad, GstObject * parent, GstQuery * query)
 static gboolean
 pad_event_func (GstPad * pad, GstObject * parent, GstEvent * event)
 {
+  GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
   GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
 
+  if (GST_EVENT_IS_SERIALIZED (event) && GST_EVENT_TYPE (event) != GST_EVENT_EOS
+      && GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT_DONE) {
+    PAD_LOCK_EVENT (aggpad);
+    while (aggpad->buffer) {
+      GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
+      PAD_WAIT_EVENT (aggpad);
+    }
+    PAD_UNLOCK_EVENT (aggpad);
+  }
+
   return klass->sink_event (GST_AGGREGATOR (parent),
       GST_AGGREGATOR_PAD (pad), event);
 }