From cc216208233f44b2df689665c58a2365ccc3e286 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 16 Apr 2012 16:24:18 +0200 Subject: [PATCH] collectpads2: provide query default and callback handling ... which presently mainly serves to answer SEEKING query negatively to dissuade upstream encoders from doing any seeking and "header finalization" (since the returned result of pushing a sticky event is fairly useless nowadays). --- libs/gst/base/gstcollectpads2.c | 144 ++++++++++++++++++++++++++++++++++++++++ libs/gst/base/gstcollectpads2.h | 25 ++++++- 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/libs/gst/base/gstcollectpads2.c b/libs/gst/base/gstcollectpads2.c index 6f009c8..9853332 100644 --- a/libs/gst/base/gstcollectpads2.c +++ b/libs/gst/base/gstcollectpads2.c @@ -130,6 +130,8 @@ struct _GstCollectPads2Private gpointer compare_user_data; GstCollectPads2EventFunction event_func; /* function and data for event callback */ gpointer event_user_data; + GstCollectPads2QueryFunction query_func; + gpointer query_user_data; GstCollectPads2ClipFunction clip_func; gpointer clip_user_data; @@ -145,6 +147,8 @@ static GstFlowReturn gst_collect_pads2_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer); static gboolean gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event); +static gboolean gst_collect_pads2_query (GstPad * pad, GstObject * parent, + GstQuery * query); static void gst_collect_pads2_finalize (GObject * object); static GstFlowReturn gst_collect_pads2_default_collected (GstCollectPads2 * pads, gpointer user_data); @@ -157,6 +161,8 @@ static void unref_data (GstCollectData2 * data); static gboolean gst_collect_pads2_event_default_internal (GstCollectPads2 * pads, GstCollectData2 * data, GstEvent * event, gpointer user_data); +static gboolean gst_collect_pads2_query_default_internal (GstCollectPads2 * + pads, GstCollectData2 * data, GstQuery * query, gpointer user_data); /* Some properties are protected by LOCK, others by STREAM_LOCK @@ -246,6 +252,7 @@ gst_collect_pads2_init (GstCollectPads2 * pads) pads->priv->earliest_time = GST_CLOCK_TIME_NONE; pads->priv->event_func = gst_collect_pads2_event_default_internal; + pads->priv->query_func = gst_collect_pads2_query_default_internal; /* members to manage the pad list */ pads->priv->pad_cookie = 0; @@ -455,6 +462,36 @@ gst_collect_pads2_set_event_function (GstCollectPads2 * pads, } /** + * gst_collect_pads2_set_query_function: + * @pads: the collectspads to use + * @func: the function to set + * @user_data: user data passed to the function + * + * Set the query callback function and user data that will be called after + * collectpads has received a query originating from one of the collected + * pads. If the query 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 + * if so (unusually) needed. + * + * MT safe. + * + * Since: 0.10.36 + */ +void +gst_collect_pads2_set_query_function (GstCollectPads2 * pads, + GstCollectPads2QueryFunction func, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS2 (pads)); + + GST_OBJECT_LOCK (pads); + pads->priv->query_func = func; + pads->priv->query_user_data = user_data; + GST_OBJECT_UNLOCK (pads); +} + +/** * gst_collect_pads2_clip_running_time: * @pads: the collectspads to use * @cdata: collect data of corresponding pad @@ -624,6 +661,7 @@ gst_collect_pads2_add_pad_full (GstCollectPads2 * pads, GstPad * pad, pads->priv->pad_list = g_slist_append (pads->priv->pad_list, data); gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads2_chain)); gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads2_event)); + gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads2_query)); /* backward compat, also add to data if stopped, so that the element already * has this in the public data list before going PAUSED (typically) * this can only be done when we are stopped because we don't take the @@ -1875,6 +1913,112 @@ pad_removed: } } +/** + * gst_collect_pads2_query_default: + * @pads: the collectspads to use + * @data: collect data of corresponding pad + * @query: query being processed + * @discard: process but do not send event downstream + * + * Default GstCollectPads2 query handling that elements should always + * chain up to to ensure proper operation. Element might however indicate + * query should not be forwarded downstream. + * + * Since: 0.11.x + */ +gboolean +gst_collect_pads2_query_default (GstCollectPads2 * pads, GstCollectData2 * data, + GstQuery * query, gboolean discard) +{ + gboolean res = TRUE; + GstObject *parent; + GstPad *pad; + + pad = data->pad; + parent = GST_OBJECT_PARENT (pad); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SEEKING: + { + GstFormat format; + + /* don't pass it along as some (file)sink might claim it does + * whereas with a collectpads in between that will not likely work */ + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + gst_query_set_seeking (query, format, FALSE, 0, -1); + res = TRUE; + discard = TRUE; + break; + } + default: + break; + } + + if (!discard) + return gst_pad_query_default (pad, parent, query); + else + return res; +} + +static gboolean +gst_collect_pads2_query_default_internal (GstCollectPads2 * pads, + GstCollectData2 * data, GstQuery * query, gpointer user_data) +{ + return gst_collect_pads2_query_default (pads, data, query, FALSE); +} + +static gboolean +gst_collect_pads2_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res = FALSE, need_unlock = FALSE; + GstCollectData2 *data; + GstCollectPads2 *pads; + GstCollectPads2QueryFunction query_func; + gpointer query_user_data; + + GST_DEBUG_OBJECT (pad, "Got %s query on sink pad", + GST_QUERY_TYPE_NAME (query)); + + /* 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); + + pads = data->collect; + + GST_OBJECT_LOCK (pads); + query_func = pads->priv->query_func; + query_user_data = pads->priv->query_user_data; + GST_OBJECT_UNLOCK (pads); + + if (GST_QUERY_IS_SERIALIZED (query)) { + GST_COLLECT_PADS2_STREAM_LOCK (pads); + need_unlock = TRUE; + } + + if (G_LIKELY (query_func)) { + res = query_func (pads, data, query, query_user_data); + } + + if (need_unlock) + GST_COLLECT_PADS2_STREAM_UNLOCK (pads); + + unref_data (data); + return res; + + /* ERRORS */ +pad_removed: + { + GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + + /* For each buffer we receive we check if our collected condition is reached * and if so we call the collected function. When this is done we check if * data has been unqueued. If data is still queued we wait holding the stream diff --git a/libs/gst/base/gstcollectpads2.h b/libs/gst/base/gstcollectpads2.h index 1b31266..f7f4105 100644 --- a/libs/gst/base/gstcollectpads2.h +++ b/libs/gst/base/gstcollectpads2.h @@ -220,6 +220,24 @@ typedef gboolean (*GstCollectPads2EventFunction) (GstCollectPads2 *pads, /** + * GstCollectPads2QueryFunction: + * @pads: the #GstCollectPads2 that trigered the callback + * @pad: the #GstPad that received an event + * @query: the #GstEvent received + * @user_data: user data passed to gst_collect_pads2_set_query_function() + * + * A function that will be called while processing a query. It takes + * ownership of the query and is responsible for chaining up (to + * events downstream (with gst_pad_event_default()). + * + * Returns: %TRUE if the pad could handle the event + * + * Since: 0.11.x + */ +typedef gboolean (*GstCollectPads2QueryFunction) (GstCollectPads2 *pads, GstCollectData2 * pad, + GstQuery * query, gpointer user_data); + +/** * GstCollectPads2ClipFunction: * @pads: a #GstCollectPads2 * @data: a #GstCollectData2 @@ -318,6 +336,9 @@ void gst_collect_pads2_set_buffer_function (GstCollectPads2 *pads, void gst_collect_pads2_set_event_function (GstCollectPads2 *pads, GstCollectPads2EventFunction func, gpointer user_data); +void gst_collect_pads2_set_query_function (GstCollectPads2 *pads, + GstCollectPads2QueryFunction func, + gpointer user_data); void gst_collect_pads2_set_compare_function (GstCollectPads2 *pads, GstCollectPads2CompareFunction func, gpointer user_data); @@ -363,9 +384,11 @@ GstFlowReturn gst_collect_pads2_clip_running_time (GstCollectPads2 * pads, GstCollectData2 * cdata, GstBuffer * buf, GstBuffer ** outbuf, gpointer user_data); -/* default handler */ +/* default handlers */ gboolean gst_collect_pads2_event_default (GstCollectPads2 * pads2, GstCollectData2 * data, GstEvent * event, gboolean discard); +gboolean gst_collect_pads2_query_default (GstCollectPads2 * pads, GstCollectData2 * data, + GstQuery * query, gboolean discard); G_END_DECLS -- 2.7.4