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.
This commit is contained in:
Mark Nauwelaerts 2012-01-30 11:34:09 +01:00
parent ee237ec523
commit 2162c635e2
2 changed files with 55 additions and 2 deletions

View 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;
}

View 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