ges: support and handle no-more-pads in GESTimeline(Pipeline)
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 30 Jan 2012 10:34:09 +0000 (11:34 +0100)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 30 Jan 2012 10:35:13 +0000 (11:35 +0100)
... to arrange for a clean READY to PAUSED state change transition.
Not doing so might have playsink reaching PAUSED prematurely
as one track prerolls, only to lose this state again (temporarily)
when the other track needs to preroll.

This is generally not nice or convenient, and particularly nasty
when trying to perform seek in PAUSED.

ges/ges-timeline-pipeline.c
ges/ges-timeline.c

index 6aca47996423dc059e6c7039f8980fbaa1f2f8a7..5a404f0c135ed85157ea67ce884edec0cda65e4b 100644 (file)
@@ -44,6 +44,7 @@ typedef struct
   GstPad *srcpad;               /* Timeline source pad */
   GstPad *playsinkpad;
   GstPad *encodebinpad;
+  GstPad *blocked_pad;
 } OutputChain;
 
 G_DEFINE_TYPE (GESTimelinePipeline, ges_timeline_pipeline, GST_TYPE_PIPELINE);
@@ -382,6 +383,13 @@ no_pad:
   }
 }
 
+static void
+pad_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
+{
+  /* no nothing */
+  GST_DEBUG_OBJECT (pad, "blocked callback, blocked: %d", blocked);
+}
+
 static void
 pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
 {
@@ -466,7 +474,9 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
       gst_object_unref (tmppad);
       goto error;
     }
-    gst_object_unref (tmppad);
+    chain->blocked_pad = tmppad;
+    GST_DEBUG ("blocking pad %" GST_PTR_FORMAT, tmppad);
+    gst_pad_set_blocked_async (tmppad, TRUE, pad_blocked, NULL);
 
     GST_DEBUG ("Reconfiguring playsink");
 
@@ -568,6 +578,13 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
     gst_object_unref (chain->playsinkpad);
   }
 
+  if (chain->blocked_pad) {
+    GST_DEBUG ("unblocking pad %" GST_PTR_FORMAT, chain->blocked_pad);
+    gst_pad_set_blocked_async (chain->blocked_pad, FALSE, pad_blocked, NULL);
+    gst_object_unref (chain->blocked_pad);
+    chain->blocked_pad = NULL;
+  }
+
   /* Unlike/remove tee */
   peer = gst_element_get_static_pad (chain->tee, "sink");
   gst_pad_unlink (pad, peer);
@@ -581,6 +598,22 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
   GST_DEBUG ("done");
 }
 
+static void
+no_more_pads_cb (GstElement * timeline, GESTimelinePipeline * self)
+{
+  GList *tmp;
+
+  GST_DEBUG ("received no-more-pads");
+  for (tmp = self->priv->chains; tmp; tmp = g_list_next (tmp)) {
+    OutputChain *chain = (OutputChain *) tmp->data;
+
+    if (chain->blocked_pad) {
+      GST_DEBUG ("unblocking pad %" GST_PTR_FORMAT, chain->blocked_pad);
+      gst_pad_set_blocked_async (chain->blocked_pad, FALSE, pad_blocked, NULL);
+    }
+  }
+}
+
 /**
  * ges_timeline_pipeline_add_timeline:
  * @pipeline: a #GESTimelinePipeline
@@ -612,6 +645,8 @@ ges_timeline_pipeline_add_timeline (GESTimelinePipeline * pipeline,
   g_signal_connect (timeline, "pad-added", (GCallback) pad_added_cb, pipeline);
   g_signal_connect (timeline, "pad-removed", (GCallback) pad_removed_cb,
       pipeline);
+  g_signal_connect (timeline, "no-more-pads", (GCallback) no_more_pads_cb,
+      pipeline);
 
   return TRUE;
 }
index 6c42e5f1733729ecdcff687cae68847918518e11..65bf307a6027a0ea600f692d66797b5e60d8b5c8 100644 (file)
@@ -908,7 +908,8 @@ static void
 pad_added_cb (GESTrack * track, GstPad * pad, TrackPrivate * tr_priv)
 {
   gchar *padname;
-
+  gboolean no_more;
+  GList *tmp;
 
   GST_DEBUG ("track:%p, pad:%s:%s", track, GST_DEBUG_PAD_NAME (pad));
 
@@ -918,8 +919,20 @@ pad_added_cb (GESTrack * track, GstPad * pad, TrackPrivate * tr_priv)
   }
 
   /* Remember the pad */
+  GST_OBJECT_LOCK (track);
   tr_priv->pad = pad;
 
+  no_more = TRUE;
+  for (tmp = tr_priv->timeline->priv->tracks; tmp; tmp = g_list_next (tmp)) {
+    TrackPrivate *tr_priv = (TrackPrivate *) tmp->data;
+
+    if (!tr_priv->pad) {
+      GST_LOG ("Found track without pad %p", tr_priv->track);
+      no_more = FALSE;
+    }
+  }
+  GST_OBJECT_UNLOCK (track);
+
   /* ghost it ! */
   GST_DEBUG ("Ghosting pad and adding it to ourself");
   padname = g_strdup_printf ("track_%p_src", track);
@@ -927,6 +940,11 @@ pad_added_cb (GESTrack * track, GstPad * pad, TrackPrivate * tr_priv)
   g_free (padname);
   gst_pad_set_active (tr_priv->ghostpad, TRUE);
   gst_element_add_pad (GST_ELEMENT (tr_priv->timeline), tr_priv->ghostpad);
+
+  if (no_more) {
+    GST_DEBUG ("Signaling no-more-pads");
+    gst_element_no_more_pads (GST_ELEMENT (tr_priv->timeline));
+  }
 }
 
 static void