From e94427e639ee042e757eaf5798317ae549160973 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 22 Jul 2013 15:05:04 -0300 Subject: [PATCH] pad-monitor: add check for serialized events order Store expected serialized events and their 'timestamps' to check if they are pushed in the same order/time as they were received --- validate/gst/qa/gst-qa-pad-monitor.c | 130 ++++++++++++++++++++++++++++++++++- validate/gst/qa/gst-qa-pad-monitor.h | 1 + 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/validate/gst/qa/gst-qa-pad-monitor.c b/validate/gst/qa/gst-qa-pad-monitor.c index 5d84df4..06c01c9 100644 --- a/validate/gst/qa/gst-qa-pad-monitor.c +++ b/validate/gst/qa/gst-qa-pad-monitor.c @@ -42,6 +42,19 @@ G_DEFINE_TYPE_WITH_CODE (GstQaPadMonitor, gst_qa_pad_monitor, #define PENDING_FIELDS "pending-fields" +typedef struct +{ + GstClockTime timestamp; + GstEvent *event; +} SerializedEventData; + +static void +_serialized_event_data_free (SerializedEventData * serialized_event) +{ + gst_event_unref (serialized_event->event); + g_slice_free (SerializedEventData, serialized_event); +} + static gboolean gst_qa_pad_monitor_do_setup (GstQaMonitor * monitor); /* This was copied from gstpad.c and might need @@ -307,6 +320,33 @@ gst_qa_pad_monitor_check_caps_fields_proxied (GstQaPadMonitor * monitor, } } +static void +gst_qa_pad_monitor_check_late_serialized_events (GstQaPadMonitor * monitor, + GstClockTime ts) +{ + gint i; + if (!GST_CLOCK_TIME_IS_VALID (ts)) + return; + + for (i = 0; i < monitor->serialized_events->len; i++) { + SerializedEventData *data = + g_ptr_array_index (monitor->serialized_events, i); + if (data->timestamp < ts) { + GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, EVENT, EXPECTED, + "Serialized event %" GST_PTR_FORMAT " wasn't pushed before expected " + "timestamp %" GST_TIME_FORMAT " on pad %s:%s", data->event, + GST_TIME_ARGS (data->timestamp), + GST_DEBUG_PAD_NAME (GST_QA_PAD_MONITOR_GET_PAD (monitor))); + } else { + /* events should be ordered by ts */ + break; + } + } + + if (i) + g_ptr_array_remove_range (monitor->serialized_events, 0, i); +} + void _parent_set_cb (GstObject * object, GstObject * parent, GstQaMonitor * monitor) { @@ -335,7 +375,7 @@ gst_qa_pad_monitor_dispose (GObject * object) gst_event_unref (monitor->expected_segment); gst_structure_free (monitor->pending_setcaps_fields); - + g_ptr_array_unref (monitor->serialized_events); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -359,6 +399,9 @@ gst_qa_pad_monitor_init (GstQaPadMonitor * pad_monitor) { pad_monitor->pending_setcaps_fields = gst_structure_empty_new (PENDING_FIELDS); + pad_monitor->serialized_events = + g_ptr_array_new_with_free_func ((GDestroyNotify) + _serialized_event_data_free); gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES); pad_monitor->first_buffer = TRUE; @@ -597,6 +640,46 @@ gst_qa_pad_monitor_check_aggregated_return (GstQaPadMonitor * monitor, } static void +gst_qa_pad_monitor_otherpad_add_pending_serialized_event (GstQaPadMonitor * + monitor, GstEvent * event, GstClockTime last_ts) +{ + GstIterator *iter; + gboolean done; + GstPad *otherpad; + GstQaPadMonitor *othermonitor; + + if (!GST_EVENT_IS_SERIALIZED (event)) + return; + + iter = gst_pad_iterate_internal_links (GST_QA_PAD_MONITOR_GET_PAD (monitor)); + done = FALSE; + while (!done) { + switch (gst_iterator_next (iter, (gpointer *) & otherpad)) { + case GST_ITERATOR_OK: + othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor"); + if (othermonitor) { + SerializedEventData *data = g_slice_new0 (SerializedEventData); + data->timestamp = last_ts; + data->event = gst_event_ref (event); + g_ptr_array_add (othermonitor->serialized_events, data); + } + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + GST_WARNING_OBJECT (monitor, "Internal links pad iteration error"); + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (iter); +} + +static void gst_qa_pad_monitor_otherpad_add_pending_field (GstQaPadMonitor * monitor, GstStructure * structure, const gchar * field) { @@ -991,6 +1074,20 @@ gst_qa_pad_monitor_sink_event_func (GstPad * pad, GstEvent * event) GstQaPadMonitor *pad_monitor = g_object_get_data ((GObject *) pad, "qa-monitor"); + if (GST_EVENT_IS_SERIALIZED (event)) { + GstClockTime last_ts; + if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_timestamp)) { + last_ts = pad_monitor->current_timestamp; + if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_duration)) { + last_ts += pad_monitor->current_duration; + } + } else { + last_ts = 0; + } + gst_qa_pad_monitor_otherpad_add_pending_serialized_event (pad_monitor, + event, last_ts); + } + return gst_qa_pad_monitor_sink_event_check (pad_monitor, event, pad_monitor->event_func); } @@ -1048,6 +1145,9 @@ gst_qa_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer, gst_qa_pad_monitor_check_buffer_timestamp_in_received_range (monitor, buffer); + gst_qa_pad_monitor_check_late_serialized_events (monitor, + GST_BUFFER_TIMESTAMP (buffer)); + /* TODO should we assume that a pad-monitor should always have an * element-monitor as a parent? */ if (G_LIKELY (GST_QA_MONITOR_GET_PARENT (monitor))) { @@ -1078,6 +1178,34 @@ static gboolean gst_qa_pad_monitor_event_probe (GstPad * pad, GstEvent * event, gpointer udata) { GstQaPadMonitor *monitor = GST_QA_PAD_MONITOR_CAST (udata); + + 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); + + if (event == next_event->event + || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) { + g_ptr_array_remove_index (monitor->serialized_events, 0); + } + } + + for (i = 0; i < monitor->serialized_events->len; i++) { + SerializedEventData *stored_event = + g_ptr_array_index (monitor->serialized_events, i); + + if (event == stored_event->event + || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (stored_event->event)) { + GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, EVENT, UNEXPECTED, + "Serialized event %" GST_PTR_FORMAT " was pushed out of original " + "serialization order in pad %s:%s", event, + GST_DEBUG_PAD_NAME (GST_QA_PAD_MONITOR_GET_PAD (monitor))); + } + } + } + /* This so far is just like an event that is flowing downstream, * so we do the same checks as a sinkpad event handler */ return gst_qa_pad_monitor_sink_event_check (monitor, event, NULL); diff --git a/validate/gst/qa/gst-qa-pad-monitor.h b/validate/gst/qa/gst-qa-pad-monitor.h index 8af927f..dbf8518 100644 --- a/validate/gst/qa/gst-qa-pad-monitor.h +++ b/validate/gst/qa/gst-qa-pad-monitor.h @@ -80,6 +80,7 @@ struct _GstQaPadMonitor { guint32 pending_newsegment_seqnum; GstEvent *expected_segment; + GPtrArray *serialized_events; GstStructure *pending_setcaps_fields; -- 2.7.4