mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-17 22:06:41 +00:00
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:
parent
4d96e5b834
commit
56d4650789
5 changed files with 119 additions and 16 deletions
54
gst/gstpad.c
54
gst/gstpad.c
|
@ -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 */
|
||||
|
|
37
gst/gstpad.h
37
gst/gstpad.h
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue