mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
pad: keep the parent alive when requested
Add a new pad flag NEED_PARENT that ensures that the parent of a pad is reffed and not NULL when the event, query and internal links functions are called. When a pad is added to an element automatically make sure the NEED_PARENT flag is enabled.
This commit is contained in:
parent
a641b0ce39
commit
fe3af1d67b
3 changed files with 71 additions and 1 deletions
|
@ -706,6 +706,7 @@ gst_element_add_pad (GstElement * element, GstPad * pad)
|
|||
GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
|
||||
GST_STR_NULL (pad_name));
|
||||
flushing = GST_PAD_IS_FLUSHING (pad);
|
||||
GST_OBJECT_FLAG_SET (pad, GST_PAD_NEED_PARENT);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
/* then check to see if there's already a pad by that name here */
|
||||
|
|
67
gst/gstpad.c
67
gst/gstpad.c
|
@ -2192,6 +2192,20 @@ not_accepted:
|
|||
}
|
||||
}
|
||||
|
||||
#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.
|
||||
|
@ -2199,18 +2213,19 @@ not_accepted:
|
|||
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];
|
||||
|
||||
|
@ -2218,11 +2233,15 @@ gst_pad_update_events (GstPad * pad)
|
|||
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
|
||||
|
@ -2253,6 +2272,12 @@ no_function:
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2451,13 +2476,28 @@ GstIterator *
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3115,6 +3155,7 @@ done:
|
|||
gboolean
|
||||
gst_pad_query (GstPad * pad, GstQuery * query)
|
||||
{
|
||||
GstObject *parent;
|
||||
gboolean res;
|
||||
GstPadQueryFunction func;
|
||||
GstPadProbeType type;
|
||||
|
@ -3135,6 +3176,8 @@ gst_pad_query (GstPad * pad, GstQuery * query)
|
|||
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)
|
||||
|
@ -3142,6 +3185,8 @@ gst_pad_query (GstPad * pad, GstQuery * query)
|
|||
|
||||
res = func (pad, query);
|
||||
|
||||
RELEASE_PARENT (parent);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query,
|
||||
GST_QUERY_TYPE_NAME (query), res);
|
||||
|
||||
|
@ -3154,6 +3199,13 @@ gst_pad_query (GstPad * pad, GstQuery * query)
|
|||
|
||||
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");
|
||||
|
@ -4252,13 +4304,17 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
|
|||
* 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)
|
||||
|
@ -4294,6 +4350,15 @@ no_function:
|
|||
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);
|
||||
|
|
|
@ -558,6 +558,8 @@ typedef GstFlowReturn (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEve
|
|||
* @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
|
||||
|
@ -570,6 +572,7 @@ typedef enum {
|
|||
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;
|
||||
|
@ -710,6 +713,7 @@ struct _GstPadClass {
|
|||
#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))
|
||||
|
|
Loading…
Reference in a new issue