gst-editing-services: ges: support and handle no-more-pads in GESTimeline( Pipeline)

Mark Nauwelaerts mnauw at kemper.freedesktop.org
Mon Jan 30 02:37:02 PST 2012


Module: gst-editing-services
Branch: master
Commit: 2162c635e260fd28644f64c926540cfb60c68539
URL:    http://cgit.freedesktop.org/gstreamer/gst-editing-services/commit/?id=2162c635e260fd28644f64c926540cfb60c68539

Author: Mark Nauwelaerts <mark.nauwelaerts at collabora.co.uk>
Date:   Mon Jan 30 11:34:09 2012 +0100

ges: support and handle no-more-pads in GESTimeline(Pipeline)

... 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 |   37 ++++++++++++++++++++++++++++++++++++-
 ges/ges-timeline.c          |   20 +++++++++++++++++++-
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/ges/ges-timeline-pipeline.c b/ges/ges-timeline-pipeline.c
index 6aca479..5a404f0 100644
--- a/ges/ges-timeline-pipeline.c
+++ b/ges/ges-timeline-pipeline.c
@@ -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);
@@ -383,6 +384,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)
 {
   OutputChain *chain;
@@ -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;
 }
diff --git a/ges/ges-timeline.c b/ges/ges-timeline.c
index 6c42e5f..65bf307 100644
--- a/ges/ges-timeline.c
+++ b/ges/ges-timeline.c
@@ -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



More information about the gstreamer-commits mailing list