pad: move caps check to central location

Make a function to call the eventfunc and perform a caps check when we are
dispatching a caps event.

This makes sure that all code paths correctly check that the caps are
acceptable before sending the caps to the eventfunction.
This commit is contained in:
Wim Taymans 2011-05-18 18:53:35 +02:00
parent 25989f3c8d
commit 500125ab4f

View file

@ -2766,29 +2766,47 @@ setcaps_failed:
} }
} }
static GstFlowReturn static gboolean
gst_pad_configure_sink (GstPad * pad, GstCaps * caps) do_event_function (GstPad * pad, GstEvent * event,
GstPadEventFunction eventfunc)
{ {
GstCaps *templ; gboolean result = TRUE;
GstCaps *caps, *templ;
/* See if pad accepts the caps */ switch (GST_EVENT_TYPE (event)) {
templ = gst_pad_get_pad_template_caps (pad); case GST_EVENT_CAPS:
if (!gst_caps_can_intersect (caps, templ)) {
goto not_accepted; /* backwards compatibility mode for caps */
gst_event_parse_caps (event, &caps);
if (!gst_pad_call_setcaps (pad, caps)) /* See if pad accepts the caps */
goto not_accepted; templ = gst_pad_get_pad_template_caps (pad);
if (!gst_caps_can_intersect (caps, templ))
goto not_accepted;
gst_caps_unref (templ); if (!gst_pad_call_setcaps (pad, caps))
goto not_accepted;
return GST_FLOW_OK; gst_caps_unref (templ);
break;
}
default:
break;
}
GST_DEBUG_OBJECT (pad, "calling event function with event %p", event);
result = eventfunc (pad, event);
return result;
/* ERRORS */
not_accepted: not_accepted:
{ {
gst_caps_unref (templ); gst_caps_unref (templ);
gst_event_unref (event);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"caps %" GST_PTR_FORMAT " not accepted", caps); "caps %" GST_PTR_FORMAT " not accepted", caps);
return GST_FLOW_NOT_NEGOTIATED; return FALSE;
} }
} }
@ -2807,6 +2825,7 @@ gst_pad_update_events (GstPad * pad)
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL)) if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
goto no_function; goto no_function;
restart:
for (i = 0; i < GST_EVENT_MAX_STICKY; i++) { for (i = 0; i < GST_EVENT_MAX_STICKY; i++) {
/* skip already active events */ /* skip already active events */
if (pad->priv->events[i].active) if (pad->priv->events[i].active)
@ -2818,11 +2837,17 @@ gst_pad_update_events (GstPad * pad)
gst_event_ref (event); gst_event_ref (event);
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
res = eventfunc (pad, event); res = do_event_function (pad, event, eventfunc);
GST_OBJECT_LOCK (pad); GST_OBJECT_LOCK (pad);
/* FIXME, things could have changed here, probably use a cookie /* things could have changed while we release the lock, check if we still
* to check for changes. */ * are handling the same event, if we don't something changed and we have
* to try again. FIXME. we need a cookie here. */
if (event != pad->priv->events[i].event) {
GST_DEBUG_OBJECT (pad, "events changed, restarting");
goto restart;
}
pad->priv->events[i].active = res; pad->priv->events[i].active = res;
/* remove the event when the event function did not accept it */ /* remove the event when the event function did not accept it */
if (!res) { if (!res) {
@ -3220,13 +3245,6 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
} }
case GST_EVENT_CAPS: case GST_EVENT_CAPS:
{ {
GstCaps *caps;
/* backwards compatibility mode for caps */
gst_event_parse_caps (event, &caps);
if (gst_pad_configure_sink (pad, caps) != GST_FLOW_OK)
result = FALSE;
/* don't forward by default */ /* don't forward by default */
forward = FALSE; forward = FALSE;
break; break;
@ -4673,7 +4691,6 @@ gboolean
gst_pad_send_event (GstPad * pad, GstEvent * event) gst_pad_send_event (GstPad * pad, GstEvent * event)
{ {
gboolean result = FALSE; gboolean result = FALSE;
GstPadEventFunction eventfunc;
gboolean serialized, need_unlock = FALSE, needs_events, sticky; gboolean serialized, need_unlock = FALSE, needs_events, sticky;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
@ -4774,24 +4791,29 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
} }
} }
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
goto no_function;
if (G_UNLIKELY (needs_events)) { if (G_UNLIKELY (needs_events)) {
GstFlowReturn ret;
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_NEED_EVENTS); GST_OBJECT_FLAG_UNSET (pad, GST_PAD_NEED_EVENTS);
GST_DEBUG_OBJECT (pad, "need to update all events"); GST_DEBUG_OBJECT (pad, "need to update all events");
if (gst_pad_update_events (pad) != GST_FLOW_OK) ret = gst_pad_update_events (pad);
result = FALSE; if (ret != GST_FLOW_OK)
else goto update_failed;
result = TRUE;
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
gst_event_unref (event); gst_event_unref (event);
result = TRUE;
} else { } else {
GstPadEventFunction eventfunc;
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
goto no_function;
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
result = eventfunc (pad, event); result = do_event_function (pad, event, eventfunc);
} }
if (need_unlock) if (need_unlock)
@ -4843,6 +4865,15 @@ dropping:
gst_event_unref (event); gst_event_unref (event);
return FALSE; return FALSE;
} }
update_failed:
{
GST_OBJECT_UNLOCK (pad);
if (need_unlock)
GST_PAD_STREAM_UNLOCK (pad);
GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad, "Update events failed");
gst_event_unref (event);
return FALSE;
}
} }
/** /**