pad-monitor: Handle out-of-segment first buffer
[platform/upstream/gstreamer.git] / validate / gst / validate / gst-validate-pad-monitor.c
1 /* GStreamer
2  *
3  * Copyright (C) 2013 Collabora Ltd.
4  *  Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
5  *
6  * gst-validate-pad-monitor.c - Validate PadMonitor class
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "gst-validate-internal.h"
29 #include "gst-validate-pad-monitor.h"
30 #include "gst-validate-element-monitor.h"
31 #include "gst-validate-reporter.h"
32 #include <string.h>
33 #include <stdarg.h>
34
35 /**
36  * SECTION:gst-validate-pad-monitor
37  * @short_description: Class that wraps a #GstPad for Validate checks
38  *
39  * TODO
40  */
41
42 #define gst_validate_pad_monitor_parent_class parent_class
43 G_DEFINE_TYPE (GstValidatePadMonitor, gst_validate_pad_monitor,
44     GST_TYPE_VALIDATE_MONITOR);
45
46 #define PENDING_FIELDS "pending-fields"
47 #define AUDIO_TIMESTAMP_TOLERANCE (GST_MSECOND * 100)
48
49 #define PAD_PARENT_IS_DEMUXER(m) \
50     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
51         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DEMUXER ( \
52             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
53         FALSE)
54
55 #define PAD_PARENT_IS_DECODER(m) \
56     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
57         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DECODER ( \
58             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
59         FALSE)
60
61 #define PAD_PARENT_IS_ENCODER(m) \
62     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
63         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_ENCODER ( \
64             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
65         FALSE)
66
67
68 /*
69  * Locking the parent should always be done before locking the
70  * pad-monitor to prevent deadlocks in case another monitor from
71  * another pad on the same element starts an operation that also
72  * requires locking itself and some other monitors from internally
73  * linked pads.
74  *
75  * An example:
76  * An element has a sink and a src pad. Some test starts running at sinkpad
77  * and it locks the parent, and then it locks itself. In case it needs to get
78  * some information from the srcpad, it is able to lock the srcpad and get it
79  * because the srcpad should never lock itself before locking the parent (which
80  * it won't be able as sinkpad already locked it).
81  *
82  * As a side one, it is possible that srcpad locks itself without locking the
83  * parent in case it wants to do a check that won't need to use other internally
84  * linked pads (sinkpad). But in this case it might lock and unlock freely without
85  * causing deadlocks.
86  */
87 #define GST_VALIDATE_PAD_MONITOR_PARENT_LOCK(m)                  \
88 G_STMT_START {                                             \
89   if (G_LIKELY (GST_VALIDATE_MONITOR_GET_PARENT (m))) {          \
90     GST_VALIDATE_MONITOR_LOCK (GST_VALIDATE_MONITOR_GET_PARENT (m));   \
91   } else {                                                 \
92     GST_WARNING_OBJECT (m, "No parent found, can't lock"); \
93   }                                                        \
94 } G_STMT_END
95
96 #define GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK(m)                  \
97 G_STMT_START {                                               \
98   if (G_LIKELY (GST_VALIDATE_MONITOR_GET_PARENT (m))) {            \
99     GST_VALIDATE_MONITOR_UNLOCK (GST_VALIDATE_MONITOR_GET_PARENT (m));   \
100   } else {                                                   \
101     GST_WARNING_OBJECT (m, "No parent found, can't unlock"); \
102   }                                                          \
103 } G_STMT_END
104
105 typedef struct
106 {
107   GstClockTime timestamp;
108   GstEvent *event;
109 } SerializedEventData;
110
111 static void
112 debug_pending_event (GstPad * pad, GPtrArray * array)
113 {
114   guint i, len;
115
116   len = array->len;
117   for (i = 0; i < len; i++) {
118     SerializedEventData *data = g_ptr_array_index (array, i);
119     GST_DEBUG_OBJECT (pad, "event #%d %" GST_TIME_FORMAT " %s %p",
120         i, GST_TIME_ARGS (data->timestamp),
121         GST_EVENT_TYPE_NAME (data->event), data->event);
122   }
123 }
124
125 static void
126 _serialized_event_data_free (SerializedEventData * serialized_event)
127 {
128   gst_event_unref (serialized_event->event);
129   g_slice_free (SerializedEventData, serialized_event);
130 }
131
132 static gboolean gst_validate_pad_monitor_do_setup (GstValidateMonitor *
133     monitor);
134 static GstElement *gst_validate_pad_monitor_get_element (GstValidateMonitor *
135     monitor);
136 static void
137 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
138     GstCaps * caps);
139 static void gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor *
140     pad_monitor, GstCaps * caps, gboolean ret);
141
142 #define PAD_IS_IN_PUSH_MODE(p) ((p)->mode == GST_PAD_MODE_PUSH)
143
144 static gboolean
145 _structure_is_raw_video (GstStructure * structure)
146 {
147   return gst_structure_has_name (structure, "video/x-raw");
148 }
149
150 static gboolean
151 _structure_is_raw_audio (GstStructure * structure)
152 {
153   return gst_structure_has_name (structure, "audio/x-raw");
154 }
155
156 static gchar *
157 _get_event_string (GstEvent * event)
158 {
159   const GstStructure *st;
160
161   if ((st = gst_event_get_structure (event)))
162     return gst_structure_to_string (st);
163   else
164     return g_strdup_printf ("%s", GST_EVENT_TYPE_NAME (event));
165 }
166
167 static void
168 _check_field_type (GstValidatePadMonitor * monitor,
169     GstStructure * structure, gboolean mandatory, const gchar * field, ...)
170 {
171   va_list var_args;
172   GType type;
173   gchar *joined_types = NULL;
174   const gchar *rejected_types[5];
175   gint rejected_types_index = 0;
176   gchar *struct_str;
177
178   if (!gst_structure_has_field (structure, field)) {
179     if (mandatory) {
180       gchar *str = gst_structure_to_string (structure);
181
182       GST_VALIDATE_REPORT (monitor, CAPS_IS_MISSING_FIELD,
183           "Field '%s' is missing from structure: %s", field, str);
184       g_free (str);
185     } else {
186       GST_DEBUG_OBJECT (monitor, "Field %s is missing but is not mandatory",
187           field);
188     }
189     return;
190   }
191
192   memset (rejected_types, 0, sizeof (rejected_types));
193   va_start (var_args, field);
194   while ((type = va_arg (var_args, GType)) != 0) {
195     if (gst_structure_has_field_typed (structure, field, type)) {
196       va_end (var_args);
197       return;
198     }
199     rejected_types[rejected_types_index++] = g_type_name (type);
200   }
201   va_end (var_args);
202
203   joined_types = g_strjoinv (" / ", (gchar **) rejected_types);
204   struct_str = gst_structure_to_string (structure);
205   GST_VALIDATE_REPORT (monitor, CAPS_FIELD_HAS_BAD_TYPE,
206       "Field '%s' has wrong type %s in structure '%s'. Expected: %s", field,
207       g_type_name (gst_structure_get_field_type (structure, field)), struct_str,
208       joined_types);
209   g_free (joined_types);
210   g_free (struct_str);
211 }
212
213 static void
214 gst_validate_pad_monitor_check_raw_video_caps_complete (GstValidatePadMonitor *
215     monitor, GstStructure * structure)
216 {
217   _check_field_type (monitor, structure, TRUE, "width", G_TYPE_INT,
218       GST_TYPE_INT_RANGE, 0);
219   _check_field_type (monitor, structure, TRUE, "height", G_TYPE_INT,
220       GST_TYPE_INT_RANGE, 0);
221   _check_field_type (monitor, structure, TRUE, "framerate", GST_TYPE_FRACTION,
222       GST_TYPE_FRACTION_RANGE, 0);
223   _check_field_type (monitor, structure, FALSE, "pixel-aspect-ratio",
224       GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, 0);
225   _check_field_type (monitor, structure, TRUE, "format", G_TYPE_STRING,
226       GST_TYPE_LIST);
227 }
228
229 static void
230 gst_validate_pad_monitor_check_raw_audio_caps_complete (GstValidatePadMonitor *
231     monitor, GstStructure * structure)
232 {
233   gint channels;
234   _check_field_type (monitor, structure, TRUE, "format", G_TYPE_STRING,
235       GST_TYPE_LIST, 0);
236   _check_field_type (monitor, structure, TRUE, "layout", G_TYPE_STRING,
237       GST_TYPE_LIST, 0);
238   _check_field_type (monitor, structure, TRUE, "rate", G_TYPE_INT,
239       GST_TYPE_LIST, GST_TYPE_INT_RANGE, 0);
240   _check_field_type (monitor, structure, TRUE, "channels", G_TYPE_INT,
241       GST_TYPE_LIST, GST_TYPE_INT_RANGE, 0);
242   if (gst_structure_get_int (structure, "channels", &channels)) {
243     if (channels > 2)
244       _check_field_type (monitor, structure, TRUE, "channel-mask",
245           GST_TYPE_BITMASK, GST_TYPE_LIST, 0);
246   }
247 }
248
249 static void
250 gst_validate_pad_monitor_check_caps_complete (GstValidatePadMonitor * monitor,
251     GstCaps * caps)
252 {
253   GstStructure *structure;
254   gint i;
255
256   GST_DEBUG_OBJECT (monitor->pad, "Checking caps %" GST_PTR_FORMAT, caps);
257
258   for (i = 0; i < gst_caps_get_size (caps); i++) {
259     structure = gst_caps_get_structure (caps, i);
260
261     if (_structure_is_raw_video (structure)) {
262       gst_validate_pad_monitor_check_raw_video_caps_complete (monitor,
263           structure);
264
265     } else if (_structure_is_raw_audio (structure)) {
266       gst_validate_pad_monitor_check_raw_audio_caps_complete (monitor,
267           structure);
268     }
269   }
270 }
271
272 static GstCaps *
273 gst_validate_pad_monitor_get_othercaps (GstValidatePadMonitor * monitor)
274 {
275   GstCaps *caps = gst_caps_new_empty ();
276   GstIterator *iter;
277   gboolean done;
278   GstPad *otherpad;
279   GstCaps *peercaps;
280
281   iter =
282       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
283       (monitor));
284   done = FALSE;
285   while (!done) {
286     GValue value = { 0, };
287     switch (gst_iterator_next (iter, &value)) {
288       case GST_ITERATOR_OK:
289         otherpad = g_value_get_object (&value);
290
291         /* TODO What would be the correct caps operation to merge the caps in
292          * case one sink is internally linked to multiple srcs? */
293         peercaps = gst_pad_get_current_caps (otherpad);
294         if (peercaps)
295           caps = gst_caps_merge (caps, peercaps);
296
297         g_value_reset (&value);
298         break;
299       case GST_ITERATOR_RESYNC:
300         gst_iterator_resync (iter);
301         gst_caps_replace (&caps, gst_caps_new_empty ());
302         break;
303       case GST_ITERATOR_ERROR:
304         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
305         done = TRUE;
306         break;
307       case GST_ITERATOR_DONE:
308         done = TRUE;
309         break;
310     }
311   }
312   gst_iterator_free (iter);
313
314   GST_DEBUG_OBJECT (monitor->pad, "Otherpad caps: %" GST_PTR_FORMAT, caps);
315
316   return caps;
317 }
318
319 static gboolean
320 _structure_is_video (GstStructure * structure)
321 {
322   const gchar *name = gst_structure_get_name (structure);
323
324   return g_strstr_len (name, 6, "video/")
325       && strcmp (name, "video/quicktime") != 0;
326 }
327
328 static gboolean
329 _structure_is_audio (GstStructure * structure)
330 {
331   const gchar *name = gst_structure_get_name (structure);
332
333   return g_strstr_len (name, 6, "audio/") != NULL;
334 }
335
336 static gboolean
337 gst_validate_pad_monitor_pad_should_proxy_othercaps (GstValidatePadMonitor *
338     monitor)
339 {
340   GstValidateMonitor *parent = GST_VALIDATE_MONITOR_GET_PARENT (monitor);
341
342   if (!parent)
343     return FALSE;
344
345   /* We only know how to handle othercaps checks for codecs so far */
346   return GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DECODER (parent) ||
347       GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_ENCODER (parent);
348 }
349
350
351 /* Check if the field @f from @s2 (if present) is represented in @s1
352  * Represented here means either equal or @s1's value is in a list/range
353  * from @s2
354  */
355 static gboolean
356 _structures_field_is_contained (GstStructure * s1, GstStructure * s2,
357     gboolean mandatory, const gchar * f)
358 {
359   const GValue *v1;
360   const GValue *v2;
361
362   v2 = gst_structure_get_value (s2, f);
363   if (!v2)
364     return TRUE;                /* nothing to compare to */
365
366   v1 = gst_structure_get_value (s1, f);
367   if (!v1)
368     return !mandatory;
369
370   if (!gst_value_is_fixed (v1) && !gst_value_is_fixed (v2))
371     return TRUE;
372
373   if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
374     return TRUE;
375
376   if (GST_VALUE_HOLDS_LIST (v2)) {
377     gint i;
378     for (i = 0; i < gst_value_list_get_size (v2); i++) {
379       const GValue *v2_subvalue = gst_value_list_get_value (v2, i);
380       if (gst_value_compare (v1, v2_subvalue) == GST_VALUE_EQUAL)
381         return TRUE;
382     }
383   }
384
385   if (GST_VALUE_HOLDS_ARRAY (v2)) {
386     gint i;
387     for (i = 0; i < gst_value_array_get_size (v2); i++) {
388       const GValue *v2_subvalue = gst_value_array_get_value (v2, i);
389       if (gst_value_compare (v1, v2_subvalue) == GST_VALUE_EQUAL)
390         return TRUE;
391     }
392   }
393
394   if (GST_VALUE_HOLDS_INT_RANGE (v2)) {
395     gint min, max;
396
397     min = gst_value_get_int_range_min (v2);
398     max = gst_value_get_int_range_max (v2);
399
400     if (G_VALUE_HOLDS_INT (v1)) {
401       gint v = g_value_get_int (v1);
402
403       return v >= min && v <= max;
404     } else {
405       /* TODO compare int ranges with int ranges
406        * or with lists if useful */
407     }
408   }
409
410   if (GST_VALUE_HOLDS_FRACTION_RANGE (v2)) {
411     const GValue *min, *max;
412
413     min = gst_value_get_fraction_range_min (v2);
414     max = gst_value_get_fraction_range_max (v2);
415
416     if (GST_VALUE_HOLDS_FRACTION (v1)) {
417       gint v_min = gst_value_compare (v1, min);
418       gint v_max = gst_value_compare (v1, max);
419
420       return (v_min == GST_VALUE_EQUAL || v_min == GST_VALUE_GREATER_THAN) &&
421           (v_max == GST_VALUE_EQUAL || v_max == GST_VALUE_LESS_THAN);
422     } else {
423       /* TODO compare fraction ranges with fraction ranges
424        * or with lists if useful */
425     }
426   }
427
428   return FALSE;
429 }
430
431 static void
432 gst_validate_pad_monitor_check_caps_fields_proxied (GstValidatePadMonitor *
433     monitor, GstCaps * caps)
434 {
435   GstStructure *structure;
436   GstStructure *otherstructure;
437   GstCaps *othercaps;
438   gint i, j;
439
440   if (!gst_validate_pad_monitor_pad_should_proxy_othercaps (monitor))
441     return;
442
443   othercaps = gst_validate_pad_monitor_get_othercaps (monitor);
444
445   for (i = 0; i < gst_caps_get_size (othercaps); i++) {
446     gboolean found = FALSE;
447     gboolean type_match = FALSE;
448
449     otherstructure = gst_caps_get_structure (othercaps, i);
450
451     /* look for a proxied version of 'otherstructure' */
452     if (_structure_is_video (otherstructure)) {
453       for (j = 0; j < gst_caps_get_size (caps); j++) {
454         structure = gst_caps_get_structure (caps, j);
455         if (_structure_is_video (structure)) {
456           type_match = TRUE;
457           if (_structures_field_is_contained (structure, otherstructure, TRUE,
458                   "width")
459               && _structures_field_is_contained (structure, otherstructure,
460                   TRUE, "height")
461               && _structures_field_is_contained (structure, otherstructure,
462                   TRUE, "framerate")
463               && _structures_field_is_contained (structure, otherstructure,
464                   FALSE, "pixel-aspect-ratio")) {
465             found = TRUE;
466             break;
467           }
468         }
469       }
470     } else if (_structure_is_audio (otherstructure)) {
471       for (j = 0; j < gst_caps_get_size (caps); j++) {
472         structure = gst_caps_get_structure (caps, j);
473         if (_structure_is_audio (structure)) {
474           type_match = TRUE;
475           if (_structures_field_is_contained (structure, otherstructure, TRUE,
476                   "rate")
477               && _structures_field_is_contained (structure, otherstructure,
478                   TRUE, "channels")) {
479             found = TRUE;
480             break;
481           }
482         }
483       }
484     }
485
486     if (type_match && !found) {
487       gchar *otherstruct_str = gst_structure_to_string (otherstructure),
488           *caps_str = gst_caps_to_string (caps);
489
490       GST_VALIDATE_REPORT (monitor, GET_CAPS_NOT_PROXYING_FIELDS,
491           "Peer pad structure '%s' has no similar version "
492           "on pad's caps '%s'", otherstruct_str, caps_str);
493
494       g_free (otherstruct_str);
495       g_free (caps_str);
496     }
497   }
498 }
499
500 static void
501 gst_validate_pad_monitor_check_late_serialized_events (GstValidatePadMonitor *
502     monitor, GstClockTime ts)
503 {
504   gint i;
505
506   if (!GST_CLOCK_TIME_IS_VALID (ts))
507     return;
508
509   GST_DEBUG_OBJECT (monitor->pad, "Timestamp to check %" GST_TIME_FORMAT,
510       GST_TIME_ARGS (ts));
511
512   for (i = 0; i < monitor->serialized_events->len; i++) {
513     SerializedEventData *data =
514         g_ptr_array_index (monitor->serialized_events, i);
515
516     GST_DEBUG_OBJECT (monitor->pad, "Event #%d (%s) ts: %" GST_TIME_FORMAT,
517         i, GST_EVENT_TYPE_NAME (data->event), GST_TIME_ARGS (data->timestamp));
518
519     if (GST_CLOCK_TIME_IS_VALID (data->timestamp) && data->timestamp < ts) {
520       gchar *event_str = _get_event_string (data->event);
521
522       GST_VALIDATE_REPORT (monitor, SERIALIZED_EVENT_WASNT_PUSHED_IN_TIME,
523           "Serialized event %s wasn't pushed before expected " "timestamp %"
524           GST_TIME_FORMAT " on pad %s:%s", event_str,
525           GST_TIME_ARGS (data->timestamp),
526           GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)));
527
528       g_free (event_str);
529     } else {
530       /* events should be ordered by ts */
531       break;
532     }
533   }
534
535   if (i) {
536     debug_pending_event (monitor->pad, monitor->serialized_events);
537     g_ptr_array_remove_range (monitor->serialized_events, 0, i);
538   }
539 }
540
541 static void
542 gst_validate_pad_monitor_dispose (GObject * object)
543 {
544   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (object);
545   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
546
547   if (pad) {
548     if (monitor->pad_probe_id)
549       gst_pad_remove_probe (pad, monitor->pad_probe_id);
550   }
551
552   if (monitor->expected_segment)
553     gst_event_unref (monitor->expected_segment);
554
555   gst_structure_free (monitor->pending_setcaps_fields);
556   g_ptr_array_unref (monitor->serialized_events);
557   g_list_free_full (monitor->expired_events, (GDestroyNotify) gst_event_unref);
558
559   G_OBJECT_CLASS (parent_class)->dispose (object);
560 }
561
562 static void
563 gst_validate_pad_monitor_class_init (GstValidatePadMonitorClass * klass)
564 {
565   GObjectClass *gobject_class;
566   GstValidateMonitorClass *monitor_klass;
567
568   gobject_class = G_OBJECT_CLASS (klass);
569   monitor_klass = GST_VALIDATE_MONITOR_CLASS (klass);
570
571   gobject_class->dispose = gst_validate_pad_monitor_dispose;
572
573   monitor_klass->setup = gst_validate_pad_monitor_do_setup;
574   monitor_klass->get_element = gst_validate_pad_monitor_get_element;
575 }
576
577 static void
578 gst_validate_pad_monitor_init (GstValidatePadMonitor * pad_monitor)
579 {
580   pad_monitor->pending_setcaps_fields =
581       gst_structure_new_empty (PENDING_FIELDS);
582   pad_monitor->serialized_events =
583       g_ptr_array_new_with_free_func ((GDestroyNotify)
584       _serialized_event_data_free);
585   pad_monitor->expired_events = NULL;
586   gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES);
587   pad_monitor->first_buffer = TRUE;
588
589   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
590   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
591 }
592
593 /**
594  * gst_validate_pad_monitor_new:
595  * @pad: (transfer-none): a #GstPad to run Validate on
596  */
597 GstValidatePadMonitor *
598 gst_validate_pad_monitor_new (GstPad * pad, GstValidateRunner * runner,
599     GstValidateElementMonitor * parent)
600 {
601   GstValidatePadMonitor *monitor = g_object_new (GST_TYPE_VALIDATE_PAD_MONITOR,
602       "object", pad, "validate-runner", runner, "validate-parent",
603       parent, NULL);
604
605   if (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor) == NULL) {
606     g_object_unref (monitor);
607     return NULL;
608   }
609   return monitor;
610 }
611
612 static GstElement *
613 gst_validate_pad_monitor_get_element (GstValidateMonitor * monitor)
614 {
615   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
616
617   return GST_PAD_PARENT (pad);
618 }
619
620 static void
621 gst_validate_pad_monitor_event_overrides (GstValidatePadMonitor * pad_monitor,
622     GstEvent * event)
623 {
624   GList *iter;
625
626   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
627   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
628       iter = g_list_next (iter)) {
629     GstValidateOverride *override = iter->data;
630
631     gst_validate_override_event_handler (override,
632         GST_VALIDATE_MONITOR_CAST (pad_monitor), event);
633   }
634   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
635 }
636
637 static void
638 gst_validate_pad_monitor_buffer_overrides (GstValidatePadMonitor * pad_monitor,
639     GstBuffer * buffer)
640 {
641   GList *iter;
642
643   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
644   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
645       iter = g_list_next (iter)) {
646     GstValidateOverride *override = iter->data;
647
648     gst_validate_override_buffer_handler (override,
649         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
650   }
651   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
652 }
653
654 static void
655 gst_validate_pad_monitor_buffer_probe_overrides (GstValidatePadMonitor *
656     pad_monitor, GstBuffer * buffer)
657 {
658   GList *iter;
659
660   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
661   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
662       iter = g_list_next (iter)) {
663     GstValidateOverride *override = iter->data;
664
665     gst_validate_override_buffer_probe_handler (override,
666         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
667   }
668   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
669 }
670
671 static void
672 gst_validate_pad_monitor_query_overrides (GstValidatePadMonitor * pad_monitor,
673     GstQuery * query)
674 {
675   GList *iter;
676
677   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
678   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
679       iter = g_list_next (iter)) {
680     GstValidateOverride *override = iter->data;
681
682     gst_validate_override_query_handler (override,
683         GST_VALIDATE_MONITOR_CAST (pad_monitor), query);
684   }
685   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
686 }
687
688 static void
689 gst_validate_pad_monitor_setcaps_overrides (GstValidatePadMonitor * pad_monitor,
690     GstCaps * caps)
691 {
692   GList *iter;
693
694   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
695   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
696       iter = g_list_next (iter)) {
697     GstValidateOverride *override = iter->data;
698
699     gst_validate_override_setcaps_handler (override,
700         GST_VALIDATE_MONITOR_CAST (pad_monitor), caps);
701   }
702   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
703 }
704
705 /* FIXME : This is a bit dubious, what's the point of this check ? */
706 static gboolean
707 gst_validate_pad_monitor_timestamp_is_in_received_range (GstValidatePadMonitor *
708     monitor, GstClockTime ts, GstClockTime tolerance)
709 {
710   GST_DEBUG_OBJECT (monitor->pad, "Checking if timestamp %" GST_TIME_FORMAT
711       " is in range: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT " for pad "
712       "%s:%s with tolerance: %" GST_TIME_FORMAT, GST_TIME_ARGS (ts),
713       GST_TIME_ARGS (monitor->timestamp_range_start),
714       GST_TIME_ARGS (monitor->timestamp_range_end),
715       GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)),
716       GST_TIME_ARGS (tolerance));
717   return !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_start) ||
718       !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_end) ||
719       ((monitor->timestamp_range_start >= tolerance ?
720           monitor->timestamp_range_start - tolerance : 0) <= ts
721       && (ts >= tolerance ? ts - tolerance : 0) <=
722       monitor->timestamp_range_end);
723 }
724
725 /* Iterates over internal links (sinkpads) to check that this buffer has
726  * a timestamp that is in the range of the lastly received buffers */
727 static void
728     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range
729     (GstValidatePadMonitor * monitor, GstBuffer * buffer,
730     GstClockTime tolerance)
731 {
732   GstClockTime ts;
733   GstClockTime ts_end;
734   GstIterator *iter;
735   gboolean has_one = FALSE;
736   gboolean found = FALSE;
737   gboolean done;
738   GstPad *otherpad;
739   GstValidatePadMonitor *othermonitor;
740
741   if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))
742       || !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
743     GST_DEBUG_OBJECT (monitor->pad,
744         "Can't check buffer timestamps range as "
745         "buffer has no valid timestamp/duration");
746     return;
747   }
748   ts = GST_BUFFER_TIMESTAMP (buffer);
749   ts_end = ts + GST_BUFFER_DURATION (buffer);
750
751   iter =
752       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
753       (monitor));
754
755   if (iter == NULL) {
756     GST_WARNING_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor),
757         "No iterator available");
758     return;
759   }
760
761   done = FALSE;
762   while (!done) {
763     GValue value = { 0, };
764     switch (gst_iterator_next (iter, &value)) {
765       case GST_ITERATOR_OK:
766         otherpad = g_value_get_object (&value);
767         GST_DEBUG_OBJECT (monitor->pad, "Checking pad %s:%s input timestamps",
768             GST_DEBUG_PAD_NAME (otherpad));
769         othermonitor =
770             g_object_get_data ((GObject *) otherpad, "validate-monitor");
771         GST_VALIDATE_MONITOR_LOCK (othermonitor);
772         if (gst_validate_pad_monitor_timestamp_is_in_received_range
773             (othermonitor, ts, tolerance)
774             &&
775             gst_validate_pad_monitor_timestamp_is_in_received_range
776             (othermonitor, ts_end, tolerance)) {
777           done = TRUE;
778           found = TRUE;
779         }
780         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
781         g_value_reset (&value);
782         has_one = TRUE;
783         break;
784       case GST_ITERATOR_RESYNC:
785         gst_iterator_resync (iter);
786         has_one = FALSE;
787         found = FALSE;
788         break;
789       case GST_ITERATOR_ERROR:
790         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
791         done = TRUE;
792         break;
793       case GST_ITERATOR_DONE:
794         done = TRUE;
795         break;
796     }
797   }
798   gst_iterator_free (iter);
799
800   if (!has_one) {
801     GST_DEBUG_OBJECT (monitor->pad, "Skipping timestamp in range check as no "
802         "internal linked pad was found");
803     return;
804   }
805   if (!found) {
806     GST_VALIDATE_REPORT (monitor, BUFFER_TIMESTAMP_OUT_OF_RECEIVED_RANGE,
807         "Timestamp %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT
808         " is out of range of received input", GST_TIME_ARGS (ts),
809         GST_TIME_ARGS (ts_end));
810   }
811 }
812
813 static void
814 gst_validate_pad_monitor_check_first_buffer (GstValidatePadMonitor *
815     pad_monitor, GstBuffer * buffer)
816 {
817   if (G_UNLIKELY (pad_monitor->first_buffer)) {
818     pad_monitor->first_buffer = FALSE;
819
820     if (!pad_monitor->has_segment
821         && PAD_IS_IN_PUSH_MODE (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)))
822     {
823       GST_VALIDATE_REPORT (pad_monitor, BUFFER_BEFORE_SEGMENT,
824           "Received buffer before Segment event");
825     }
826
827     GST_DEBUG_OBJECT (pad_monitor->pad,
828         "Checking first buffer (pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
829         ")", GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
830         GST_TIME_ARGS (GST_BUFFER_DTS (buffer)));
831
832     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
833       gint64 running_time = gst_segment_to_running_time (&pad_monitor->segment,
834           pad_monitor->segment.format, GST_BUFFER_TIMESTAMP (buffer));
835       /* Only check for in-segment buffers */
836       if (GST_CLOCK_TIME_IS_VALID (running_time) && running_time != 0) {
837         GST_VALIDATE_REPORT (pad_monitor, FIRST_BUFFER_RUNNING_TIME_IS_NOT_ZERO,
838             "First buffer running time is not 0, it is: %" GST_TIME_FORMAT,
839             GST_TIME_ARGS (running_time));
840       }
841     }
842   }
843 }
844
845 static void
846 gst_validate_pad_monitor_check_eos (GstValidatePadMonitor *
847     pad_monitor, GstBuffer * buffer)
848 {
849   if (G_UNLIKELY (pad_monitor->is_eos)) {
850     GST_VALIDATE_REPORT (pad_monitor, BUFFER_AFTER_EOS,
851         "Received buffer %" GST_PTR_FORMAT " after EOS", buffer);
852   }
853 }
854
855 static void
856 gst_validate_pad_monitor_update_buffer_data (GstValidatePadMonitor *
857     pad_monitor, GstBuffer * buffer)
858 {
859   pad_monitor->current_timestamp = GST_BUFFER_TIMESTAMP (buffer);
860   pad_monitor->current_duration = GST_BUFFER_DURATION (buffer);
861   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
862     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_start)) {
863       pad_monitor->timestamp_range_start =
864           MIN (pad_monitor->timestamp_range_start,
865           GST_BUFFER_TIMESTAMP (buffer));
866     } else {
867       pad_monitor->timestamp_range_start = GST_BUFFER_TIMESTAMP (buffer);
868     }
869
870     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
871       GstClockTime endts =
872           GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
873       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_end)) {
874         pad_monitor->timestamp_range_end =
875             MAX (pad_monitor->timestamp_range_end, endts);
876       } else {
877         pad_monitor->timestamp_range_end = endts;
878       }
879     }
880   }
881   GST_DEBUG_OBJECT (pad_monitor->pad, "Current stored range: %" GST_TIME_FORMAT
882       " - %" GST_TIME_FORMAT,
883       GST_TIME_ARGS (pad_monitor->timestamp_range_start),
884       GST_TIME_ARGS (pad_monitor->timestamp_range_end));
885 }
886
887 static GstFlowReturn
888 _combine_flows (GstFlowReturn ret1, GstFlowReturn ret2)
889 {
890   if (ret1 == ret2)
891     return ret1;
892   if (ret1 <= GST_FLOW_NOT_NEGOTIATED)
893     return ret1;
894   if (ret2 <= GST_FLOW_NOT_NEGOTIATED)
895     return ret2;
896   if (ret1 == GST_FLOW_FLUSHING || ret2 == GST_FLOW_FLUSHING)
897     return GST_FLOW_FLUSHING;
898   if (ret1 == GST_FLOW_OK || ret2 == GST_FLOW_OK)
899     return GST_FLOW_OK;
900   return ret2;
901 }
902
903 static void
904 gst_validate_pad_monitor_check_aggregated_return (GstValidatePadMonitor *
905     monitor, GstFlowReturn ret)
906 {
907   GstIterator *iter;
908   gboolean done;
909   GstPad *otherpad;
910   GstPad *peerpad;
911   GstValidatePadMonitor *othermonitor;
912   GstFlowReturn aggregated = GST_FLOW_NOT_LINKED;
913   gboolean found_a_pad = FALSE;
914   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
915
916   iter = gst_pad_iterate_internal_links (pad);
917   done = FALSE;
918   while (!done) {
919     GValue value = { 0, };
920     switch (gst_iterator_next (iter, &value)) {
921       case GST_ITERATOR_OK:
922         otherpad = g_value_get_object (&value);
923         peerpad = gst_pad_get_peer (otherpad);
924         if (peerpad) {
925           othermonitor =
926               g_object_get_data ((GObject *) peerpad, "validate-monitor");
927           if (othermonitor) {
928             found_a_pad = TRUE;
929             GST_VALIDATE_MONITOR_LOCK (othermonitor);
930             aggregated =
931                 _combine_flows (aggregated, othermonitor->last_flow_return);
932             GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
933           }
934
935           gst_object_unref (peerpad);
936         }
937         g_value_reset (&value);
938         break;
939       case GST_ITERATOR_RESYNC:
940         gst_iterator_resync (iter);
941         break;
942       case GST_ITERATOR_ERROR:
943         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
944         done = TRUE;
945         break;
946       case GST_ITERATOR_DONE:
947         done = TRUE;
948         break;
949     }
950   }
951   gst_iterator_free (iter);
952   if (!found_a_pad) {
953     /* no peer pad found, nothing to do */
954     return;
955   }
956   if (aggregated == GST_FLOW_OK || aggregated == GST_FLOW_EOS) {
957     /* those are acceptable situations */
958
959     if (GST_PAD_IS_FLUSHING (pad) && ret == GST_FLOW_FLUSHING) {
960       /* pad is flushing, always acceptable to return flushing */
961       return;
962     }
963
964     if (monitor->is_eos && ret == GST_FLOW_EOS) {
965       /* this element received eos and returned eos */
966       return;
967     }
968
969     if (PAD_PARENT_IS_DEMUXER (monitor) && ret == GST_FLOW_EOS) {
970       /* a demuxer can return EOS when the samples end */
971       return;
972     }
973   }
974
975   if (aggregated != ret) {
976     GST_VALIDATE_REPORT (monitor, WRONG_FLOW_RETURN,
977         "Wrong combined flow return %s(%d). Expected: %s(%d)",
978         gst_flow_get_name (ret), ret, gst_flow_get_name (aggregated),
979         aggregated);
980   }
981 }
982
983 static void
984     gst_validate_pad_monitor_otherpad_add_pending_serialized_event
985     (GstValidatePadMonitor * monitor, GstEvent * event, GstClockTime last_ts)
986 {
987   GstIterator *iter;
988   gboolean done;
989   GstPad *otherpad;
990   GstValidatePadMonitor *othermonitor;
991
992   if (!GST_EVENT_IS_SERIALIZED (event))
993     return;
994
995   iter =
996       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
997       (monitor));
998   if (iter == NULL) {
999     /* inputselector will return NULL if the sinkpad is not the active one .... */
1000     GST_FIXME_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD
1001         (monitor), "No iterator");
1002     return;
1003   }
1004   done = FALSE;
1005   while (!done) {
1006     GValue value = { 0, };
1007     switch (gst_iterator_next (iter, &value)) {
1008       case GST_ITERATOR_OK:
1009         otherpad = g_value_get_object (&value);
1010         othermonitor =
1011             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1012         if (othermonitor) {
1013           SerializedEventData *data = g_slice_new0 (SerializedEventData);
1014           data->timestamp = last_ts;
1015           data->event = gst_event_ref (event);
1016           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1017           GST_DEBUG_OBJECT (monitor->pad, "Storing for pad %s:%s event %p %s",
1018               GST_DEBUG_PAD_NAME (otherpad), event,
1019               GST_EVENT_TYPE_NAME (event));
1020           g_ptr_array_add (othermonitor->serialized_events, data);
1021           debug_pending_event (otherpad, othermonitor->serialized_events);
1022           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1023         }
1024         g_value_reset (&value);
1025         break;
1026       case GST_ITERATOR_RESYNC:
1027         gst_iterator_resync (iter);
1028         break;
1029       case GST_ITERATOR_ERROR:
1030         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1031         done = TRUE;
1032         break;
1033       case GST_ITERATOR_DONE:
1034         done = TRUE;
1035         break;
1036     }
1037   }
1038   gst_iterator_free (iter);
1039 }
1040
1041 static void
1042 gst_validate_pad_monitor_otherpad_add_pending_field (GstValidatePadMonitor *
1043     monitor, GstStructure * structure, const gchar * field)
1044 {
1045   GstIterator *iter;
1046   gboolean done;
1047   GstPad *otherpad;
1048   GstValidatePadMonitor *othermonitor;
1049   const GValue *v;
1050
1051   v = gst_structure_get_value (structure, field);
1052   if (v == NULL) {
1053     GST_DEBUG_OBJECT (monitor->pad, "Not adding pending field %s as it isn't "
1054         "present on structure %" GST_PTR_FORMAT, field, structure);
1055     return;
1056   }
1057
1058   iter =
1059       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1060       (monitor));
1061   done = FALSE;
1062   while (!done) {
1063     GValue value = { 0, };
1064     switch (gst_iterator_next (iter, &value)) {
1065       case GST_ITERATOR_OK:
1066         otherpad = g_value_get_object (&value);
1067         othermonitor =
1068             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1069         if (othermonitor) {
1070           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1071           g_assert (othermonitor->pending_setcaps_fields != NULL);
1072           gst_structure_set_value (othermonitor->pending_setcaps_fields,
1073               field, v);
1074           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1075         }
1076         g_value_reset (&value);
1077         break;
1078       case GST_ITERATOR_RESYNC:
1079         gst_iterator_resync (iter);
1080         break;
1081       case GST_ITERATOR_ERROR:
1082         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1083         done = TRUE;
1084         break;
1085       case GST_ITERATOR_DONE:
1086         done = TRUE;
1087         break;
1088     }
1089   }
1090   gst_iterator_free (iter);
1091 }
1092
1093 static void
1094 gst_validate_pad_monitor_otherpad_clear_pending_fields (GstValidatePadMonitor *
1095     monitor)
1096 {
1097   GstIterator *iter;
1098   gboolean done;
1099   GstPad *otherpad;
1100   GstValidatePadMonitor *othermonitor;
1101
1102   iter =
1103       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1104       (monitor));
1105
1106   if (iter == NULL) {
1107     GST_DEBUG_OBJECT (monitor, "No internally linked pad");
1108
1109     return;
1110   }
1111
1112   done = FALSE;
1113   while (!done) {
1114     GValue value = { 0, };
1115     switch (gst_iterator_next (iter, &value)) {
1116       case GST_ITERATOR_OK:
1117         otherpad = g_value_get_object (&value);
1118         othermonitor =
1119             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1120         if (othermonitor) {
1121           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1122           g_assert (othermonitor->pending_setcaps_fields != NULL);
1123           gst_structure_free (othermonitor->pending_setcaps_fields);
1124           othermonitor->pending_setcaps_fields =
1125               gst_structure_new_empty (PENDING_FIELDS);
1126           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1127         }
1128         g_value_reset (&value);
1129         break;
1130       case GST_ITERATOR_RESYNC:
1131         gst_iterator_resync (iter);
1132         break;
1133       case GST_ITERATOR_ERROR:
1134         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1135         done = TRUE;
1136         break;
1137       case GST_ITERATOR_DONE:
1138         done = TRUE;
1139         break;
1140     }
1141   }
1142   gst_iterator_free (iter);
1143 }
1144
1145 static void
1146 gst_validate_pad_monitor_add_expected_newsegment (GstValidatePadMonitor *
1147     monitor, GstEvent * event)
1148 {
1149   GstIterator *iter;
1150   gboolean done;
1151   GstPad *otherpad;
1152   GstValidatePadMonitor *othermonitor;
1153
1154   iter =
1155       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1156       (monitor));
1157
1158   if (iter == NULL) {
1159     GST_DEBUG_OBJECT (monitor, "No internally linked pad");
1160     return;
1161   }
1162
1163   done = FALSE;
1164   while (!done) {
1165     GValue value = { 0, };
1166     switch (gst_iterator_next (iter, &value)) {
1167       case GST_ITERATOR_OK:
1168         otherpad = g_value_get_object (&value);
1169         othermonitor =
1170             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1171         GST_VALIDATE_MONITOR_LOCK (othermonitor);
1172         gst_event_replace (&othermonitor->expected_segment, event);
1173         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1174         g_value_reset (&value);
1175         break;
1176       case GST_ITERATOR_RESYNC:
1177         gst_iterator_resync (iter);
1178         break;
1179       case GST_ITERATOR_ERROR:
1180         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1181         done = TRUE;
1182         break;
1183       case GST_ITERATOR_DONE:
1184         done = TRUE;
1185         break;
1186     }
1187   }
1188   gst_iterator_free (iter);
1189 }
1190
1191 static void
1192 gst_validate_pad_monitor_flush (GstValidatePadMonitor * pad_monitor)
1193 {
1194   pad_monitor->current_timestamp = GST_CLOCK_TIME_NONE;
1195   pad_monitor->current_duration = GST_CLOCK_TIME_NONE;
1196   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
1197   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
1198   pad_monitor->has_segment = FALSE;
1199   pad_monitor->is_eos = FALSE;
1200   pad_monitor->last_flow_return = GST_FLOW_OK;
1201   gst_caps_replace (&pad_monitor->last_caps, NULL);
1202   pad_monitor->caps_is_audio = pad_monitor->caps_is_video =
1203       pad_monitor->caps_is_raw = FALSE;
1204
1205   g_list_free_full (pad_monitor->expired_events,
1206       (GDestroyNotify) gst_event_unref);
1207   pad_monitor->expired_events = NULL;
1208
1209   if (pad_monitor->serialized_events->len)
1210     g_ptr_array_remove_range (pad_monitor->serialized_events, 0,
1211         pad_monitor->serialized_events->len);
1212 }
1213
1214 /* common checks for both sink and src event functions */
1215 static void
1216 gst_validate_pad_monitor_common_event_check (GstValidatePadMonitor *
1217     pad_monitor, GstEvent * event)
1218 {
1219   guint32 seqnum = gst_event_get_seqnum (event);
1220
1221   switch (GST_EVENT_TYPE (event)) {
1222     case GST_EVENT_FLUSH_START:
1223     {
1224       if (pad_monitor->pending_flush_start_seqnum) {
1225         if (seqnum == pad_monitor->pending_flush_start_seqnum) {
1226           pad_monitor->pending_flush_start_seqnum = 0;
1227         } else {
1228           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1229               "The expected flush-start seqnum should be the same as the "
1230               "one from the event that caused it (probably a seek). Got: %u."
1231               " Expected: %u", seqnum, pad_monitor->pending_flush_start_seqnum);
1232         }
1233       }
1234
1235       if (pad_monitor->pending_flush_stop) {
1236         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_START_UNEXPECTED,
1237             "Received flush-start from " " when flush-stop was expected");
1238       }
1239       pad_monitor->pending_flush_stop = TRUE;
1240     }
1241       break;
1242     case GST_EVENT_FLUSH_STOP:
1243     {
1244       if (pad_monitor->pending_flush_stop_seqnum) {
1245         if (seqnum == pad_monitor->pending_flush_stop_seqnum) {
1246           pad_monitor->pending_flush_stop_seqnum = 0;
1247         } else {
1248           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1249               "The expected flush-stop seqnum should be the same as the "
1250               "one from the event that caused it (probably a seek). Got: %u."
1251               " Expected: %u", seqnum, pad_monitor->pending_flush_stop_seqnum);
1252         }
1253       }
1254
1255       if (!pad_monitor->pending_flush_stop) {
1256         gchar *event_str = _get_event_string (event);
1257
1258         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_STOP_UNEXPECTED,
1259             "Unexpected flush-stop %s", event_str);
1260         g_free (event_str);
1261       }
1262       pad_monitor->pending_flush_stop = FALSE;
1263
1264       /* cleanup our data */
1265       gst_validate_pad_monitor_flush (pad_monitor);
1266     }
1267       break;
1268     default:
1269       break;
1270   }
1271 }
1272
1273 static gboolean
1274 gst_validate_pad_monitor_downstream_event_check (GstValidatePadMonitor *
1275     pad_monitor, GstObject * parent, GstEvent * event,
1276     GstPadEventFunction handler)
1277 {
1278   gboolean ret = TRUE;
1279   const GstSegment *segment;
1280   guint32 seqnum = gst_event_get_seqnum (event);
1281   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1282
1283   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1284
1285   /* pre checks */
1286   switch (GST_EVENT_TYPE (event)) {
1287     case GST_EVENT_SEGMENT:
1288       /* parse segment data to be used if event is handled */
1289       gst_event_parse_segment (event, &segment);
1290
1291       GST_DEBUG_OBJECT (pad_monitor->pad, "Got segment %" GST_SEGMENT_FORMAT,
1292           segment);
1293
1294       if (pad_monitor->pending_newsegment_seqnum) {
1295         if (pad_monitor->pending_newsegment_seqnum == seqnum) {
1296           pad_monitor->pending_newsegment_seqnum = 0;
1297         } else {
1298           /* TODO is this an error? could be a segment from the start
1299            * received just before the seek segment */
1300         }
1301       }
1302
1303       /* got a segment, no need for EOS now */
1304       pad_monitor->pending_eos_seqnum = 0;
1305
1306       if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1307         gst_validate_pad_monitor_add_expected_newsegment (pad_monitor, event);
1308       } else {
1309         /* check if this segment is the expected one */
1310         if (pad_monitor->expected_segment) {
1311           const GstSegment *exp_segment;
1312
1313           if (pad_monitor->expected_segment != event) {
1314             gst_event_parse_segment (pad_monitor->expected_segment,
1315                 &exp_segment);
1316             if (segment->format == exp_segment->format) {
1317               if ((exp_segment->rate * exp_segment->applied_rate !=
1318                       segment->rate * segment->applied_rate)
1319                   || exp_segment->start != segment->start
1320                   || exp_segment->stop != segment->stop
1321                   || exp_segment->position != segment->position) {
1322                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1323                     "Expected segment didn't match received segment event");
1324               }
1325             }
1326           }
1327           gst_event_replace (&pad_monitor->expected_segment, NULL);
1328         }
1329       }
1330       break;
1331     case GST_EVENT_CAPS:{
1332       GstCaps *caps;
1333
1334       gst_event_parse_caps (event, &caps);
1335       gst_validate_pad_monitor_setcaps_pre (pad_monitor, caps);
1336       break;
1337     }
1338     case GST_EVENT_EOS:
1339       pad_monitor->is_eos = TRUE;
1340       if (pad_monitor->pending_eos_seqnum &&
1341           pad_monitor->pending_eos_seqnum != seqnum) {
1342         GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1343             "The expected EOS seqnum should be the same as the "
1344             "one from the seek that caused it. Got: %u."
1345             " Expected: %u", seqnum, pad_monitor->pending_eos_seqnum);
1346       }
1347       /*
1348        * TODO add end of stream checks for
1349        *  - events not pushed
1350        *  - buffer data not pushed
1351        *  - pending events not received
1352        */
1353       break;
1354
1355       /* both flushes are handled by the common event function */
1356     case GST_EVENT_FLUSH_START:
1357     case GST_EVENT_FLUSH_STOP:
1358     case GST_EVENT_TAG:
1359     case GST_EVENT_SINK_MESSAGE:
1360     default:
1361       break;
1362   }
1363
1364   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1365   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1366   gst_validate_pad_monitor_event_overrides (pad_monitor, event);
1367   if (handler) {
1368     gst_event_ref (event);
1369     ret = pad_monitor->event_func (pad, parent, event);
1370   }
1371   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1372   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1373
1374   /* post checks */
1375   switch (GST_EVENT_TYPE (event)) {
1376     case GST_EVENT_SEGMENT:
1377       if (ret) {
1378         if (!pad_monitor->has_segment
1379             && pad_monitor->segment.format != segment->format) {
1380           gst_segment_init (&pad_monitor->segment, segment->format);
1381         }
1382         gst_segment_copy_into (segment, &pad_monitor->segment);
1383         pad_monitor->has_segment = TRUE;
1384       }
1385       break;
1386     case GST_EVENT_CAPS:{
1387       GstCaps *caps;
1388
1389       gst_event_parse_caps (event, &caps);
1390       gst_validate_pad_monitor_setcaps_post (pad_monitor, caps, ret);
1391       break;
1392     }
1393     case GST_EVENT_FLUSH_START:
1394     case GST_EVENT_FLUSH_STOP:
1395     case GST_EVENT_EOS:
1396     case GST_EVENT_TAG:
1397     case GST_EVENT_SINK_MESSAGE:
1398     default:
1399       break;
1400   }
1401
1402   if (handler)
1403     gst_event_unref (event);
1404   return ret;
1405 }
1406
1407 static gboolean
1408 gst_validate_pad_monitor_src_event_check (GstValidatePadMonitor * pad_monitor,
1409     GstObject * parent, GstEvent * event, GstPadEventFunction handler)
1410 {
1411   gboolean ret = TRUE;
1412   gdouble rate;
1413   GstFormat format;
1414   gint64 start, stop;
1415   GstSeekFlags seek_flags;
1416   GstSeekType start_type, stop_type;
1417   guint32 seqnum = gst_event_get_seqnum (event);
1418   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1419
1420   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1421
1422   /* pre checks */
1423   switch (GST_EVENT_TYPE (event)) {
1424     case GST_EVENT_SEEK:
1425     {
1426       gst_event_parse_seek (event, &rate, &format, &seek_flags, &start_type,
1427           &start, &stop_type, &stop);
1428       /* upstream seek - store the seek event seqnum to check
1429        * flushes and newsegments share the same */
1430
1431       /* TODO we might need to use a list as multiple seeks can be sent
1432        * before the flushes arrive here */
1433       if (seek_flags & GST_SEEK_FLAG_FLUSH) {
1434         pad_monitor->pending_flush_start_seqnum = seqnum;
1435         pad_monitor->pending_flush_stop_seqnum = seqnum;
1436       }
1437       pad_monitor->pending_newsegment_seqnum = seqnum;
1438       pad_monitor->pending_eos_seqnum = seqnum;
1439     }
1440       break;
1441       /* both flushes are handled by the common event handling function */
1442     case GST_EVENT_FLUSH_START:
1443     case GST_EVENT_FLUSH_STOP:
1444     case GST_EVENT_NAVIGATION:
1445     case GST_EVENT_LATENCY:
1446     case GST_EVENT_STEP:
1447     case GST_EVENT_QOS:
1448     default:
1449       break;
1450   }
1451
1452   if (handler) {
1453     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1454     gst_event_ref (event);
1455     ret = pad_monitor->event_func (pad, parent, event);
1456     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1457   }
1458
1459   /* post checks */
1460   switch (GST_EVENT_TYPE (event)) {
1461     case GST_EVENT_FLUSH_START:
1462     case GST_EVENT_FLUSH_STOP:
1463     case GST_EVENT_QOS:
1464     case GST_EVENT_SEEK:
1465     {
1466       if (ret == FALSE) {
1467         /* do not expect any of these events anymore */
1468         pad_monitor->pending_flush_start_seqnum = 0;
1469         pad_monitor->pending_flush_stop_seqnum = 0;
1470         pad_monitor->pending_newsegment_seqnum = 0;
1471         pad_monitor->pending_eos_seqnum = 0;
1472       }
1473     }
1474       break;
1475     case GST_EVENT_NAVIGATION:
1476     case GST_EVENT_LATENCY:
1477     case GST_EVENT_STEP:
1478     default:
1479       break;
1480   }
1481
1482   if (handler)
1483     gst_event_unref (event);
1484   return ret;
1485 }
1486
1487 static GstFlowReturn
1488 gst_validate_pad_monitor_chain_func (GstPad * pad, GstObject * parent,
1489     GstBuffer * buffer)
1490 {
1491   GstValidatePadMonitor *pad_monitor =
1492       g_object_get_data ((GObject *) pad, "validate-monitor");
1493   GstFlowReturn ret;
1494
1495   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1496   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1497
1498   gst_validate_pad_monitor_check_first_buffer (pad_monitor, buffer);
1499   gst_validate_pad_monitor_update_buffer_data (pad_monitor, buffer);
1500   gst_validate_pad_monitor_check_eos (pad_monitor, buffer);
1501
1502   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1503   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1504
1505   gst_validate_pad_monitor_buffer_overrides (pad_monitor, buffer);
1506
1507   ret = pad_monitor->chain_func (pad, parent, buffer);
1508
1509   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1510   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1511
1512   pad_monitor->last_flow_return = ret;
1513   if (ret == GST_FLOW_EOS) {
1514     pad_monitor->is_eos = ret;
1515   }
1516   if (PAD_PARENT_IS_DEMUXER (pad_monitor))
1517     gst_validate_pad_monitor_check_aggregated_return (pad_monitor, ret);
1518
1519   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1520   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1521
1522   return ret;
1523 }
1524
1525 static gboolean
1526 gst_validate_pad_monitor_event_is_tracked (GstValidatePadMonitor * monitor,
1527     GstEvent * event)
1528 {
1529   if (!GST_EVENT_IS_SERIALIZED (event)) {
1530     return FALSE;
1531   }
1532
1533   /* we don't track Tag events because they mutate too much and it is hard
1534    * to match a tag event pushed on a source pad with the one that was received
1535    * on a sink pad.
1536    * One idea would be to use seqnum, but it seems that it is undefined whether
1537    * seqnums should be maintained in tag events that are created from others
1538    * up to today. (2013-08-29)
1539    */
1540   if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
1541     return FALSE;
1542
1543   return TRUE;
1544 }
1545
1546 static gboolean
1547 gst_validate_pad_monitor_sink_event_func (GstPad * pad, GstObject * parent,
1548     GstEvent * event)
1549 {
1550   GstValidatePadMonitor *pad_monitor =
1551       g_object_get_data ((GObject *) pad, "validate-monitor");
1552   gboolean ret;
1553
1554   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1555   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1556
1557   if (gst_validate_pad_monitor_event_is_tracked (pad_monitor, event)) {
1558     GstClockTime last_ts = GST_CLOCK_TIME_NONE;
1559     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_timestamp)) {
1560       last_ts = pad_monitor->current_timestamp;
1561       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_duration)) {
1562         last_ts += pad_monitor->current_duration;
1563       }
1564     }
1565     gst_validate_pad_monitor_otherpad_add_pending_serialized_event (pad_monitor,
1566         event, last_ts);
1567   }
1568
1569   ret =
1570       gst_validate_pad_monitor_downstream_event_check (pad_monitor, parent,
1571       event, pad_monitor->event_func);
1572
1573   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1574   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1575   return ret;
1576 }
1577
1578 static gboolean
1579 gst_validate_pad_monitor_src_event_func (GstPad * pad, GstObject * parent,
1580     GstEvent * event)
1581 {
1582   GstValidatePadMonitor *pad_monitor =
1583       g_object_get_data ((GObject *) pad, "validate-monitor");
1584   gboolean ret;
1585
1586   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1587   ret = gst_validate_pad_monitor_src_event_check (pad_monitor, parent, event,
1588       pad_monitor->event_func);
1589   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1590   return ret;
1591 }
1592
1593 static gboolean
1594 gst_validate_pad_monitor_query_func (GstPad * pad, GstObject * parent,
1595     GstQuery * query)
1596 {
1597   GstValidatePadMonitor *pad_monitor =
1598       g_object_get_data ((GObject *) pad, "validate-monitor");
1599   gboolean ret;
1600
1601   gst_validate_pad_monitor_query_overrides (pad_monitor, query);
1602
1603   ret = pad_monitor->query_func (pad, parent, query);
1604
1605   if (ret) {
1606     switch (GST_QUERY_TYPE (query)) {
1607       case GST_QUERY_CAPS:{
1608         GstCaps *res;
1609         /* We shouldn't need to lock the parent as this doesn't modify
1610          * other monitors, just does some peer_pad_caps */
1611         GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1612
1613         gst_query_parse_caps_result (query, &res);
1614         if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1615           gst_validate_pad_monitor_check_caps_fields_proxied (pad_monitor, res);
1616         }
1617         GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1618         break;
1619       }
1620       default:
1621         break;
1622     }
1623   }
1624
1625   return ret;
1626 }
1627
1628 static gboolean
1629 gst_validate_pad_monitor_activatemode_func (GstPad * pad, GstObject * parent,
1630     GstPadMode mode, gboolean active)
1631 {
1632   GstValidatePadMonitor *pad_monitor =
1633       g_object_get_data ((GObject *) pad, "validate-monitor");
1634   gboolean ret = TRUE;
1635
1636   /* TODO add overrides for activate func */
1637
1638   if (pad_monitor->activatemode_func)
1639     ret = pad_monitor->activatemode_func (pad, parent, mode, active);
1640   if (ret && active == FALSE) {
1641     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1642     gst_validate_pad_monitor_flush (pad_monitor);
1643     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1644   }
1645
1646   return ret;
1647 }
1648
1649 static gboolean
1650 gst_validate_pad_get_range_func (GstPad * pad, GstObject * parent,
1651     guint64 offset, guint size, GstBuffer ** buffer)
1652 {
1653   GstValidatePadMonitor *pad_monitor =
1654       g_object_get_data ((GObject *) pad, "validate-monitor");
1655   gboolean ret;
1656   ret = pad_monitor->getrange_func (pad, parent, offset, size, buffer);
1657   return ret;
1658 }
1659
1660 static gboolean
1661 gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
1662     gpointer udata)
1663 {
1664   GstValidatePadMonitor *monitor = udata;
1665
1666   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1667   GST_VALIDATE_MONITOR_LOCK (monitor);
1668
1669   gst_validate_pad_monitor_check_first_buffer (monitor, buffer);
1670   gst_validate_pad_monitor_update_buffer_data (monitor, buffer);
1671   gst_validate_pad_monitor_check_eos (monitor, buffer);
1672
1673   if (PAD_PARENT_IS_DECODER (monitor) || PAD_PARENT_IS_ENCODER (monitor)) {
1674     GstClockTime tolerance = 0;
1675
1676     if (monitor->caps_is_audio)
1677       tolerance = AUDIO_TIMESTAMP_TOLERANCE;
1678
1679     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range (monitor,
1680         buffer, tolerance);
1681   }
1682
1683   gst_validate_pad_monitor_check_late_serialized_events (monitor,
1684       GST_BUFFER_TIMESTAMP (buffer));
1685
1686   /* a GstValidatePadMonitor parent must be a GstValidateElementMonitor */
1687   if (PAD_PARENT_IS_DECODER (monitor)) {
1688
1689     /* should not push out of segment data */
1690     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)) &&
1691         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)) &&
1692         ((!gst_segment_clip (&monitor->segment, monitor->segment.format,
1693                     GST_BUFFER_TIMESTAMP (buffer),
1694                     GST_BUFFER_TIMESTAMP (buffer) +
1695                     GST_BUFFER_DURATION (buffer), NULL, NULL)) ||
1696             /* In the case of raw data, buffers should be strictly contained inside the
1697              * segment */
1698             (monitor->caps_is_raw &&
1699                 GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer) <
1700                 monitor->segment.start))
1701         ) {
1702       /* TODO is this a timestamp issue? */
1703       GST_VALIDATE_REPORT (monitor, BUFFER_IS_OUT_OF_SEGMENT,
1704           "buffer is out of segment and shouldn't be pushed. Timestamp: %"
1705           GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT ". Range: %"
1706           GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1707           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1708           GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
1709           GST_TIME_ARGS (monitor->segment.start),
1710           GST_TIME_ARGS (monitor->segment.stop));
1711     }
1712   }
1713
1714   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1715   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1716   gst_validate_pad_monitor_buffer_probe_overrides (monitor, buffer);
1717   return TRUE;
1718 }
1719
1720 static gboolean
1721 gst_validate_pad_monitor_event_probe (GstPad * pad, GstEvent * event,
1722     gpointer udata)
1723 {
1724   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (udata);
1725   gboolean ret;
1726
1727   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1728   GST_VALIDATE_MONITOR_LOCK (monitor);
1729
1730   GST_DEBUG_OBJECT (pad, "event %p %s", event, GST_EVENT_TYPE_NAME (event));
1731
1732   if (GST_EVENT_IS_SERIALIZED (event)) {
1733     gint i;
1734
1735     /* Detect if events the element received are being forwarded in the same order
1736      *
1737      * Several scenarios:
1738      * 1) The element pushes the event as-is
1739      * 2) The element consumes the event and does not forward it
1740      * 3) The element consumes the event and creates another one instead
1741      * 4) The element pushes other serialized event before pushing out the
1742      *    one it received
1743      *
1744      * For each pad we have two lists to track serialized events:
1745      *  1) We received on input and expect to see (serialized_events)
1746      *  2) We received on input but don't expect to see (expired_events)
1747      *
1748      * To detect events that are pushed in a different order from the one they were
1749      * received in we check that:
1750      *
1751      * For each event being outputted:
1752      *   If it is in the expired_events list:
1753      *     RAISE WARNING
1754      *   If it is in the serialized_events list:
1755      *     If there are other events that were received before:
1756      *        Put those events on the expired_events list
1757      *     Remove that event and any previous ones from the serialized_events list
1758      *
1759      * Clear expired events list when flushing or on pad deactivation
1760      *
1761      */
1762
1763     if (g_list_find (monitor->expired_events, event)) {
1764       gchar *event_str = _get_event_string (event);
1765       /* If it's the expired events, we've failed */
1766       GST_WARNING_OBJECT (pad, "Did not expect event %p %s", event,
1767           GST_EVENT_TYPE_NAME (event));
1768       GST_VALIDATE_REPORT (monitor, EVENT_SERIALIZED_OUT_OF_ORDER,
1769           "Serialized event was pushed out of order: %s", event_str);
1770
1771       g_free (event_str);
1772       monitor->expired_events = g_list_remove (monitor->expired_events, event);
1773       gst_event_unref (event);  /* remove the ref that was on the list */
1774     } else if (monitor->serialized_events->len) {
1775       for (i = 0; i < monitor->serialized_events->len; i++) {
1776         SerializedEventData *next_event =
1777             g_ptr_array_index (monitor->serialized_events, i);
1778         GST_DEBUG_OBJECT (pad, "Checking against stored event #%d: %p %s", i,
1779             next_event->event, GST_EVENT_TYPE_NAME (next_event->event));
1780
1781         if (event == next_event->event
1782             || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1783           /* We have found our event */
1784           GST_DEBUG_OBJECT (pad, "Found matching event");
1785
1786           while (monitor->serialized_events->len > i
1787               && GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1788             /* Swallow all expected events of the same type */
1789             g_ptr_array_remove_index (monitor->serialized_events, i);
1790             next_event = g_ptr_array_index (monitor->serialized_events, i);
1791           }
1792
1793           /* Move all previous events to expired events */
1794           if (G_UNLIKELY (i > 0)) {
1795             GST_DEBUG_OBJECT (pad,
1796                 "Moving previous expected events to expired list");
1797             while (i--) {
1798               next_event = g_ptr_array_index (monitor->serialized_events, 0);
1799               monitor->expired_events =
1800                   g_list_append (monitor->expired_events,
1801                   gst_event_ref (next_event->event));
1802               g_ptr_array_remove_index (monitor->serialized_events, 0);
1803             }
1804           }
1805           debug_pending_event (pad, monitor->serialized_events);
1806           break;
1807         }
1808       }
1809     }
1810   }
1811
1812   /* This so far is just like an event that is flowing downstream,
1813    * so we do the same checks as a sinkpad event handler */
1814   ret =
1815       gst_validate_pad_monitor_downstream_event_check (monitor, NULL, event,
1816       NULL);
1817   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1818   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1819
1820   return ret;
1821 }
1822
1823 static GstPadProbeReturn
1824 gst_validate_pad_monitor_pad_probe (GstPad * pad, GstPadProbeInfo * info,
1825     gpointer udata)
1826 {
1827   if (info->type & GST_PAD_PROBE_TYPE_BUFFER)
1828     gst_validate_pad_monitor_buffer_probe (pad, info->data, udata);
1829   else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)
1830     gst_validate_pad_monitor_event_probe (pad, info->data, udata);
1831
1832   return GST_PAD_PROBE_OK;
1833 }
1834
1835 static void
1836 gst_validate_pad_monitor_update_caps_info (GstValidatePadMonitor * pad_monitor,
1837     GstCaps * caps)
1838 {
1839   GstStructure *structure;
1840
1841   g_return_if_fail (gst_caps_is_fixed (caps));
1842
1843   pad_monitor->caps_is_audio = FALSE;
1844   pad_monitor->caps_is_video = FALSE;
1845
1846   structure = gst_caps_get_structure (caps, 0);
1847   if (g_str_has_prefix (gst_structure_get_name (structure), "audio/")) {
1848     pad_monitor->caps_is_audio = TRUE;
1849   } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/")) {
1850     pad_monitor->caps_is_video = TRUE;
1851   }
1852
1853   if (g_str_has_prefix (gst_structure_get_name (structure), "audio/x-raw") ||
1854       g_str_has_prefix (gst_structure_get_name (structure), "video/x-raw")) {
1855     pad_monitor->caps_is_raw = TRUE;
1856   } else {
1857     pad_monitor->caps_is_raw = FALSE;
1858   }
1859 }
1860
1861 static void
1862 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
1863     GstCaps * caps)
1864 {
1865   GstStructure *structure;
1866
1867   /* Check if caps are identical to last caps and complain if so
1868    * Only checked for sink pads as src pads might push the same caps
1869    * multiple times during unlinked/autoplugging scenarios */
1870   if (GST_PAD_IS_SINK (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)) &&
1871       pad_monitor->last_caps
1872       && gst_caps_is_equal (caps, pad_monitor->last_caps)) {
1873     gchar *caps_str = gst_caps_to_string (caps);
1874
1875     GST_VALIDATE_REPORT (pad_monitor, EVENT_CAPS_DUPLICATE, "%s", caps_str);
1876     g_free (caps_str);
1877
1878   }
1879
1880   gst_validate_pad_monitor_check_caps_complete (pad_monitor, caps);
1881
1882   if (caps) {
1883     structure = gst_caps_get_structure (caps, 0);
1884     if (gst_structure_n_fields (pad_monitor->pending_setcaps_fields)) {
1885       gint i;
1886       for (i = 0;
1887           i < gst_structure_n_fields (pad_monitor->pending_setcaps_fields);
1888           i++) {
1889         const gchar *name =
1890             gst_structure_nth_field_name (pad_monitor->pending_setcaps_fields,
1891             i);
1892         const GValue *v = gst_structure_get_value (structure, name);
1893         const GValue *otherv =
1894             gst_structure_get_value (pad_monitor->pending_setcaps_fields, name);
1895
1896         if (v == NULL) {
1897           gchar *caps_str = gst_caps_to_string (caps);
1898
1899           GST_VALIDATE_REPORT (pad_monitor, CAPS_EXPECTED_FIELD_NOT_FOUND,
1900               "Field %s is missing from setcaps caps '%s'", name, caps_str);
1901           g_free (caps_str);
1902         } else if (gst_value_compare (v, otherv) != GST_VALUE_EQUAL) {
1903           gchar *caps_str = gst_caps_to_string (caps),
1904               *pending_setcaps_fields_str =
1905               gst_structure_to_string (pad_monitor->pending_setcaps_fields);
1906
1907
1908           GST_VALIDATE_REPORT (pad_monitor, CAPS_FIELD_UNEXPECTED_VALUE,
1909               "Field %s from setcaps caps '%s' is different "
1910               "from expected value in caps '%s'", name, caps_str,
1911               pending_setcaps_fields_str);
1912
1913           g_free (pending_setcaps_fields_str);
1914           g_free (caps_str);
1915         }
1916       }
1917     }
1918
1919     if (gst_validate_pad_monitor_pad_should_proxy_othercaps (pad_monitor)) {
1920       if (_structure_is_video (structure)) {
1921         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1922             structure, "width");
1923         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1924             structure, "height");
1925         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1926             structure, "framerate");
1927         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1928             structure, "pixel-aspect-ratio");
1929       } else if (_structure_is_audio (structure)) {
1930         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1931             structure, "rate");
1932         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1933             structure, "channels");
1934       }
1935     }
1936   }
1937
1938   gst_structure_free (pad_monitor->pending_setcaps_fields);
1939   pad_monitor->pending_setcaps_fields =
1940       gst_structure_new_empty (PENDING_FIELDS);
1941
1942   gst_validate_pad_monitor_setcaps_overrides (pad_monitor, caps);
1943 }
1944
1945 static void
1946 gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor * pad_monitor,
1947     GstCaps * caps, gboolean ret)
1948 {
1949   if (!ret)
1950     gst_validate_pad_monitor_otherpad_clear_pending_fields (pad_monitor);
1951   else {
1952     if (pad_monitor->last_caps) {
1953       gst_caps_unref (pad_monitor->last_caps);
1954     }
1955     pad_monitor->last_caps = gst_caps_ref (caps);
1956     gst_validate_pad_monitor_update_caps_info (pad_monitor, caps);
1957   }
1958 }
1959
1960 static gboolean
1961 gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
1962 {
1963   GstValidatePadMonitor *pad_monitor = GST_VALIDATE_PAD_MONITOR_CAST (monitor);
1964   GstPad *pad;
1965   if (!GST_IS_PAD (GST_VALIDATE_MONITOR_GET_OBJECT (monitor))) {
1966     GST_WARNING_OBJECT (monitor, "Trying to create pad monitor with other "
1967         "type of object");
1968     return FALSE;
1969   }
1970
1971   pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1972
1973   if (g_object_get_data ((GObject *) pad, "validate-monitor")) {
1974     GST_WARNING_OBJECT (pad_monitor,
1975         "Pad already has a validate-monitor associated");
1976     return FALSE;
1977   }
1978
1979   g_object_set_data ((GObject *) pad, "validate-monitor", pad_monitor);
1980
1981   pad_monitor->pad = pad;
1982
1983   pad_monitor->event_func = GST_PAD_EVENTFUNC (pad);
1984   pad_monitor->query_func = GST_PAD_QUERYFUNC (pad);
1985   pad_monitor->activatemode_func = GST_PAD_ACTIVATEMODEFUNC (pad);
1986   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1987
1988     pad_monitor->chain_func = GST_PAD_CHAINFUNC (pad);
1989     if (pad_monitor->chain_func)
1990       gst_pad_set_chain_function (pad, gst_validate_pad_monitor_chain_func);
1991
1992     gst_pad_set_event_function (pad, gst_validate_pad_monitor_sink_event_func);
1993   } else {
1994     pad_monitor->getrange_func = GST_PAD_GETRANGEFUNC (pad);
1995     if (pad_monitor->getrange_func)
1996       gst_pad_set_getrange_function (pad, gst_validate_pad_get_range_func);
1997
1998     gst_pad_set_event_function (pad, gst_validate_pad_monitor_src_event_func);
1999
2000     /* add buffer/event probes */
2001     pad_monitor->pad_probe_id =
2002         gst_pad_add_probe (pad,
2003         GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
2004         GST_PAD_PROBE_TYPE_EVENT_FLUSH,
2005         (GstPadProbeCallback) gst_validate_pad_monitor_pad_probe, pad_monitor,
2006         NULL);
2007   }
2008   gst_pad_set_query_function (pad, gst_validate_pad_monitor_query_func);
2009   gst_pad_set_activatemode_function (pad,
2010       gst_validate_pad_monitor_activatemode_func);
2011
2012   gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (monitor),
2013       g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad)));
2014
2015   if (G_UNLIKELY (GST_PAD_PARENT (pad) == NULL))
2016     GST_FIXME ("Saw a pad not belonging to any object");
2017
2018   return TRUE;
2019 }