mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
pad: Rename and rework the dispatcher function
Rename gst_pad_dispatcher() to gst_pad_forward() and make it more useful by iterating the internal links of a pad and handling resync properly. Add a method gst_pad_event_forward() that unconditionally forwards an event to all internally linked pads. Update some pad code to use the new forward function.
This commit is contained in:
parent
a767bf2bf9
commit
9058499eeb
2 changed files with 102 additions and 132 deletions
217
gst/gstpad.c
217
gst/gstpad.c
|
@ -1448,8 +1448,12 @@ no_func:
|
|||
static gboolean
|
||||
gst_pad_get_query_types_dispatcher (GstPad * pad, const GstQueryType ** data)
|
||||
{
|
||||
*data = gst_pad_get_query_types (pad);
|
||||
GstPad *peer;
|
||||
|
||||
if ((peer = gst_pad_get_peer (pad))) {
|
||||
*data = gst_pad_get_query_types (peer);
|
||||
gst_object_unref (peer);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1457,8 +1461,8 @@ gst_pad_get_query_types_dispatcher (GstPad * pad, const GstQueryType ** data)
|
|||
* gst_pad_get_query_types_default:
|
||||
* @pad: a #GstPad.
|
||||
*
|
||||
* Invoke the default dispatcher for the query types on
|
||||
* the pad.
|
||||
* Invoke the default query types function on the pad. This function will get
|
||||
* the supported query type from the peer of an internally linked pad of @pad.
|
||||
*
|
||||
* Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
|
||||
* of #GstQueryType, or NULL if none of the internally-linked pads has a
|
||||
|
@ -1471,7 +1475,7 @@ gst_pad_get_query_types_default (GstPad * pad)
|
|||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
|
||||
gst_pad_forward (pad, (GstPadForwardFunction)
|
||||
gst_pad_get_query_types_dispatcher, &result);
|
||||
|
||||
return result;
|
||||
|
@ -3086,19 +3090,30 @@ gst_pad_iterate_internal_links (GstPad * pad)
|
|||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
|
||||
/**
|
||||
* gst_pad_forward:
|
||||
* @pad: a #GstPad
|
||||
* @forward: a #GstPadForwardFunction
|
||||
* @user_data: user data passed to @forward
|
||||
*
|
||||
* Calls @forward for all internally linked pads of @pad. This function deals with
|
||||
* dynamically changing internal pads and will make sure that the @forward
|
||||
* function is only called once for each pad.
|
||||
*
|
||||
* When @forward returns TRUE, no further pads will be processed.
|
||||
*
|
||||
* Returns: TRUE if one of the dispatcher functions returned TRUE.
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_forward (GstPad * pad, GstPadForwardFunction forward,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstIterator *iter;
|
||||
gboolean done = FALSE;
|
||||
GValue item = { 0, };
|
||||
GstPad *eventpad;
|
||||
GList *pushed_pads = NULL;
|
||||
|
||||
GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads",
|
||||
event, GST_EVENT_TYPE_NAME (event));
|
||||
|
||||
iter = gst_pad_iterate_internal_links (pad);
|
||||
|
||||
if (!iter)
|
||||
|
@ -3107,37 +3122,26 @@ gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
|
|||
while (!done) {
|
||||
switch (gst_iterator_next (iter, &item)) {
|
||||
case GST_ITERATOR_OK:
|
||||
eventpad = g_value_get_object (&item);
|
||||
{
|
||||
GstPad *intpad;
|
||||
|
||||
/* if already pushed, skip */
|
||||
if (g_list_find (pushed_pads, eventpad)) {
|
||||
intpad = g_value_get_object (&item);
|
||||
|
||||
/* if already pushed, skip. FIXME, find something faster to tag pads */
|
||||
if (g_list_find (pushed_pads, intpad)) {
|
||||
g_value_reset (&item);
|
||||
break;
|
||||
}
|
||||
|
||||
if (GST_PAD_IS_SRC (eventpad)) {
|
||||
/* for each pad we send to, we should ref the event; it's up
|
||||
* to downstream to unref again when handled. */
|
||||
GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
|
||||
event, GST_EVENT_TYPE_NAME (event),
|
||||
GST_DEBUG_PAD_NAME (eventpad));
|
||||
gst_event_ref (event);
|
||||
result |= gst_pad_push_event (eventpad, event);
|
||||
} else {
|
||||
/* we only send the event on one pad, multi-sinkpad elements
|
||||
* should implement a handler */
|
||||
GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
|
||||
event, GST_EVENT_TYPE_NAME (event),
|
||||
GST_DEBUG_PAD_NAME (eventpad));
|
||||
result = gst_pad_push_event (eventpad, event);
|
||||
done = TRUE;
|
||||
event = NULL;
|
||||
}
|
||||
GST_LOG_OBJECT (pad, "calling forward function on pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (intpad));
|
||||
done = result = forward (intpad, user_data);
|
||||
|
||||
pushed_pads = g_list_prepend (pushed_pads, eventpad);
|
||||
pushed_pads = g_list_prepend (pushed_pads, intpad);
|
||||
|
||||
g_value_reset (&item);
|
||||
break;
|
||||
}
|
||||
case GST_ITERATOR_RESYNC:
|
||||
/* We don't reset the result here because we don't push the event
|
||||
* again on pads that got the event already and because we need
|
||||
|
@ -3156,35 +3160,70 @@ gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
|
|||
g_value_unset (&item);
|
||||
gst_iterator_free (iter);
|
||||
|
||||
no_iter:
|
||||
|
||||
/* If this is a sinkpad and we don't have pads to send the event to, we
|
||||
* return TRUE. This is so that when using the default handler on a sink
|
||||
* element, we don't fail to push it. */
|
||||
if (!pushed_pads)
|
||||
result = GST_PAD_IS_SINK (pad);
|
||||
|
||||
g_list_free (pushed_pads);
|
||||
|
||||
/* we handled the incoming event so we unref once */
|
||||
if (event) {
|
||||
GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
|
||||
gst_event_unref (event);
|
||||
}
|
||||
|
||||
no_iter:
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstEvent *event;
|
||||
gboolean res;
|
||||
} EventData;
|
||||
|
||||
static gboolean
|
||||
event_forward_func (GstPad * pad, EventData * data)
|
||||
{
|
||||
/* for each pad we send to, we should ref the event; it's up
|
||||
* to downstream to unref again when handled. */
|
||||
GST_LOG_OBJECT (pad, "Reffing and pushing event %p (%s) to %s:%s",
|
||||
data->event, GST_EVENT_TYPE_NAME (data->event), GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
data->res |= gst_pad_push_event (pad, gst_event_ref (data->event));
|
||||
|
||||
/* don't stop */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_event_forward:
|
||||
* @pad: a #GstPad
|
||||
* @event: (transfer full): the #GstEvent to handle.
|
||||
*
|
||||
* Forward @event to all internally linked pads of @pad.
|
||||
*
|
||||
* Returns: TRUE if the event was sent succesfully.
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_event_forward (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
EventData data;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
data.event = event;
|
||||
data.res = FALSE;
|
||||
|
||||
gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data);
|
||||
|
||||
return data.res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_event_default:
|
||||
* @pad: a #GstPad to call the default event handler on.
|
||||
* @event: (transfer full): the #GstEvent to handle.
|
||||
*
|
||||
* Invokes the default event handler for the given pad. End-of-stream and
|
||||
* discontinuity events are handled specially, and then the event is sent to all
|
||||
* pads internally linked to @pad. Note that if there are many possible sink
|
||||
* pads that are internally linked to @pad, only one will be sent an event.
|
||||
* Multi-sinkpad elements should implement custom event handlers.
|
||||
* Invokes the default event handler for the given pad.
|
||||
*
|
||||
* The EOS event will pause the task associated with @pad before it is forwarded
|
||||
* to all internally linked pads,
|
||||
*
|
||||
* The CAPS event will never be forwarded.
|
||||
*
|
||||
* The the event is sent to all pads internally linked to @pad.
|
||||
*
|
||||
* Returns: TRUE if the event was sent succesfully.
|
||||
*/
|
||||
|
@ -3216,83 +3255,13 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
|
|||
}
|
||||
|
||||
if (forward)
|
||||
result = gst_pad_event_default_dispatch (pad, event);
|
||||
result = gst_pad_event_forward (pad, event);
|
||||
else
|
||||
gst_event_unref (event);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_dispatcher:
|
||||
* @pad: a #GstPad to dispatch.
|
||||
* @dispatch: the #GstPadDispatcherFunction to call.
|
||||
* @data: (closure): gpointer user data passed to the dispatcher function.
|
||||
*
|
||||
* Invokes the given dispatcher function on each respective peer of
|
||||
* all pads that are internally linked to the given pad.
|
||||
* The GstPadDispatcherFunction should return TRUE when no further pads
|
||||
* need to be processed.
|
||||
*
|
||||
* Returns: TRUE if one of the dispatcher functions returned TRUE.
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
GstIterator *iter = NULL;
|
||||
gboolean done = FALSE;
|
||||
GValue item = { 0, };
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (dispatch != NULL, FALSE);
|
||||
|
||||
iter = gst_pad_iterate_internal_links (pad);
|
||||
|
||||
if (!iter)
|
||||
goto no_iter;
|
||||
|
||||
while (!done) {
|
||||
switch (gst_iterator_next (iter, &item)) {
|
||||
case GST_ITERATOR_OK:
|
||||
{
|
||||
GstPad *int_pad = g_value_get_object (&item);
|
||||
GstPad *int_peer = gst_pad_get_peer (int_pad);
|
||||
|
||||
if (int_peer) {
|
||||
GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
|
||||
GST_DEBUG_PAD_NAME (int_peer));
|
||||
done = res = dispatch (int_peer, data);
|
||||
gst_object_unref (int_peer);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (int_pad, "no peer");
|
||||
}
|
||||
g_value_reset (&item);
|
||||
}
|
||||
break;
|
||||
case GST_ITERATOR_RESYNC:
|
||||
gst_iterator_resync (iter);
|
||||
break;
|
||||
case GST_ITERATOR_ERROR:
|
||||
done = TRUE;
|
||||
GST_ERROR_OBJECT (pad, "Could not iterate internally linked pads");
|
||||
break;
|
||||
case GST_ITERATOR_DONE:
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_value_unset (&item);
|
||||
gst_iterator_free (iter);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "done, result %d", res);
|
||||
|
||||
no_iter:
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_query:
|
||||
* @pad: a #GstPad to invoke the default query on.
|
||||
|
@ -3416,8 +3385,8 @@ gst_pad_query_default (GstPad * pad, GstQuery * query)
|
|||
case GST_QUERY_RATE:
|
||||
case GST_QUERY_CONVERT:
|
||||
default:
|
||||
return gst_pad_dispatcher
|
||||
(pad, (GstPadDispatcherFunction) gst_pad_query, query);
|
||||
return gst_pad_forward
|
||||
(pad, (GstPadForwardFunction) gst_pad_peer_query, query);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
gst/gstpad.h
17
gst/gstpad.h
|
@ -459,16 +459,16 @@ typedef void (*GstPadFixateCapsFunction) (GstPad *pad, GstCaps *caps);
|
|||
|
||||
/* misc */
|
||||
/**
|
||||
* GstPadDispatcherFunction:
|
||||
* @pad: the #GstPad that is dispatched.
|
||||
* @data: the gpointer to optional user data.
|
||||
* GstPadForwardFunction:
|
||||
* @pad: the #GstPad that is forwarded.
|
||||
* @user_data: the gpointer to optional user data.
|
||||
*
|
||||
* A dispatcher function is called for all internally linked pads, see
|
||||
* gst_pad_dispatcher().
|
||||
* A forward function is called for all internally linked pads, see
|
||||
* gst_pad_forward().
|
||||
*
|
||||
* Returns: TRUE if the dispatching procedure has to be stopped.
|
||||
*/
|
||||
typedef gboolean (*GstPadDispatcherFunction) (GstPad *pad, gpointer data);
|
||||
typedef gboolean (*GstPadForwardFunction) (GstPad *pad, gpointer user_data);
|
||||
|
||||
/**
|
||||
* GstProbeType:
|
||||
|
@ -912,6 +912,7 @@ GstFlowReturn gst_pad_pull_range (GstPad *pad, guint64 offset, guint size,
|
|||
GstBuffer **buffer);
|
||||
gboolean gst_pad_push_event (GstPad *pad, GstEvent *event);
|
||||
gboolean gst_pad_event_default (GstPad *pad, GstEvent *event);
|
||||
gboolean gst_pad_event_forward (GstPad *pad, GstEvent *event);
|
||||
|
||||
/* data passing functions on pad */
|
||||
GstFlowReturn gst_pad_chain (GstPad *pad, GstBuffer *buffer);
|
||||
|
@ -946,8 +947,8 @@ void gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query);
|
|||
gboolean gst_pad_query_default (GstPad *pad, GstQuery *query);
|
||||
|
||||
/* misc helper functions */
|
||||
gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch,
|
||||
gpointer data);
|
||||
gboolean gst_pad_forward (GstPad *pad, GstPadForwardFunction forward,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
Loading…
Reference in a new issue