pad: Implement GstPadEventFullFunction

API: GstPadEventFullFunction

Returns a GstFlowReturn, allows asynchronous elements to properly
propagate flow returns

https://bugzilla.gnome.org/show_bug.cgi?id=757821
This commit is contained in:
Edward Hervey 2015-11-12 17:15:37 +01:00
parent 4d96e5b834
commit 56d4650789
5 changed files with 119 additions and 16 deletions

View file

@ -1826,6 +1826,51 @@ gst_pad_set_event_function_full (GstPad * pad, GstPadEventFunction event,
GST_DEBUG_FUNCPTR_NAME (event));
}
static gboolean
event_wrap (GstPad * pad, GstObject * object, GstEvent * event)
{
GstFlowReturn ret;
ret = GST_PAD_EVENTFULLFUNC (pad) (pad, object, event);
if (ret == GST_FLOW_OK)
return TRUE;
return FALSE;
}
/**
* gst_pad_set_event_full_function:
* @p: a #GstPad of either direction.
* @f: the #GstPadEventFullFunction to set.
*
* Calls gst_pad_set_event_full_function_full() with %NULL for the user_data and
* notify.
*/
/**
* gst_pad_set_event_full_function_full:
* @pad: a #GstPad of either direction.
* @event: the #GstPadEventFullFunction to set.
* @user_data: user_data passed to @notify
* @notify: notify called when @event will not be used anymore.
*
* Sets the given event handler for the pad.
*/
void
gst_pad_set_event_full_function_full (GstPad * pad,
GstPadEventFullFunction event, gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->eventnotify)
pad->eventnotify (pad->eventdata);
GST_PAD_EVENTFULLFUNC (pad) = event;
GST_PAD_EVENTFUNC (pad) = event_wrap;
pad->eventdata = user_data;
pad->eventnotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfullfunc for set to %s",
GST_DEBUG_FUNCPTR_NAME (event));
}
/**
* gst_pad_set_query_function:
* @p: a #GstPad of either direction.
@ -5389,6 +5434,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
GstEventType event_type;
gboolean serialized, need_unlock = FALSE, sticky;
GstPadEventFunction eventfunc;
GstPadEventFullFunction eventfullfunc = NULL;
GstObject *parent;
GST_OBJECT_LOCK (pad);
@ -5486,7 +5532,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
eventfullfunc = GST_PAD_EVENTFULLFUNC (pad);
eventfunc = GST_PAD_EVENTFUNC (pad);
if (G_UNLIKELY (eventfunc == NULL && eventfullfunc == NULL))
goto no_function;
ACQUIRE_PARENT (pad, parent, no_parent);
@ -5499,7 +5547,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
if (sticky)
gst_event_ref (event);
if (eventfunc (pad, parent, event)) {
if (eventfullfunc) {
ret = eventfullfunc (pad, parent, event);
} else if (eventfunc (pad, parent, event)) {
ret = GST_FLOW_OK;
} else {
/* something went wrong */

View file

