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));
|
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:
|
* gst_pad_set_query_function:
|
||||||
* @p: a #GstPad of either direction.
|
* @p: a #GstPad of either direction.
|
||||||
|
@ -5389,6 +5434,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
|
||||||
GstEventType event_type;
|
GstEventType event_type;
|
||||||
gboolean serialized, need_unlock = FALSE, sticky;
|
gboolean serialized, need_unlock = FALSE, sticky;
|
||||||
GstPadEventFunction eventfunc;
|
GstPadEventFunction eventfunc;
|
||||||
|
GstPadEventFullFunction eventfullfunc = NULL;
|
||||||
GstObject *parent;
|
GstObject *parent;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (pad);
|
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);
|
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;
|
goto no_function;
|
||||||
|
|
||||||
ACQUIRE_PARENT (pad, parent, no_parent);
|
ACQUIRE_PARENT (pad, parent, no_parent);
|
||||||
|
@ -5499,7 +5547,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
|
||||||
if (sticky)
|
if (sticky)
|
||||||
gst_event_ref (event);
|
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;
|
ret = GST_FLOW_OK;
|
||||||
} else {
|
} else {
|
||||||
/* something went wrong */
|
/* 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,
|
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstObject *parent,
|
||||||
GstEvent *event);
|
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 */
|
/* internal links */
|
||||||
/**
|
/**
|
||||||
|
@ -756,6 +776,7 @@ struct _GstPad {
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
struct {
|
struct {
|
||||||
GstFlowReturn last_flowret;
|
GstFlowReturn last_flowret;
|
||||||
|
GstPadEventFullFunction eventfullfunc;
|
||||||
} abi;
|
} abi;
|
||||||
} ABI;
|
} ABI;
|
||||||
};
|
};
|
||||||
|
@ -880,6 +901,17 @@ struct _GstPadClass {
|
||||||
* class, use the base class's virtual functions instead.
|
* class, use the base class's virtual functions instead.
|
||||||
*/
|
*/
|
||||||
#define GST_PAD_EVENTFUNC(pad) (GST_PAD_CAST(pad)->eventfunc)
|
#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:
|
* GST_PAD_QUERYFUNC:
|
||||||
* @pad: a #GstPad
|
* @pad: a #GstPad
|
||||||
|
@ -1306,6 +1338,10 @@ void gst_pad_set_event_function_full (GstPad *pad,
|
||||||
GstPadEventFunction event,
|
GstPadEventFunction event,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GDestroyNotify notify);
|
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_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)
|
#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_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_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_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 */
|
/* pad links */
|
||||||
void gst_pad_set_link_function_full (GstPad *pad,
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static GstFlowReturn
|
||||||
gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
{
|
{
|
||||||
GstSingleQueue *sq;
|
GstSingleQueue *sq;
|
||||||
GstMultiQueue *mq;
|
GstMultiQueue *mq;
|
||||||
guint32 curid;
|
guint32 curid;
|
||||||
GstMultiQueueItem *item;
|
GstMultiQueueItem *item;
|
||||||
gboolean res;
|
gboolean res = TRUE;
|
||||||
|
GstFlowReturn flowret = GST_FLOW_OK;
|
||||||
GstEventType type;
|
GstEventType type;
|
||||||
GstEvent *sref = NULL;
|
GstEvent *sref = NULL;
|
||||||
|
|
||||||
|
@ -2088,8 +2089,17 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
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:
|
flushing:
|
||||||
{
|
{
|
||||||
|
@ -2098,14 +2108,14 @@ flushing:
|
||||||
if (sref)
|
if (sref)
|
||||||
gst_event_unref (sref);
|
gst_event_unref (sref);
|
||||||
gst_multi_queue_item_destroy (item);
|
gst_multi_queue_item_destroy (item);
|
||||||
goto done;
|
return sq->srcresult;
|
||||||
}
|
}
|
||||||
was_eos:
|
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);
|
gst_event_unref (event);
|
||||||
res = FALSE;
|
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_DEBUG_FUNCPTR (gst_multi_queue_chain));
|
||||||
gst_pad_set_activatemode_function (sq->sinkpad,
|
gst_pad_set_activatemode_function (sq->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode));
|
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_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
|
||||||
gst_pad_set_query_function (sq->sinkpad,
|
gst_pad_set_query_function (sq->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));
|
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 GstFlowReturn gst_queue_push_one (GstQueue * queue);
|
||||||
static void gst_queue_loop (GstPad * pad);
|
static void gst_queue_loop (GstPad * pad);
|
||||||
|
|
||||||
static gboolean gst_queue_handle_sink_event (GstPad * pad, GstObject * parent,
|
static GstFlowReturn gst_queue_handle_sink_event (GstPad * pad,
|
||||||
GstEvent * event);
|
GstObject * parent, GstEvent * event);
|
||||||
static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent,
|
static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent,
|
||||||
GstQuery * query);
|
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_chain_list_function (queue->sinkpad, gst_queue_chain_list);
|
||||||
gst_pad_set_activatemode_function (queue->sinkpad,
|
gst_pad_set_activatemode_function (queue->sinkpad,
|
||||||
gst_queue_sink_activate_mode);
|
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_query_function (queue->sinkpad, gst_queue_handle_sink_query);
|
||||||
GST_PAD_SET_PROXY_CAPS (queue->sinkpad);
|
GST_PAD_SET_PROXY_CAPS (queue->sinkpad);
|
||||||
gst_element_add_pad (GST_ELEMENT (queue), 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)
|
gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
{
|
{
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
|
@ -985,7 +985,12 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
}
|
}
|
||||||
break;
|
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 */
|
/* ERRORS */
|
||||||
out_eos:
|
out_eos:
|
||||||
|
@ -993,7 +998,7 @@ out_eos:
|
||||||
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS");
|
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS");
|
||||||
GST_QUEUE_MUTEX_UNLOCK (queue);
|
GST_QUEUE_MUTEX_UNLOCK (queue);
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
return FALSE;
|
return GST_FLOW_EOS;
|
||||||
}
|
}
|
||||||
out_flow_error:
|
out_flow_error:
|
||||||
{
|
{
|
||||||
|
@ -1001,7 +1006,7 @@ out_flow_error:
|
||||||
"refusing event, we have a downstream flow error: %s",
|
"refusing event, we have a downstream flow error: %s",
|
||||||
gst_flow_get_name (queue->srcresult));
|
gst_flow_get_name (queue->srcresult));
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
return FALSE;
|
return queue->srcresult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -895,6 +895,7 @@ EXPORTS
|
||||||
gst_pad_set_chain_function_full
|
gst_pad_set_chain_function_full
|
||||||
gst_pad_set_chain_list_function_full
|
gst_pad_set_chain_list_function_full
|
||||||
gst_pad_set_element_private
|
gst_pad_set_element_private
|
||||||
|
gst_pad_set_event_full_function_full
|
||||||
gst_pad_set_event_function_full
|
gst_pad_set_event_function_full
|
||||||
gst_pad_set_getrange_function_full
|
gst_pad_set_getrange_function_full
|
||||||
gst_pad_set_iterate_internal_links_function_full
|
gst_pad_set_iterate_internal_links_function_full
|
||||||
|
|
Loading…
Reference in a new issue