}
}
+#define ACQUIRE_PARENT(pad, parent, label) \
+ G_STMT_START { \
+ if (G_LIKELY ((parent = GST_OBJECT_PARENT (pad)))) \
+ gst_object_ref (parent); \
+ else if (G_LIKELY (GST_PAD_NEEDS_PARENT (pad))) \
+ goto label; \
+ } G_STMT_END
+
+#define RELEASE_PARENT(parent) \
+ G_STMT_START { \
+ if (G_LIKELY (parent)) \
+ gst_object_unref (parent); \
+ } G_STMT_END
+
/* function to send all pending events on the sinkpad to the event
* function and collect the results. This function should be called with
* the object lock. The object lock might be released by this function.
static GstFlowReturn
gst_pad_update_events (GstPad * pad)
{
+ GstObject *parent;
GstFlowReturn ret = GST_FLOW_OK;
guint i;
GstPadEventFunction eventfunc;
GstEvent *event;
gboolean caps_notify = FALSE;
+ PadEvent *ev;
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
goto no_function;
for (i = 0; i < GST_EVENT_MAX_STICKY; i++) {
gboolean res;
- PadEvent *ev;
ev = &pad->priv->events[i];
if ((event = gst_event_steal (&ev->pending)) == NULL)
continue;
+ ACQUIRE_PARENT (pad, parent, no_parent);
+
gst_event_ref (event);
GST_OBJECT_UNLOCK (pad);
res = do_event_function (pad, event, eventfunc, &caps_notify);
+ RELEASE_PARENT (parent);
+
/* things could have changed while we release the lock, check if we still
* are handling the same event, if we don't something changed and we have
* to try again. FIXME. we need a cookie here. FIXME, we also want to remove
GST_DEBUG_PAD_NAME (pad));
return GST_FLOW_NOT_SUPPORTED;
}
+no_parent:
+ {
+ GST_DEBUG_OBJECT (pad, "pad has no parent");
+ gst_event_take (&ev->pending, event);
+ return GST_FLOW_WRONG_STATE;
+ }
}
/**
gst_pad_iterate_internal_links (GstPad * pad)
{
GstIterator *res = NULL;
+ GstObject *parent;
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+ GST_OBJECT_LOCK (pad);
+ ACQUIRE_PARENT (pad, parent, no_parent);
+ GST_OBJECT_UNLOCK (pad);
+
if (GST_PAD_ITERINTLINKFUNC (pad))
res = GST_PAD_ITERINTLINKFUNC (pad) (pad);
+ RELEASE_PARENT (parent);
+
return res;
+
+ /* ERRORS */
+no_parent:
+ {
+ GST_DEBUG_OBJECT (pad, "no parent");
+ GST_OBJECT_UNLOCK (pad);
+ return FALSE;
+ }
}
/**
gboolean
gst_pad_query (GstPad * pad, GstQuery * query)
{
+ GstObject *parent;
gboolean res;
GstPadQueryFunction func;
GstPadProbeType type;
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped);
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped);
+
+ ACQUIRE_PARENT (pad, parent, no_parent);
GST_OBJECT_UNLOCK (pad);
if ((func = GST_PAD_QUERYFUNC (pad)) == NULL)
res = func (pad, query);
+ RELEASE_PARENT (parent);
+
GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query,
GST_QUERY_TYPE_NAME (query), res);
return res;
+ /* ERRORS */
+no_parent:
+ {
+ GST_DEBUG_OBJECT (pad, "had no parent");
+ GST_OBJECT_UNLOCK (pad);
+ return FALSE;
+ }
no_func:
{
GST_DEBUG_OBJECT (pad, "had no query function");
* note that a sticky event has already been updated above */
if (G_LIKELY (!needs_events || !sticky)) {
GstPadEventFunction eventfunc;
+ GstObject *parent;
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
goto no_function;
+ ACQUIRE_PARENT (pad, parent, no_parent);
GST_OBJECT_UNLOCK (pad);
result = eventfunc (pad, event);
+
+ RELEASE_PARENT (parent);
}
if (need_unlock)
gst_event_unref (event);
return FALSE;
}
+no_parent:
+ {
+ GST_DEBUG_OBJECT (pad, "no parent");
+ GST_OBJECT_UNLOCK (pad);
+ if (need_unlock)
+ GST_PAD_STREAM_UNLOCK (pad);
+ gst_event_unref (event);
+ return FALSE;
+ }
flushing:
{
GST_OBJECT_UNLOCK (pad);
* @GST_PAD_PROXY_CAPS: the default event and query handler will forward
* all events and queries to the internally linked pads
* instead of discarding them.
+ * @GST_PAD_NEED_PARENT: ensure that there is a parent object before calling
+ * into the pad callbacks.
* @GST_PAD_FLAG_LAST: offset to define more flags
*
* Pad state flags
GST_PAD_NEED_EVENTS = (GST_OBJECT_FLAG_LAST << 4),
GST_PAD_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 5),
GST_PAD_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 6),
+ GST_PAD_NEED_PARENT = (GST_OBJECT_FLAG_LAST << 7),
/* padding */
GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16)
} GstPadFlags;
#define GST_PAD_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_RECONFIGURE))
#define GST_PAD_NEEDS_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_EVENTS))
#define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FIXED_CAPS))
+#define GST_PAD_NEEDS_PARENT(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_PARENT))
#define GST_PAD_IS_PROXY_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_PROXY_CAPS))
#define GST_PAD_SET_PROXY_CAPS(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_PROXY_CAPS))