@ -362,6 +362,26 @@ typedef GstFlowReturn (*GstPadGetRangeFunction) (GstPad *pad, GstObject *parent
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstObject *parent,
GstEvent *event);
/**
* GstPadEventFullFunction:
* @pad: the #GstPad to handle the event.
* @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT
* flag is set, @parent is guaranteed to be not-%NULL and remain valid
* during the execution of this function.
* @event: (transfer full): the #GstEvent to handle.
*
* Function signature to handle an event for the pad.
*
* This variant is for specific elements that will take into account the
* last downstream flow return (from a pad push), in which case they can
* return it.
*
* Returns: %GST_FLOW_OK if the event was handled properly, or any other
* #GstFlowReturn dependent on downstream state.
*/
typedef GstFlowReturn (*GstPadEventFullFunction) (GstPad *pad, GstObject *parent,
GstEvent *event);
/* internal links */
/**
@ -756,6 +776,7 @@ struct _GstPad {
gpointer _gst_reserved[GST_PADDING];
struct {
GstFlowReturn last_flowret;
GstPadEventFullFunction eventfullfunc;
} abi;
} ABI;
};
@ -880,6 +901,17 @@ struct _GstPadClass {
* class, use the base class's virtual functions instead.
*/
#define GST_PAD_EVENTFUNC(pad) (GST_PAD_CAST(pad)->eventfunc)
/**
* GST_PAD_EVENTFULLFUNC:
* @pad: a #GstPad
*
* Get the #GstPadEventFullFunction from the given @pad, which
* is the function that handles events on the pad. You can
* use this to set your own event handling function on a pad
* after you create it. If your element derives from a base
* class, use the base class's virtual functions instead.
*/
#define GST_PAD_EVENTFULLFUNC(pad) (GST_PAD_CAST(pad)->ABI.abi.eventfullfunc)
/**
* GST_PAD_QUERYFUNC:
* @pad: a #GstPad
@ -1306,6 +1338,10 @@ void gst_pad_set_event_function_full (GstPad *pad,
GstPadEventFunction event,
gpointer user_data,
GDestroyNotify notify);
void gst_pad_set_event_full_function_full (GstPad *pad,
GstPadEventFullFunction event,
gpointer user_data,
GDestroyNotify notify);
#define gst_pad_set_activate_function(p,f) gst_pad_set_activate_function_full((p),(f),NULL,NULL)
#define gst_pad_set_activatemode_function(p,f) gst_pad_set_activatemode_function_full((p),(f),NULL,NULL)
@ -1313,6 +1349,7 @@ void gst_pad_set_event_function_full (GstPad *pad,
#define gst_pad_set_chain_list_function(p,f) gst_pad_set_chain_list_function_full((p),(f),NULL,NULL)
#define gst_pad_set_getrange_function(p,f) gst_pad_set_getrange_function_full((p),(f),NULL,NULL)
#define gst_pad_set_event_function(p,f) gst_pad_set_event_function_full((p),(f),NULL,NULL)
#define gst_pad_set_event_full_function(p,f) gst_pad_set_event_full_function_full((p),(f),NULL,NULL)
/* pad links */
void gst_pad_set_link_function_full (GstPad *pad,

View file

@ -1941,14 +1941,15 @@ gst_multi_queue_sink_activate_mode (GstPad * pad, GstObject * parent,
return res;
}
static gboolean
static GstFlowReturn
gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstSingleQueue *sq;
GstMultiQueue *mq;
guint32 curid;
GstMultiQueueItem *item;
gboolean res;
gboolean res = TRUE;
GstFlowReturn flowret = GST_FLOW_OK;
GstEventType type;
GstEvent *sref = NULL;
@ -2088,8 +2089,17 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
default:
break;
}
done:
return res;
if (res == FALSE) {
if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
flowret = GST_FLOW_NOT_NEGOTIATED;
else
flowret = GST_FLOW_ERROR;
}
GST_DEBUG_OBJECT (mq, "SingleQueue %d : returning %s", sq->id,
gst_flow_get_name (flowret));
return flowret;
flushing:
{
@ -2098,14 +2108,14 @@ flushing:
if (sref)
gst_event_unref (sref);
gst_multi_queue_item_destroy (item);
goto done;
return sq->srcresult;
}
was_eos:
{
GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return FALSE");
GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return GST_FLOW_EOS");
gst_event_unref (event);
res = FALSE;
goto done;
return GST_FLOW_EOS;
}
}
@ -2676,7 +2686,7 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
GST_DEBUG_FUNCPTR (gst_multi_queue_chain));
gst_pad_set_activatemode_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode));
gst_pad_set_event_function (sq->sinkpad,
gst_pad_set_event_full_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
gst_pad_set_query_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));

View file

@ -200,8 +200,8 @@ static GstFlowReturn gst_queue_chain_list (GstPad * pad, GstObject * parent,
static GstFlowReturn gst_queue_push_one (GstQueue * queue);
static void gst_queue_loop (GstPad * pad);
static gboolean gst_queue_handle_sink_event (GstPad * pad, GstObject * parent,
GstEvent * event);
static GstFlowReturn gst_queue_handle_sink_event (GstPad * pad,
GstObject * parent, GstEvent * event);
static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent,
GstQuery * query);
@ -431,7 +431,7 @@ gst_queue_init (GstQueue * queue)
gst_pad_set_chain_list_function (queue->sinkpad, gst_queue_chain_list);
gst_pad_set_activatemode_function (queue->sinkpad,
gst_queue_sink_activate_mode);
gst_pad_set_event_function (queue->sinkpad, gst_queue_handle_sink_event);
gst_pad_set_event_full_function (queue->sinkpad, gst_queue_handle_sink_event);
gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query);
GST_PAD_SET_PROXY_CAPS (queue->sinkpad);
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
@ -897,7 +897,7 @@ no_item:
}
}
static gboolean
static GstFlowReturn
gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
gboolean ret = TRUE;
@ -985,7 +985,12 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
}
break;
}
return ret;
if (ret == FALSE) {
if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
return GST_FLOW_NOT_NEGOTIATED;
return GST_FLOW_ERROR;
}
return GST_FLOW_OK;
/* ERRORS */
out_eos:
@ -993,7 +998,7 @@ out_eos:
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS");
GST_QUEUE_MUTEX_UNLOCK (queue);
gst_event_unref (event);
return FALSE;
return GST_FLOW_EOS;
}
out_flow_error:
{
@ -1001,7 +1006,7 @@ out_flow_error:
"refusing event, we have a downstream flow error: %s",
gst_flow_get_name (queue->srcresult));
gst_event_unref (event);
return FALSE;
return queue->srcresult;
}
}

View file

@ -895,6 +895,7 @@ EXPORTS
gst_pad_set_chain_function_full
gst_pad_set_chain_list_function_full
gst_pad_set_element_private
gst_pad_set_event_full_function_full
gst_pad_set_event_function_full
gst_pad_set_getrange_function_full
gst_pad_set_iterate_internal_links_function_full