pad: make serialized queries push sticky events first

Before we can proceed with a serialized query, we need to be sure that all
sticky events were pushed.
This commit is contained in:
Wim Taymans 2012-03-14 16:01:15 +01:00
parent 9e2ef19dc2
commit 05cd564bea

View file

@ -3099,6 +3099,58 @@ done:
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
} }
/* should be called with pad LOCK */
static gboolean
push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
{
GstFlowReturn *data = user_data;
GstEvent *event = ev->event;
if (ev->received) {
GST_DEBUG_OBJECT (pad, "event %s was already received",
GST_EVENT_TYPE_NAME (event));
return TRUE;
}
*data = gst_pad_push_event_unchecked (pad, gst_event_ref (event),
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM);
switch (*data) {
case GST_FLOW_OK:
ev->received = TRUE;
GST_DEBUG_OBJECT (pad, "event %s marked received",
GST_EVENT_TYPE_NAME (event));
break;
case GST_FLOW_NOT_LINKED:
/* not linked is not a problem, we are sticky so the event will be
* sent later */
GST_DEBUG_OBJECT (pad, "pad was not linked");
*data = GST_FLOW_OK;
/* fallthrough */
default:
GST_DEBUG_OBJECT (pad, "mark pending events");
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
break;
}
return *data == GST_FLOW_OK;
}
/* check sticky events and push them when needed. should be called
* with pad LOCK */
static inline GstFlowReturn
check_sticky (GstPad * pad)
{
GstFlowReturn ret = GST_FLOW_OK;
if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
GST_DEBUG_OBJECT (pad, "pushing all sticky events");
events_foreach (pad, push_sticky, &ret);
}
return ret;
}
/** /**
* gst_pad_query: * gst_pad_query:
@ -3243,7 +3295,7 @@ gst_pad_peer_query (GstPad * pad, GstQuery * query)
{ {
GstPad *peerpad; GstPad *peerpad;
GstPadProbeType type; GstPadProbeType type;
gboolean res; gboolean res, serialized;
GstFlowReturn ret; GstFlowReturn ret;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
@ -3263,7 +3315,16 @@ gst_pad_peer_query (GstPad * pad, GstQuery * query)
GST_DEBUG_OBJECT (pad, "peer query %p (%s)", query, GST_DEBUG_OBJECT (pad, "peer query %p (%s)", query,
GST_QUERY_TYPE_NAME (query)); GST_QUERY_TYPE_NAME (query));
serialized = GST_QUERY_IS_SERIALIZED (query);
GST_OBJECT_LOCK (pad); GST_OBJECT_LOCK (pad);
if (GST_PAD_IS_SRC (pad) && serialized) {
/* all serialized queries on the srcpad trigger push of
* sticky events */
if (!check_sticky (pad) == GST_FLOW_OK)
goto sticky_failed;
}
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH | PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped); GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped);
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped); PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped);
@ -3300,6 +3361,12 @@ unknown_direction:
g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
return FALSE; return FALSE;
} }
sticky_failed:
{
GST_WARNING_OBJECT (pad, "could not send sticky events");
GST_OBJECT_UNLOCK (pad);
return FALSE;
}
no_peer: no_peer:
{ {
GST_WARNING_OBJECT (pad, "pad has no peer"); GST_WARNING_OBJECT (pad, "pad has no peer");
@ -3323,58 +3390,6 @@ probe_stopped:
* Data passing functions * Data passing functions
*/ */
/* should be called with pad LOCK */
static gboolean
push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
{
GstFlowReturn *data = user_data;
GstEvent *event = ev->event;
if (ev->received) {
GST_DEBUG_OBJECT (pad, "event %s was already received",
GST_EVENT_TYPE_NAME (event));
return TRUE;
}
*data = gst_pad_push_event_unchecked (pad, gst_event_ref (event),
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM);
switch (*data) {
case GST_FLOW_OK:
ev->received = TRUE;
GST_DEBUG_OBJECT (pad, "event %s marked received",
GST_EVENT_TYPE_NAME (event));
break;
case GST_FLOW_NOT_LINKED:
/* not linked is not a problem, we are sticky so the event will be
* sent later */
GST_DEBUG_OBJECT (pad, "pad was not linked");
*data = GST_FLOW_OK;
/* fallthrough */
default:
GST_DEBUG_OBJECT (pad, "mark pending events");
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
break;
}
return *data == GST_FLOW_OK;
}
/* check sticky events and push them when needed. should be called
* with pad LOCK */
static inline GstFlowReturn
check_sticky (GstPad * pad)
{
GstFlowReturn ret = GST_FLOW_OK;
if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
GST_DEBUG_OBJECT (pad, "pushing all sticky events");
events_foreach (pad, push_sticky, &ret);
}
return ret;
}
/* this is the chain function that does not perform the additional argument /* this is the chain function that does not perform the additional argument
* checking for that little extra speed. * checking for that little extra speed.
*/ */