basetransform: delay serialized events when src caps are not set yet

https://bugzilla.gnome.org/show_bug.cgi?id=659571
This commit is contained in:
Vincent Penquerc'h 2011-09-20 13:04:06 +01:00 committed by Sebastian Dröge
parent b090a376d4
commit 56b3acb043

View file

@ -281,6 +281,7 @@ struct _GstBaseTransformPrivate
guint64 dropped;
GstClockTime last_stop_out;
GList *delayed_events;
};
static GstElementClass *parent_class = NULL;
@ -356,6 +357,18 @@ static const GstQueryType *gst_base_transform_query_type (GstPad * pad);
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
static void
gst_base_transform_drop_delayed_events (GstBaseTransform * trans)
{
GST_OBJECT_LOCK (trans);
if (trans->priv->delayed_events) {
g_list_foreach (trans->priv->delayed_events, (GFunc) gst_event_unref, NULL);
g_list_free (trans->priv->delayed_events);
trans->priv->delayed_events = NULL;
}
GST_OBJECT_UNLOCK (trans);
}
static void
gst_base_transform_finalize (GObject * object)
{
@ -363,6 +376,7 @@ gst_base_transform_finalize (GObject * object)
trans = GST_BASE_TRANSFORM (object);
gst_base_transform_drop_delayed_events (trans);
gst_caps_replace (&trans->priv->sink_suggest, NULL);
g_mutex_free (trans->transform_lock);
@ -465,6 +479,7 @@ gst_base_transform_init (GstBaseTransform * trans,
trans->cache_caps2 = NULL;
trans->priv->pad_mode = GST_ACTIVATE_NONE;
trans->priv->gap_aware = FALSE;
trans->priv->delayed_events = NULL;
trans->passthrough = FALSE;
if (bclass->transform == NULL) {
@ -2036,6 +2051,28 @@ not_supported:
}
}
static void
gst_base_transform_send_delayed_events (GstBaseTransform * trans)
{
GList *list, *tmp;
GST_OBJECT_LOCK (trans);
list = trans->priv->delayed_events;
trans->priv->delayed_events = NULL;
GST_OBJECT_UNLOCK (trans);
if (!list)
return;
for (tmp = list; tmp; tmp = tmp->next) {
GstEvent *ev = tmp->data;
GST_DEBUG_OBJECT (trans->srcpad, "Sending delayed event %s",
GST_EVENT_TYPE_NAME (ev));
gst_pad_push_event (trans->srcpad, ev);
}
g_list_free (list);
}
static gboolean
gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
{
@ -2056,9 +2093,31 @@ gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
/* FIXME, do this in the default event handler so the subclass can do
* something different. */
if (forward)
ret = gst_pad_push_event (trans->srcpad, event);
else
if (forward) {
gboolean delay, caps_set = (GST_PAD_CAPS (trans->srcpad) != NULL);
/* src caps may not yet be set, so we delay any serialized events
that we receive before (in particular newsegment events), except
EOS and flush stops, since those'll obsolete previous events */
if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
gst_base_transform_drop_delayed_events (trans);
delay = FALSE;
} else {
delay = GST_EVENT_IS_SERIALIZED (event) && !caps_set
&& GST_EVENT_TYPE (event) != GST_EVENT_EOS;
}
if (delay) {
GST_OBJECT_LOCK (trans);
trans->priv->delayed_events =
g_list_append (trans->priv->delayed_events, event);
GST_OBJECT_UNLOCK (trans);
} else {
if (caps_set && GST_EVENT_IS_SERIALIZED (event))
gst_base_transform_send_delayed_events (trans);
ret = gst_pad_push_event (trans->srcpad, event);
}
} else
gst_event_unref (event);
gst_object_unref (trans);
@ -2494,6 +2553,9 @@ gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
trans->priv->discont = FALSE;
}
trans->priv->processed++;
gst_base_transform_send_delayed_events (trans);
ret = gst_pad_push (trans->srcpad, outbuf);
} else {
gst_buffer_unref (outbuf);
@ -2586,6 +2648,8 @@ gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
GST_PAD_STREAM_LOCK (trans->sinkpad);
GST_PAD_STREAM_UNLOCK (trans->sinkpad);
gst_base_transform_drop_delayed_events (trans);
trans->have_same_caps = FALSE;
/* We can only reset the passthrough mode if the instance told us to
handle it in configure_caps */