mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
pad: Fix sticky event ordering for instant-rate-change
The event type for instant-rate-change events was poorly chosen, leading to them being re-sent too late and even after EOS. Add a mechanism in GstPad for the sticky event order to be different to the value of the event type to fix that up. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3387>
This commit is contained in:
parent
132eddd7b9
commit
bdaa8f83aa
4 changed files with 73 additions and 11 deletions
|
@ -213,6 +213,33 @@ gst_event_type_get_flags (GstEventType type)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_event_type_to_sticky_ordering
|
||||||
|
* @type: a #GstEventType
|
||||||
|
*
|
||||||
|
* Converts the #GstEventType to an unsigned integer that
|
||||||
|
* represents the ordering of sticky events when re-sending them.
|
||||||
|
* A lower value represents a higher-priority event.
|
||||||
|
*
|
||||||
|
* Returns: an unsigned integer
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
/* FIXME 2.0: Remove the sticky event order overrides once
|
||||||
|
* the event type numbers are fixed */
|
||||||
|
guint
|
||||||
|
gst_event_type_to_sticky_ordering (GstEventType type)
|
||||||
|
{
|
||||||
|
guint sticky_order = type;
|
||||||
|
|
||||||
|
/* Fix up the sticky event ordering for events where the
|
||||||
|
* type was chosen poorly */
|
||||||
|
if (type == GST_EVENT_INSTANT_RATE_CHANGE) {
|
||||||
|
sticky_order = GST_EVENT_SEGMENT + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sticky_order;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gst_event_free (GstEvent * event)
|
_gst_event_free (GstEvent * event)
|
||||||
{
|
{
|
||||||
|
|
|
@ -169,6 +169,7 @@ typedef enum {
|
||||||
GST_EVENT_GAP = GST_EVENT_MAKE_TYPE (160, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
|
GST_EVENT_GAP = GST_EVENT_MAKE_TYPE (160, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
|
||||||
|
|
||||||
/* sticky downstream non-serialized */
|
/* sticky downstream non-serialized */
|
||||||
|
/* FIXME 2.0: change to value 72 and move after the GST_EVENT_SEGMENT event */
|
||||||
GST_EVENT_INSTANT_RATE_CHANGE = GST_EVENT_MAKE_TYPE (180, _FLAG(DOWNSTREAM) | _FLAG(STICKY)),
|
GST_EVENT_INSTANT_RATE_CHANGE = GST_EVENT_MAKE_TYPE (180, _FLAG(DOWNSTREAM) | _FLAG(STICKY)),
|
||||||
|
|
||||||
/* upstream events */
|
/* upstream events */
|
||||||
|
@ -417,6 +418,10 @@ GST_API
|
||||||
GstEventTypeFlags
|
GstEventTypeFlags
|
||||||
gst_event_type_get_flags (GstEventType type);
|
gst_event_type_get_flags (GstEventType type);
|
||||||
|
|
||||||
|
|
||||||
|
GST_API
|
||||||
|
guint gst_event_type_to_sticky_ordering (GstEventType type) G_GNUC_CONST;
|
||||||
|
|
||||||
#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
|
#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
|
||||||
/* refcounting */
|
/* refcounting */
|
||||||
static inline GstEvent *
|
static inline GstEvent *
|
||||||
|
|
|
@ -128,6 +128,7 @@ enum
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
gboolean received;
|
gboolean received;
|
||||||
|
guint sticky_order;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
} PadEvent;
|
} PadEvent;
|
||||||
|
|
||||||
|
@ -459,6 +460,8 @@ remove_events (GstPad * pad)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define _to_sticky_order(t) gst_event_type_to_sticky_ordering(t)
|
||||||
|
|
||||||
/* should be called with object lock */
|
/* should be called with object lock */
|
||||||
static PadEvent *
|
static PadEvent *
|
||||||
find_event_by_type (GstPad * pad, GstEventType type, guint idx)
|
find_event_by_type (GstPad * pad, GstEventType type, guint idx)
|
||||||
|
@ -466,6 +469,7 @@ find_event_by_type (GstPad * pad, GstEventType type, guint idx)
|
||||||
guint i, len;
|
guint i, len;
|
||||||
GArray *events;
|
GArray *events;
|
||||||
PadEvent *ev;
|
PadEvent *ev;
|
||||||
|
guint last_sticky_order = _to_sticky_order (type);
|
||||||
|
|
||||||
events = pad->priv->events;
|
events = pad->priv->events;
|
||||||
len = events->len;
|
len = events->len;
|
||||||
|
@ -479,7 +483,7 @@ find_event_by_type (GstPad * pad, GstEventType type, guint idx)
|
||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
goto found;
|
goto found;
|
||||||
idx--;
|
idx--;
|
||||||
} else if (GST_EVENT_TYPE (ev->event) > type) {
|
} else if (ev->sticky_order > last_sticky_order) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,11 +503,12 @@ find_event (GstPad * pad, GstEvent * event)
|
||||||
events = pad->priv->events;
|
events = pad->priv->events;
|
||||||
len = events->len;
|
len = events->len;
|
||||||
|
|
||||||
|
guint sticky_order = _to_sticky_order (GST_EVENT_TYPE (event));
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
ev = &g_array_index (events, PadEvent, i);
|
ev = &g_array_index (events, PadEvent, i);
|
||||||
if (event == ev->event)
|
if (event == ev->event)
|
||||||
goto found;
|
goto found;
|
||||||
else if (GST_EVENT_TYPE (ev->event) > GST_EVENT_TYPE (event))
|
else if (ev->sticky_order > sticky_order)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ev = NULL;
|
ev = NULL;
|
||||||
|
@ -522,13 +527,15 @@ remove_event_by_type (GstPad * pad, GstEventType type)
|
||||||
events = pad->priv->events;
|
events = pad->priv->events;
|
||||||
len = events->len;
|
len = events->len;
|
||||||
|
|
||||||
|
guint last_sticky_order = _to_sticky_order (type);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
ev = &g_array_index (events, PadEvent, i);
|
ev = &g_array_index (events, PadEvent, i);
|
||||||
if (ev->event == NULL)
|
if (ev->event == NULL)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
if (GST_EVENT_TYPE (ev->event) > type)
|
if (ev->sticky_order > last_sticky_order)
|
||||||
break;
|
break;
|
||||||
else if (GST_EVENT_TYPE (ev->event) != type)
|
else if (GST_EVENT_TYPE (ev->event) != type)
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -599,6 +606,7 @@ restart:
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
/* take additional ref, func might release the lock */
|
/* take additional ref, func might release the lock */
|
||||||
|
ev_ret.sticky_order = ev->sticky_order;
|
||||||
ev_ret.event = gst_event_ref (ev->event);
|
ev_ret.event = gst_event_ref (ev->event);
|
||||||
ev_ret.received = ev->received;
|
ev_ret.received = ev->received;
|
||||||
|
|
||||||
|
@ -4033,12 +4041,17 @@ push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint data_sticky_order = 0;
|
||||||
|
if (data->event) {
|
||||||
|
data_sticky_order = _to_sticky_order (GST_EVENT_TYPE (data->event));
|
||||||
|
}
|
||||||
|
|
||||||
/* If we're called because of an sticky event, only forward
|
/* If we're called because of an sticky event, only forward
|
||||||
* events that would come before this new event and the
|
* events that would come before this new event and the
|
||||||
* event itself */
|
* event itself */
|
||||||
if (data->event && GST_EVENT_IS_STICKY (data->event) &&
|
if (data->event && GST_EVENT_IS_STICKY (data->event) &&
|
||||||
GST_EVENT_TYPE (data->event) <= GST_EVENT_SEGMENT &&
|
data_sticky_order <= _to_sticky_order (GST_EVENT_SEGMENT) &&
|
||||||
GST_EVENT_TYPE (data->event) < GST_EVENT_TYPE (event)) {
|
data_sticky_order < ev->sticky_order) {
|
||||||
data->ret = GST_FLOW_CUSTOM_SUCCESS_1;
|
data->ret = GST_FLOW_CUSTOM_SUCCESS_1;
|
||||||
} else {
|
} else {
|
||||||
data->ret = gst_pad_push_event_unchecked (pad, gst_event_ref (event),
|
data->ret = gst_pad_push_event_unchecked (pad, gst_event_ref (event),
|
||||||
|
@ -5295,6 +5308,7 @@ store_sticky_event (GstPad * pad, GstEvent * event)
|
||||||
gboolean insert = TRUE;
|
gboolean insert = TRUE;
|
||||||
|
|
||||||
type = GST_EVENT_TYPE (event);
|
type = GST_EVENT_TYPE (event);
|
||||||
|
guint sticky_order = _to_sticky_order (type);
|
||||||
|
|
||||||
/* Store all sticky events except SEGMENT/EOS when we're flushing,
|
/* Store all sticky events except SEGMENT/EOS when we're flushing,
|
||||||
* otherwise they can be dropped and nothing would ever resend them.
|
* otherwise they can be dropped and nothing would ever resend them.
|
||||||
|
@ -5343,11 +5357,11 @@ store_sticky_event (GstPad * pad, GstEvent * event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type < GST_EVENT_TYPE (ev->event) || (type != GST_EVENT_TYPE (ev->event)
|
if (sticky_order < ev->sticky_order || (type != GST_EVENT_TYPE (ev->event)
|
||||||
&& GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS)) {
|
&& GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS)) {
|
||||||
/* STREAM_START, CAPS and SEGMENT must be delivered in this order. By
|
/* STREAM_START, CAPS and SEGMENT must be delivered in this order. By
|
||||||
* storing the sticky ordered we can check that this is respected. */
|
* storing the sticky ordered we can check that this is respected. */
|
||||||
if (G_UNLIKELY (GST_EVENT_TYPE (ev->event) <= GST_EVENT_SEGMENT
|
if (G_UNLIKELY (ev->sticky_order <= _to_sticky_order (GST_EVENT_SEGMENT)
|
||||||
|| GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS))
|
|| GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS))
|
||||||
g_warning (G_STRLOC
|
g_warning (G_STRLOC
|
||||||
":%s:<%s:%s> Sticky event misordering, got '%s' before '%s'",
|
":%s:<%s:%s> Sticky event misordering, got '%s' before '%s'",
|
||||||
|
@ -5359,6 +5373,7 @@ store_sticky_event (GstPad * pad, GstEvent * event)
|
||||||
}
|
}
|
||||||
if (insert) {
|
if (insert) {
|
||||||
PadEvent ev;
|
PadEvent ev;
|
||||||
|
ev.sticky_order = sticky_order;
|
||||||
ev.event = gst_event_ref (event);
|
ev.event = gst_event_ref (event);
|
||||||
ev.received = FALSE;
|
ev.received = FALSE;
|
||||||
g_array_insert_val (events, i, ev);
|
g_array_insert_val (events, i, ev);
|
||||||
|
@ -5438,7 +5453,7 @@ sticky_changed (GstPad * pad, PadEvent * ev, gpointer user_data)
|
||||||
|
|
||||||
/* Forward all sticky events before our current one that are pending */
|
/* Forward all sticky events before our current one that are pending */
|
||||||
if (ev->event != data->event
|
if (ev->event != data->event
|
||||||
&& GST_EVENT_TYPE (ev->event) < GST_EVENT_TYPE (data->event))
|
&& ev->sticky_order < _to_sticky_order (GST_EVENT_TYPE (data->event)))
|
||||||
return push_sticky (pad, ev, data);
|
return push_sticky (pad, ev, data);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -2591,6 +2591,12 @@ test_sticky_events_handler (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
case 2:
|
case 2:
|
||||||
fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
|
fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_CHANGE);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_COLLECTION);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fail_unless (FALSE);
|
fail_unless (FALSE);
|
||||||
break;
|
break;
|
||||||
|
@ -2642,6 +2648,15 @@ GST_START_TEST (test_sticky_events)
|
||||||
gst_segment_init (&seg, GST_FORMAT_TIME);
|
gst_segment_init (&seg, GST_FORMAT_TIME);
|
||||||
gst_pad_push_event (srcpad, gst_event_new_segment (&seg));
|
gst_pad_push_event (srcpad, gst_event_new_segment (&seg));
|
||||||
|
|
||||||
|
/* Push a stream collection */
|
||||||
|
GstStreamCollection *collection = gst_stream_collection_new (0);
|
||||||
|
gst_pad_push_event (srcpad, gst_event_new_stream_collection (collection));
|
||||||
|
gst_object_unref (collection);
|
||||||
|
|
||||||
|
/* Push an instant rate change, which should be sent earlier than the preceding stream collection */
|
||||||
|
gst_pad_push_event (srcpad, gst_event_new_instant_rate_change (1.0,
|
||||||
|
GST_SEGMENT_FLAG_NONE));
|
||||||
|
|
||||||
/* now make a sinkpad */
|
/* now make a sinkpad */
|
||||||
sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
fail_unless (sinkpad != NULL);
|
fail_unless (sinkpad != NULL);
|
||||||
|
@ -2662,13 +2677,13 @@ GST_START_TEST (test_sticky_events)
|
||||||
gst_pad_push_event (srcpad, gst_event_new_caps (caps));
|
gst_pad_push_event (srcpad, gst_event_new_caps (caps));
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
/* should have triggered 2 events, the segment event is still pending */
|
/* should have triggered 2 events, the segment, stream collection and instant-rate events are still pending */
|
||||||
fail_unless_equals_int (sticky_count, 2);
|
fail_unless_equals_int (sticky_count, 2);
|
||||||
|
|
||||||
fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK);
|
fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK);
|
||||||
|
|
||||||
/* should have triggered 3 events */
|
/* should have triggered 5 events */
|
||||||
fail_unless_equals_int (sticky_count, 3);
|
fail_unless_equals_int (sticky_count, 5);
|
||||||
|
|
||||||
gst_object_unref (srcpad);
|
gst_object_unref (srcpad);
|
||||||
gst_object_unref (sinkpad);
|
gst_object_unref (sinkpad);
|
||||||
|
|
Loading…
Reference in a new issue