mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-17 05:46:36 +00:00
pad: also push sticky events on new event
Make a helper function check_sticky to check and push pending sticky events. Move the handling of the result of pushing the sticky event inside the push_event function, we need to mark the event as received when it was pushed correctly. Move the sticky events code outside of gst_pad_push_event_unchecked and make it purely handle sending the event to the peer. when pushing a sticky event, first store it on the pad. Then check and push any pending sticky events when we get a serialized or sticky event on a srcpad. This fixes the issue where sticky events are not pushed when an event is pushed.
This commit is contained in:
parent
0054e6da9e
commit
35241f35c0
1 changed files with 82 additions and 71 deletions
153
gst/gstpad.c
153
gst/gstpad.c
|
@ -147,7 +147,7 @@ static GstFlowReturn gst_pad_chain_list_default (GstPad * pad,
|
|||
static GstFlowReturn gst_pad_send_event_unchecked (GstPad * pad,
|
||||
GstEvent * event, GstPadProbeType type);
|
||||
static GstFlowReturn gst_pad_push_event_unchecked (GstPad * pad,
|
||||
GstEvent * event, GstPadProbeType type, gboolean * stored);
|
||||
GstEvent * event, GstPadProbeType type);
|
||||
|
||||
static guint gst_pad_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
@ -3274,26 +3274,58 @@ probe_stopped:
|
|||
* Data passing functions
|
||||
*/
|
||||
|
||||
/* should be called with pad LOCK */
|
||||
static gboolean
|
||||
push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
|
||||
{
|
||||
GstFlowReturn *data = user_data;
|
||||
gboolean stored;
|
||||
GstEvent *event = ev->event;
|
||||
|
||||
if (ev->received) {
|
||||
GST_DEBUG_OBJECT (pad, "event %s was already received",
|
||||
GST_EVENT_TYPE_NAME (ev->event));
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
return TRUE;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
*data = gst_pad_push_event_unchecked (pad, gst_event_ref (ev->event),
|
||||
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, &stored);
|
||||
*data = gst_pad_push_event_unchecked (pad, gst_event_ref (event),
|
||||
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM);
|
||||
|
||||
GST_OBJECT_LOCK (pad);
|
||||
switch (*data) {
|
||||
case GST_FLOW_OK:
|
||||
ev->received = TRUE;
|
||||
GST_DEBUG_OBJECT (pad, "event %s marked received",
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
break;
|
||||
case GST_FLOW_NOT_LINKED:
|
||||
/* not linked is not a problem, we are sticky so the event will be
|
||||
* sent later */
|
||||
GST_DEBUG_OBJECT (pad, "pad was not linked");
|
||||
*data = GST_FLOW_OK;
|
||||
/* fallthrough */
|
||||
default:
|
||||
GST_DEBUG_OBJECT (pad, "mark pending events");
|
||||
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
|
||||
break;
|
||||
}
|
||||
return *data == GST_FLOW_OK;
|
||||
}
|
||||
|
||||
/* check sticky events and push them when needed. should be called
|
||||
* with pad LOCK */
|
||||
static inline GstFlowReturn
|
||||
check_sticky (GstPad * pad)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
|
||||
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "pushing all sticky events");
|
||||
events_foreach (pad, push_sticky, &ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* this is the chain function that does not perform the additional argument
|
||||
* checking for that little extra speed.
|
||||
*/
|
||||
|
@ -3521,16 +3553,8 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data)
|
|||
if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH))
|
||||
goto wrong_mode;
|
||||
|
||||
if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
|
||||
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "pushing all sticky events");
|
||||
|
||||
ret = GST_FLOW_OK;
|
||||
events_foreach (pad, push_sticky, &ret);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto events_error;
|
||||
}
|
||||
if (G_UNLIKELY ((ret = check_sticky (pad))) != GST_FLOW_OK)
|
||||
goto events_error;
|
||||
|
||||
/* do block probes */
|
||||
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
|
||||
|
@ -3700,16 +3724,8 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size,
|
|||
if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL))
|
||||
goto wrong_mode;
|
||||
|
||||
if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
|
||||
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "pushing all sticky events");
|
||||
|
||||
ret = GST_FLOW_OK;
|
||||
events_foreach (pad, push_sticky, &ret);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto events_error;
|
||||
}
|
||||
if (G_UNLIKELY ((ret = check_sticky (pad))) != GST_FLOW_OK)
|
||||
goto events_error;
|
||||
|
||||
/* when one of the probes returns a buffer, probed_data will be called and we
|
||||
* skip calling the getrange function */
|
||||
|
@ -4040,24 +4056,19 @@ gst_pad_store_sticky_event (GstPad * pad, GstEvent * event, gboolean locked)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* should be called with pad LOCK */
|
||||
static GstFlowReturn
|
||||
gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
|
||||
GstPadProbeType type, gboolean * stored)
|
||||
GstPadProbeType type)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
GstPad *peerpad;
|
||||
GstEventType event_type;
|
||||
gboolean sticky;
|
||||
|
||||
sticky = GST_EVENT_IS_STICKY (event);
|
||||
|
||||
GST_OBJECT_LOCK (pad);
|
||||
|
||||
/* Two checks to be made:
|
||||
* . (un)set the FLUSHING flag for flushing events,
|
||||
* . handle pad blocking */
|
||||
event_type = GST_EVENT_TYPE (event);
|
||||
*stored = FALSE;
|
||||
switch (event_type) {
|
||||
case GST_EVENT_FLUSH_START:
|
||||
GST_PAD_SET_FLUSHING (pad);
|
||||
|
@ -4079,19 +4090,6 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
|
|||
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
|
||||
goto flushed;
|
||||
|
||||
/* store the event on the pad, but only on srcpads. We always store the
|
||||
* event exactly how it was sent */
|
||||
if (sticky) {
|
||||
/* srcpad sticky events are store immediately, the received flag is set
|
||||
* to FALSE and will be set to TRUE when we can successfully push the
|
||||
* event to the peer pad */
|
||||
if (gst_pad_store_sticky_event (pad, event, TRUE)) {
|
||||
GST_DEBUG_OBJECT (pad, "event %s updated",
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
}
|
||||
*stored = TRUE;
|
||||
}
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEGMENT:
|
||||
/* pass the adjusted segment event on. We need to do this even if
|
||||
|
@ -4137,41 +4135,24 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
|
|||
gst_object_unref (peerpad);
|
||||
|
||||
GST_OBJECT_LOCK (pad);
|
||||
if (sticky) {
|
||||
if (ret == GST_FLOW_OK) {
|
||||
PadEvent *ev;
|
||||
|
||||
if ((ev = find_event (pad, event)))
|
||||
ev->received = TRUE;
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "event marked received");
|
||||
} else {
|
||||
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
|
||||
GST_DEBUG_OBJECT (pad, "mark pending events");
|
||||
}
|
||||
}
|
||||
pad->priv->using--;
|
||||
if (pad->priv->using == 0) {
|
||||
/* pad is not active anymore, trigger idle callbacks */
|
||||
PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
|
||||
idle_probe_stopped, ret);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
return ret;
|
||||
|
||||
/* ERROR handling */
|
||||
flushed:
|
||||
{
|
||||
GST_DEBUG_OBJECT (pad, "We're flushing");
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
gst_event_unref (event);
|
||||
return GST_FLOW_FLUSHING;
|
||||
}
|
||||
probe_stopped:
|
||||
{
|
||||
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
gst_event_unref (event);
|
||||
|
||||
switch (ret) {
|
||||
|
@ -4189,14 +4170,12 @@ not_linked:
|
|||
{
|
||||
GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked");
|
||||
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
gst_event_unref (event);
|
||||
return sticky ? GST_FLOW_OK : GST_FLOW_NOT_LINKED;
|
||||
return GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
idle_probe_stopped:
|
||||
{
|
||||
GST_DEBUG_OBJECT (pad, "Idle probe returned %s", gst_flow_get_name (ret));
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -4222,7 +4201,7 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
|||
{
|
||||
gboolean res;
|
||||
GstPadProbeType type;
|
||||
gboolean stored;
|
||||
gboolean sticky, serialized;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
@ -4240,10 +4219,35 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
|||
} else
|
||||
goto unknown_direction;
|
||||
|
||||
if (gst_pad_push_event_unchecked (pad, event, type, &stored) != GST_FLOW_OK)
|
||||
res = stored ? TRUE : FALSE;
|
||||
else
|
||||
GST_OBJECT_LOCK (pad);
|
||||
sticky = GST_EVENT_IS_STICKY (event);
|
||||
serialized = GST_EVENT_IS_SERIALIZED (event);
|
||||
|
||||
if (sticky) {
|
||||
/* can't store on flushing pads */
|
||||
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
|
||||
goto flushed;
|
||||
|
||||
/* srcpad sticky events are store immediately, the received flag is set
|
||||
* to FALSE and will be set to TRUE when we can successfully push the
|
||||
* event to the peer pad */
|
||||
if (gst_pad_store_sticky_event (pad, event, TRUE)) {
|
||||
GST_DEBUG_OBJECT (pad, "event %s updated", GST_EVENT_TYPE_NAME (event));
|
||||
}
|
||||
}
|
||||
if (GST_PAD_IS_SRC (pad) && (serialized || sticky)) {
|
||||
/* all serialized or sticky events on the srcpad trigger push of
|
||||
* sticky events */
|
||||
res = (check_sticky (pad) == GST_FLOW_OK);
|
||||
}
|
||||
if (!sticky) {
|
||||
/* other events are pushed right away */
|
||||
res = (gst_pad_push_event_unchecked (pad, event, type) == GST_FLOW_OK);
|
||||
} else {
|
||||
gst_event_unref (event);
|
||||
res = TRUE;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
return res;
|
||||
|
||||
|
@ -4261,6 +4265,13 @@ unknown_direction:
|
|||
gst_event_unref (event);
|
||||
return FALSE;
|
||||
}
|
||||
flushed:
|
||||
{
|
||||
GST_DEBUG_OBJECT (pad, "We're flushing");
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
gst_event_unref (event);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we can call the event function with the given event */
|
||||
|
|
Loading…
Reference in a new issue