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_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
|
||||||
GST_STR_NULL (pad_name));
|
GST_STR_NULL (pad_name));
|
||||||
flushing = GST_PAD_IS_FLUSHING (pad);
|
flushing = GST_PAD_IS_FLUSHING (pad);
|
||||||
|
GST_OBJECT_FLAG_SET (pad, GST_PAD_NEED_PARENT);
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
|
||||||
/* then check to see if there's already a pad by that name here */
|
/* 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 to send all pending events on the sinkpad to the event
|
||||||
* function and collect the results. This function should be called with
|
* function and collect the results. This function should be called with
|
||||||
* the object lock. The object lock might be released by this function.
|
* the object lock. The object lock might be released by this function.
|
||||||
|
@ -2199,18 +2213,19 @@ not_accepted:
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_pad_update_events (GstPad * pad)
|
gst_pad_update_events (GstPad * pad)
|
||||||
{
|
{
|
||||||
|
GstObject *parent;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
guint i;
|
guint i;
|
||||||
GstPadEventFunction eventfunc;
|
GstPadEventFunction eventfunc;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
gboolean caps_notify = FALSE;
|
gboolean caps_notify = FALSE;
|
||||||
|
PadEvent *ev;
|
||||||
|
|
||||||
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
|
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
|
||||||
goto no_function;
|
goto no_function;
|
||||||
|
|
||||||
for (i = 0; i < GST_EVENT_MAX_STICKY; i++) {
|
for (i = 0; i < GST_EVENT_MAX_STICKY; i++) {
|
||||||
gboolean res;
|
gboolean res;
|
||||||
PadEvent *ev;
|
|
||||||
|
|
||||||
ev = &pad->priv->events[i];
|
ev = &pad->priv->events[i];
|
||||||
|
|
||||||
|
@ -2218,11 +2233,15 @@ gst_pad_update_events (GstPad * pad)
|
||||||
if ((event = gst_event_steal (&ev->pending)) == NULL)
|
if ((event = gst_event_steal (&ev->pending)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ACQUIRE_PARENT (pad, parent, no_parent);
|
||||||
|
|
||||||
gst_event_ref (event);
|
gst_event_ref (event);
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
|
||||||
res = do_event_function (pad, event, eventfunc, &caps_notify);
|
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
|
/* 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
|
* 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
|
* 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));
|
GST_DEBUG_PAD_NAME (pad));
|
||||||
return GST_FLOW_NOT_SUPPORTED;
|
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)
|
gst_pad_iterate_internal_links (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstIterator *res = NULL;
|
GstIterator *res = NULL;
|
||||||
|
GstObject *parent;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
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))
|
if (GST_PAD_ITERINTLINKFUNC (pad))
|
||||||
res = GST_PAD_ITERINTLINKFUNC (pad) (pad);
|
res = GST_PAD_ITERINTLINKFUNC (pad) (pad);
|
||||||
|
|
||||||
|
RELEASE_PARENT (parent);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_parent:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (pad, "no parent");
|
||||||
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3115,6 +3155,7 @@ done:
|
||||||
gboolean
|
gboolean
|
||||||
gst_pad_query (GstPad * pad, GstQuery * query)
|
gst_pad_query (GstPad * pad, GstQuery * query)
|
||||||
{
|
{
|
||||||
|
GstObject *parent;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
GstPadQueryFunction func;
|
GstPadQueryFunction func;
|
||||||
GstPadProbeType type;
|
GstPadProbeType type;
|
||||||
|
@ -3135,6 +3176,8 @@ gst_pad_query (GstPad * pad, GstQuery * query)
|
||||||
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);
|
||||||
|
|
||||||
|
ACQUIRE_PARENT (pad, parent, no_parent);
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
|
||||||
if ((func = GST_PAD_QUERYFUNC (pad)) == NULL)
|
if ((func = GST_PAD_QUERYFUNC (pad)) == NULL)
|
||||||
|
@ -3142,6 +3185,8 @@ gst_pad_query (GstPad * pad, GstQuery * query)
|
||||||
|
|
||||||
res = func (pad, query);
|
res = func (pad, query);
|
||||||
|
|
||||||
|
RELEASE_PARENT (parent);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query,
|
GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query,
|
||||||
GST_QUERY_TYPE_NAME (query), res);
|
GST_QUERY_TYPE_NAME (query), res);
|
||||||
|
|
||||||
|
@ -3154,6 +3199,13 @@ gst_pad_query (GstPad * pad, GstQuery * query)
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_parent:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (pad, "had no parent");
|
||||||
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
no_func:
|
no_func:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (pad, "had no query function");
|
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 */
|
* note that a sticky event has already been updated above */
|
||||||
if (G_LIKELY (!needs_events || !sticky)) {
|
if (G_LIKELY (!needs_events || !sticky)) {
|
||||||
GstPadEventFunction eventfunc;
|
GstPadEventFunction eventfunc;
|
||||||
|
GstObject *parent;
|
||||||
|
|
||||||
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
|
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
|
||||||
goto no_function;
|
goto no_function;
|
||||||
|
|
||||||
|
ACQUIRE_PARENT (pad, parent, no_parent);
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
|
||||||
result = eventfunc (pad, event);
|
result = eventfunc (pad, event);
|
||||||
|
|
||||||
|
RELEASE_PARENT (parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_unlock)
|
if (need_unlock)
|
||||||
|
@ -4294,6 +4350,15 @@ no_function:
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
return FALSE;
|
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:
|
flushing:
|
||||||
{
|
{
|
||||||
GST_OBJECT_UNLOCK (pad);
|
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
|
* @GST_PAD_PROXY_CAPS: the default event and query handler will forward
|
||||||
* all events and queries to the internally linked pads
|
* all events and queries to the internally linked pads
|
||||||
* instead of discarding them.
|
* 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
|
* @GST_PAD_FLAG_LAST: offset to define more flags
|
||||||
*
|
*
|
||||||
* Pad state flags
|
* Pad state flags
|
||||||
|
@ -570,6 +572,7 @@ typedef enum {
|
||||||
GST_PAD_NEED_EVENTS = (GST_OBJECT_FLAG_LAST << 4),
|
GST_PAD_NEED_EVENTS = (GST_OBJECT_FLAG_LAST << 4),
|
||||||
GST_PAD_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 5),
|
GST_PAD_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 5),
|
||||||
GST_PAD_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 6),
|
GST_PAD_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 6),
|
||||||
|
GST_PAD_NEED_PARENT = (GST_OBJECT_FLAG_LAST << 7),
|
||||||
/* padding */
|
/* padding */
|
||||||
GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16)
|
GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16)
|
||||||
} GstPadFlags;
|
} 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_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_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_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_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))
|
#define GST_PAD_SET_PROXY_CAPS(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_PROXY_CAPS))
|
||||||
|
|
Loading…
Reference in a new issue