collectpads2: modify event handling using a default event handler

... that elements should "chain up" to.
This commit is contained in:
Mark Nauwelaerts 2012-04-16 16:24:10 +02:00
parent d342871907
commit 994357a16a
2 changed files with 96 additions and 69 deletions

View file

@ -155,6 +155,10 @@ static gboolean gst_collect_pads2_recalculate_full (GstCollectPads2 * pads);
static void ref_data (GstCollectData2 * data);
static void unref_data (GstCollectData2 * data);
static gboolean gst_collect_pads2_event_default_internal (GstCollectPads2 *
pads, GstCollectData2 * data, GstEvent * event, gpointer user_data);
/* Some properties are protected by LOCK, others by STREAM_LOCK
* However, manipulating either of these partitions may require
* to signal/wake a _WAIT, so use a separate (sort of) event to prevent races
@ -241,6 +245,8 @@ gst_collect_pads2_init (GstCollectPads2 * pads)
pads->priv->earliest_data = NULL;
pads->priv->earliest_time = GST_CLOCK_TIME_NONE;
pads->priv->event_func = gst_collect_pads2_event_default_internal;
/* members to manage the pad list */
pads->priv->pad_cookie = 0;
pads->priv->pad_list = NULL;
@ -424,8 +430,8 @@ unref_data (GstCollectData2 * data)
* @func: the function to set
* @user_data: user data passed to the function
*
* Set the event callback function and user data that will be called after
* collectpads has processed and event originating from one of the collected
* Set the event callback function and user data that will be called when
* collectpads has received an event originating from one of the collected
* pads. If the event being processed is a serialized one, this callback is
* called with @pads STREAM_LOCK held, otherwise not. As this lock should be
* held when calling a number of CollectPads functions, it should be acquired
@ -1640,47 +1646,41 @@ gst_collect_pads2_default_compare_func (GstCollectPads2 * pads,
return 0;
}
static gboolean
gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
/**
* gst_collect_pads2_event_default:
* @pads: the collectspads to use
* @data: collect data of corresponding pad
* @event: event being processed
* @discard: process but do not send event downstream
*
* Default GstCollectPads2 event handling that elements should always
* chain up to to ensure proper operation. Element might however indicate
* event should not be forwarded downstream.
*
* Since: 0.11.x
*/
gboolean
gst_collect_pads2_event_default (GstCollectPads2 * pads, GstCollectData2 * data,
GstEvent * event, gboolean discard)
{
gboolean res = FALSE, need_unlock = FALSE;
GstCollectData2 *data;
GstCollectPads2 *pads;
GstCollectPads2EventFunction event_func;
gboolean res = TRUE;
GstCollectPads2BufferFunction buffer_func;
gpointer event_user_data;
/* some magic to get the managing collect_pads2 */
GST_OBJECT_LOCK (pad);
data = (GstCollectData2 *) gst_pad_get_element_private (pad);
if (G_UNLIKELY (data == NULL))
goto pad_removed;
ref_data (data);
GST_OBJECT_UNLOCK (pad);
res = FALSE;
pads = data->collect;
GST_DEBUG_OBJECT (data->pad, "Got %s event on sink pad",
GST_EVENT_TYPE_NAME (event));
GstObject *parent;
GstPad *pad;
GST_OBJECT_LOCK (pads);
event_func = pads->priv->event_func;
event_user_data = pads->priv->event_user_data;
buffer_func = pads->priv->buffer_func;
GST_OBJECT_UNLOCK (pads);
pad = data->pad;
parent = GST_OBJECT_PARENT (pad);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
{
/* forward event to unblock check_collected */
if (event_func) {
res = event_func (pads, data, event, event_user_data);
} else {
GST_DEBUG_OBJECT (pad, "forwarding flush start");
res = gst_pad_event_default (pad, parent, event);
}
/* now unblock the chain function.
* no cond per pad, so they all unblock,
@ -1703,9 +1703,7 @@ gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
/* event already cleaned up by forwarding */
res = TRUE;
goto done;
goto eat;
}
case GST_EVENT_FLUSH_STOP:
{
@ -1728,8 +1726,7 @@ gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
}
GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
/* forward event */
goto forward_or_default;
goto forward;
}
case GST_EVENT_EOS:
{
@ -1748,7 +1745,7 @@ gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
gst_collect_pads2_check_collected (pads);
GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
goto forward_or_eat;
goto eat;
}
case GST_EVENT_SEGMENT:
{
@ -1796,48 +1793,76 @@ gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
/* we must not forward this event since multiple segments will be
* accumulated and this is certainly not what we want. */
goto forward_or_eat;
goto eat;
}
case GST_EVENT_CAPS:
case GST_EVENT_STREAM_START:
case GST_EVENT_STREAM_CONFIG:
goto forward_or_eat;
goto eat;
default:
/* forward other events */
goto forward_or_default;
goto forward;
}
forward_or_default:
if (GST_EVENT_IS_SERIALIZED (event)) {
GST_COLLECT_PADS2_STREAM_LOCK (pads);
need_unlock = TRUE;
}
if (event_func) {
res = event_func (pads, data, event, event_user_data);
} else {
GST_DEBUG_OBJECT (pad, "forwarding %s", GST_EVENT_TYPE_NAME (event));
res = gst_pad_event_default (pad, parent, event);
}
if (need_unlock)
GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
goto done;
forward_or_eat:
if (GST_EVENT_IS_SERIALIZED (event)) {
GST_COLLECT_PADS2_STREAM_LOCK (pads);
need_unlock = TRUE;
}
if (event_func) {
res = event_func (pads, data, event, event_user_data);
} else {
eat:
gst_event_unref (event);
res = TRUE;
return res;
forward:
if (discard)
goto eat;
else
return gst_pad_event_default (pad, parent, event);
}
static gboolean
gst_collect_pads2_event_default_internal (GstCollectPads2 * pads,
GstCollectData2 * data, GstEvent * event, gpointer user_data)
{
return gst_collect_pads2_event_default (pads, data, event, FALSE);
}
static gboolean
gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
gboolean res = FALSE, need_unlock = FALSE;
GstCollectData2 *data;
GstCollectPads2 *pads;
GstCollectPads2EventFunction event_func;
gpointer event_user_data;
/* some magic to get the managing collect_pads2 */
GST_OBJECT_LOCK (pad);
data = (GstCollectData2 *) gst_pad_get_element_private (pad);
if (G_UNLIKELY (data == NULL))
goto pad_removed;
ref_data (data);
GST_OBJECT_UNLOCK (pad);
res = FALSE;
pads = data->collect;
GST_DEBUG_OBJECT (data->pad, "Got %s event on sink pad",
GST_EVENT_TYPE_NAME (event));
GST_OBJECT_LOCK (pads);
event_func = pads->priv->event_func;
event_user_data = pads->priv->event_user_data;
GST_OBJECT_UNLOCK (pads);
if (GST_EVENT_IS_SERIALIZED (event)) {
GST_COLLECT_PADS2_STREAM_LOCK (pads);
need_unlock = TRUE;
}
if (G_LIKELY (event_func)) {
res = event_func (pads, data, event, event_user_data);
}
if (need_unlock)
GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
goto done;
done:
unref_data (data);
return res;

View file

@ -207,11 +207,9 @@ typedef gint (*GstCollectPads2CompareFunction) (GstCollectPads2 *pads,
* @user_data: user data passed to gst_collect_pads2_set_event_function()
*
* A function that will be called while processing an event. It takes
* ownership of the event and is responsible for forwarding
* events downstream (with gst_pad_event_default()) or dropping events.
*
* The STREAM_START, CAPS, STREAM_CONFIG, SEGMENT and EOS events should
* usually be dropped by this function.
* ownership of the event and is responsible for chaining up (to
* gst_collect_pads2_event_default()) or dropping events (such typical cases
* being handled by the default handler).
*
* Returns: %TRUE if the pad could handle the event
*
@ -365,6 +363,10 @@ GstFlowReturn gst_collect_pads2_clip_running_time (GstCollectPads2 * pads,
GstCollectData2 * cdata, GstBuffer * buf, GstBuffer ** outbuf,
gpointer user_data);
/* default handler */
gboolean gst_collect_pads2_event_default (GstCollectPads2 * pads2, GstCollectData2 * data,
GstEvent * event, gboolean discard);
G_END_DECLS