mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-01 03:52:25 +00:00
WIP: pad-monitor: Fix serialized event order check
This commit is contained in:
parent
fef4eba9a2
commit
d2edb59a24
2 changed files with 90 additions and 17 deletions
|
@ -100,6 +100,20 @@ typedef struct
|
|||
GstEvent *event;
|
||||
} SerializedEventData;
|
||||
|
||||
static void
|
||||
debug_pending_event (GstPad * pad, GPtrArray * array)
|
||||
{
|
||||
guint i, len;
|
||||
|
||||
len = array->len;
|
||||
for (i = 0; i < len; i++) {
|
||||
SerializedEventData *data = g_ptr_array_index (array, i);
|
||||
GST_DEBUG_OBJECT (pad, "event #%d %" GST_TIME_FORMAT " %s %p",
|
||||
i, GST_TIME_ARGS (data->timestamp),
|
||||
GST_EVENT_TYPE_NAME (data->event), data->event);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_serialized_event_data_free (SerializedEventData * serialized_event)
|
||||
{
|
||||
|
@ -464,8 +478,10 @@ gst_validate_pad_monitor_check_late_serialized_events (GstValidatePadMonitor *
|
|||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
if (i) {
|
||||
debug_pending_event (monitor->pad, monitor->serialized_events);
|
||||
g_ptr_array_remove_range (monitor->serialized_events, 0, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -484,6 +500,7 @@ gst_validate_pad_monitor_dispose (GObject * object)
|
|||
|
||||
gst_structure_free (monitor->pending_setcaps_fields);
|
||||
g_ptr_array_unref (monitor->serialized_events);
|
||||
g_list_free (monitor->expired_events);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
@ -511,6 +528,7 @@ gst_validate_pad_monitor_init (GstValidatePadMonitor * pad_monitor)
|
|||
pad_monitor->serialized_events =
|
||||
g_ptr_array_new_with_free_func ((GDestroyNotify)
|
||||
_serialized_event_data_free);
|
||||
pad_monitor->expired_events = NULL;
|
||||
gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES);
|
||||
pad_monitor->first_buffer = TRUE;
|
||||
|
||||
|
@ -906,7 +924,11 @@ static void
|
|||
data->timestamp = last_ts;
|
||||
data->event = gst_event_ref (event);
|
||||
GST_VALIDATE_MONITOR_LOCK (othermonitor);
|
||||
GST_DEBUG_OBJECT (monitor->pad, "Storing for pad %s:%s event %p %s",
|
||||
GST_DEBUG_PAD_NAME (otherpad), event,
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
g_ptr_array_add (othermonitor->serialized_events, data);
|
||||
debug_pending_event (otherpad, othermonitor->serialized_events);
|
||||
GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
|
||||
}
|
||||
g_value_reset (&value);
|
||||
|
@ -1548,29 +1570,79 @@ gst_validate_pad_monitor_event_probe (GstPad * pad, GstEvent * event,
|
|||
GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
|
||||
GST_VALIDATE_MONITOR_LOCK (monitor);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "event %p %s", event, GST_EVENT_TYPE_NAME (event));
|
||||
|
||||
if (GST_EVENT_IS_SERIALIZED (event)) {
|
||||
gint i;
|
||||
|
||||
if (monitor->serialized_events->len > 0) {
|
||||
SerializedEventData *next_event =
|
||||
g_ptr_array_index (monitor->serialized_events, 0);
|
||||
/* Detect if events the element received are being forwarded in the same order
|
||||
*
|
||||
* Several scenarios:
|
||||
* 1) The element pushes the event as-is
|
||||
* 2) The element consumes the event and does not forward it
|
||||
* 3) The element consumes the event and creates another one instead
|
||||
* 4) The element pushes other serialized event before pushing out the
|
||||
* one it received
|
||||
*
|
||||
* For each pad we have two lists to track serialized events:
|
||||
* 1) We received on input and expect to see (serialized_events)
|
||||
* 2) We received on input but don't expect to see (expired_events)
|
||||
*
|
||||
* To detect events that are pushed in a different order from the one they were
|
||||
* received in we check that:
|
||||
*
|
||||
* For each event being outputted:
|
||||
* If it is in the expired_events list:
|
||||
* RAISE WARNING
|
||||
* If it is in the serialized_events list:
|
||||
* If there are other events that were received before:
|
||||
* Put those events on the expired_events list
|
||||
* Remove that event and any previous ones from the serialized_events list
|
||||
*
|
||||
* FIXME : When do we clear the expired_events list ?
|
||||
*
|
||||
*/
|
||||
|
||||
if (event == next_event->event
|
||||
|| GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
|
||||
g_ptr_array_remove_index (monitor->serialized_events, 0);
|
||||
}
|
||||
} else {
|
||||
/* if the event is not the first, it might be out of order */
|
||||
if (g_list_find (monitor->expired_events, event)) {
|
||||
/* If it's the expired events, we've failed */
|
||||
GST_WARNING_OBJECT (pad, "Did not expect event %p %s", event,
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
GST_VALIDATE_REPORT (monitor, EVENT_SERIALIZED_OUT_OF_ORDER,
|
||||
"Serialized event was pushed out of order: %" GST_PTR_FORMAT, event);
|
||||
monitor->expired_events =
|
||||
g_list_remove (monitor->expired_events, monitor);
|
||||
} else if (monitor->serialized_events->len) {
|
||||
for (i = 0; i < monitor->serialized_events->len; i++) {
|
||||
SerializedEventData *stored_event =
|
||||
SerializedEventData *next_event =
|
||||
g_ptr_array_index (monitor->serialized_events, i);
|
||||
GST_DEBUG_OBJECT (pad, "Checking against stored event #%d: %p %s", i,
|
||||
next_event->event, GST_EVENT_TYPE_NAME (next_event->event));
|
||||
|
||||
if (event == stored_event->event
|
||||
|| GST_EVENT_TYPE (event) == GST_EVENT_TYPE (stored_event->event)) {
|
||||
GST_VALIDATE_REPORT (monitor, EVENT_SERIALIZED_OUT_OF_ORDER,
|
||||
"Serialized event %" GST_PTR_FORMAT " was pushed out of original "
|
||||
"serialization order in pad %s:%s", event,
|
||||
GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)));
|
||||
if (event == next_event->event
|
||||
|| GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
|
||||
/* We have found our event */
|
||||
GST_DEBUG_OBJECT (pad, "Found matching event");
|
||||
|
||||
while (monitor->serialized_events->len > i
|
||||
&& GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
|
||||
/* Swallow all expected events of the same type */
|
||||
g_ptr_array_remove_index (monitor->serialized_events, i);
|
||||
next_event = g_ptr_array_index (monitor->serialized_events, i);
|
||||
}
|
||||
|
||||
/* Move all previous events to expired events */
|
||||
if (G_UNLIKELY (i > 0)) {
|
||||
GST_DEBUG_OBJECT (pad,
|
||||
"Moving previous expected events to expired list");
|
||||
while (i--) {
|
||||
next_event = g_ptr_array_index (monitor->serialized_events, 0);
|
||||
monitor->expired_events =
|
||||
g_list_append (monitor->expired_events, next_event->event);
|
||||
g_ptr_array_remove_index (monitor->serialized_events, 0);
|
||||
}
|
||||
}
|
||||
debug_pending_event (pad, monitor->serialized_events);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ struct _GstValidatePadMonitor {
|
|||
|
||||
GstEvent *expected_segment;
|
||||
GPtrArray *serialized_events;
|
||||
GList *expired_events;
|
||||
|
||||
GstStructure *pending_setcaps_fields;
|
||||
|
||||
|
|
Loading…
Reference in a new issue