bla
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 7 Apr 2011 08:40:16 +0000 (10:40 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 7 Apr 2011 08:40:16 +0000 (10:40 +0200)
libs/gst/base/gstbasesrc.c

index 72f38af..892e6d9 100644 (file)
@@ -240,6 +240,9 @@ struct _GstBaseSrcPrivate
 
   /* pending events (TAG, CUSTOM_BOTH, CUSTOM_DOWNSTREAM) to be
    * pushed in the data stream */
+  GList *pending_tags;
+  volatile gint have_tags;
+
   GList *pending_events;
   volatile gint have_events;
 
@@ -440,6 +443,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
   basesrc->data.ABI.typefind = DEFAULT_TYPEFIND;
   basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
   g_atomic_int_set (&basesrc->priv->have_events, FALSE);
+  g_atomic_int_set (&basesrc->priv->have_tags, FALSE);
 
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
   GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_IS_SOURCE);
@@ -461,6 +465,11 @@ gst_base_src_finalize (GObject * object)
   event_p = &basesrc->data.ABI.pending_seek;
   gst_event_replace (event_p, NULL);
 
+  if (basesrc->priv->pending_tags) {
+    g_list_foreach (basesrc->priv->pending_tags, (GFunc) gst_event_unref, NULL);
+    g_list_free (basesrc->priv->pending_tags);
+  }
+
   if (basesrc->priv->pending_events) {
     g_list_foreach (basesrc->priv->pending_events, (GFunc) gst_event_unref,
         NULL);
@@ -1588,9 +1597,17 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
       /* sending random NEWSEGMENT downstream can break sync. */
       break;
     case GST_EVENT_TAG:
+      /* Insert TAG in the dataflow */
+      GST_OBJECT_LOCK (src);
+      src->priv->pending_tags = g_list_append (src->priv->pending_tags, event);
+      g_atomic_int_set (&src->priv->have_tags, TRUE);
+      GST_OBJECT_UNLOCK (src);
+      event = NULL;
+      result = TRUE;
+      break;
     case GST_EVENT_CUSTOM_DOWNSTREAM:
     case GST_EVENT_CUSTOM_BOTH:
-      /* Insert TAG, CUSTOM_DOWNSTREAM, CUSTOM_BOTH in the dataflow */
+      /* Insert CUSTOM_DOWNSTREAM, CUSTOM_BOTH in the dataflow */
       GST_OBJECT_LOCK (src);
       src->priv->pending_events =
           g_list_append (src->priv->pending_events, event);
@@ -2357,7 +2374,7 @@ gst_base_src_loop (GstPad * pad)
   gint64 position;
   gboolean eos;
   gulong blocksize;
-  GList *pending_events = NULL, *tmp;
+  GList *pending_tags = NULL, *pending_events = NULL, *tmp;
 
   eos = FALSE;
 
@@ -2414,6 +2431,24 @@ gst_base_src_loop (GstPad * pad)
   }
   src->priv->newsegment_pending = FALSE;
 
+  if (g_atomic_int_get (&src->priv->have_tags)) {
+    GST_OBJECT_LOCK (src);
+    /* take the events */
+    pending_tags = src->priv->pending_tags;
+    src->priv->pending_tags = NULL;
+    g_atomic_int_set (&src->priv->have_tags, FALSE);
+    GST_OBJECT_UNLOCK (src);
+  }
+
+  /* Push out pending tags if any */
+  if (G_UNLIKELY (pending_tags != NULL)) {
+    for (tmp = pending_tags; tmp; tmp = g_list_next (tmp)) {
+      GstEvent *ev = (GstEvent *) tmp->data;
+      gst_pad_push_event (pad, ev);
+    }
+    g_list_free (pending_tags);
+  }
+
   if (g_atomic_int_get (&src->priv->have_events)) {
     GST_OBJECT_LOCK (src);
     /* take the events */
@@ -2423,7 +2458,7 @@ gst_base_src_loop (GstPad * pad)
     GST_OBJECT_UNLOCK (src);
   }
 
-  /* Push out pending tags if any */
+  /* Push out pending events if any */
   if (G_UNLIKELY (pending_events != NULL)) {
     for (tmp = pending_events; tmp; tmp = g_list_next (tmp)) {
       GstEvent *ev = (GstEvent *) tmp->data;
@@ -2854,6 +2889,19 @@ gst_base_src_set_flushing (GstBaseSrc * basesrc,
   } else {
     /* signal the live source that it can start playing */
     basesrc->live_running = live_play;
+
+    /* When unlocking drop all delayed events */
+    if (unlock) {
+      GST_OBJECT_LOCK (basesrc);
+      if (basesrc->priv->pending_events) {
+        g_list_foreach (basesrc->priv->pending_events, (GFunc) gst_event_unref,
+            NULL);
+        g_list_free (basesrc->priv->pending_events);
+        basesrc->priv->pending_events = NULL;
+        g_atomic_int_set (&basesrc->priv->have_events, FALSE);
+      }
+      GST_OBJECT_UNLOCK (basesrc);
+    }
   }
   GST_LIVE_SIGNAL (basesrc);
   GST_LIVE_UNLOCK (basesrc);