pad-monitor: check that no buffers are pushed after a pad is EOS
[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     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
827       gint64 running_time = gst_segment_to_running_time (&pad_monitor->segment,
828           pad_monitor->segment.format, GST_BUFFER_TIMESTAMP (buffer));
829       if (running_time != 0) {
830         GST_VALIDATE_REPORT (pad_monitor, FIRST_BUFFER_RUNNING_TIME_IS_NOT_ZERO,
831             "First buffer running time is not 0, it is: %" GST_TIME_FORMAT,
832             GST_TIME_ARGS (running_time));
833       }
834     }
835   }
836 }
837
838 static void
839 gst_validate_pad_monitor_check_eos (GstValidatePadMonitor *
840     pad_monitor, GstBuffer * buffer)
841 {
842   if (G_UNLIKELY (pad_monitor->is_eos)) {
843     GST_VALIDATE_REPORT (pad_monitor, BUFFER_AFTER_EOS,
844           "Received buffer %" GST_PTR_FORMAT " after EOS", buffer);
845   }
846 }
847
848 static void
849 gst_validate_pad_monitor_update_buffer_data (GstValidatePadMonitor *
850     pad_monitor, GstBuffer * buffer)
851 {
852   pad_monitor->current_timestamp = GST_BUFFER_TIMESTAMP (buffer);
853   pad_monitor->current_duration = GST_BUFFER_DURATION (buffer);
854   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
855     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_start)) {
856       pad_monitor->timestamp_range_start =
857           MIN (pad_monitor->timestamp_range_start,
858           GST_BUFFER_TIMESTAMP (buffer));
859     } else {
860       pad_monitor->timestamp_range_start = GST_BUFFER_TIMESTAMP (buffer);
861     }
862
863     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
864       GstClockTime endts =
865           GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
866       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_end)) {
867         pad_monitor->timestamp_range_end =
868             MAX (pad_monitor->timestamp_range_end, endts);
869       } else {
870         pad_monitor->timestamp_range_end = endts;
871       }
872     }
873   }
874   GST_DEBUG_OBJECT (pad_monitor->pad, "Current stored range: %" GST_TIME_FORMAT
875       " - %" GST_TIME_FORMAT,
876       GST_TIME_ARGS (pad_monitor->timestamp_range_start),
877       GST_TIME_ARGS (pad_monitor->timestamp_range_end));
878 }
879
880 static GstFlowReturn
881 _combine_flows (GstFlowReturn ret1, GstFlowReturn ret2)
882 {
883   if (ret1 == ret2)
884     return ret1;
885   if (ret1 <= GST_FLOW_NOT_NEGOTIATED)
886     return ret1;
887   if (ret2 <= GST_FLOW_NOT_NEGOTIATED)
888     return ret2;
889   if (ret1 == GST_FLOW_FLUSHING || ret2 == GST_FLOW_FLUSHING)
890     return GST_FLOW_FLUSHING;
891   if (ret1 == GST_FLOW_OK || ret2 == GST_FLOW_OK)
892     return GST_FLOW_OK;
893   return ret2;
894 }
895
896 static void
897 gst_validate_pad_monitor_check_aggregated_return (GstValidatePadMonitor *
898     monitor, GstFlowReturn ret)
899 {
900   GstIterator *iter;
901   gboolean done;
902   GstPad *otherpad;
903   GstPad *peerpad;
904   GstValidatePadMonitor *othermonitor;
905   GstFlowReturn aggregated = GST_FLOW_NOT_LINKED;
906   gboolean found_a_pad = FALSE;
907   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
908
909   iter = gst_pad_iterate_internal_links (pad);
910   done = FALSE;
911   while (!done) {
912     GValue value = { 0, };
913     switch (gst_iterator_next (iter, &value)) {
914       case GST_ITERATOR_OK:
915         otherpad = g_value_get_object (&value);
916         peerpad = gst_pad_get_peer (otherpad);
917         if (peerpad) {
918           othermonitor =
919               g_object_get_data ((GObject *) peerpad, "validate-monitor");
920           if (othermonitor) {
921             found_a_pad = TRUE;
922             GST_VALIDATE_MONITOR_LOCK (othermonitor);
923             aggregated =
924                 _combine_flows (aggregated, othermonitor->last_flow_return);
925             GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
926           }
927
928           gst_object_unref (peerpad);
929         }
930         g_value_reset (&value);
931         break;
932       case GST_ITERATOR_RESYNC:
933         gst_iterator_resync (iter);
934         break;
935       case GST_ITERATOR_ERROR:
936         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
937         done = TRUE;
938         break;
939       case GST_ITERATOR_DONE:
940         done = TRUE;
941         break;
942     }
943   }
944   gst_iterator_free (iter);
945   if (!found_a_pad) {
946     /* no peer pad found, nothing to do */
947     return;
948   }
949   if (aggregated == GST_FLOW_OK || aggregated == GST_FLOW_EOS) {
950     /* those are acceptable situations */
951
952     if (GST_PAD_IS_FLUSHING (pad) && ret == GST_FLOW_FLUSHING) {
953       /* pad is flushing, always acceptable to return flushing */
954       return;
955     }
956
957     if (monitor->is_eos && ret == GST_FLOW_EOS) {
958       /* this element received eos and returned eos */
959       return;
960     }
961
962     if (PAD_PARENT_IS_DEMUXER (monitor) && ret == GST_FLOW_EOS) {
963       /* a demuxer can return EOS when the samples end */
964       return;
965     }
966   }
967
968   if (aggregated != ret) {
969     GST_VALIDATE_REPORT (monitor, WRONG_FLOW_RETURN,
970         "Wrong combined flow return %s(%d). Expected: %s(%d)",
971         gst_flow_get_name (ret), ret, gst_flow_get_name (aggregated),
972         aggregated);
973   }
974 }
975
976 static void
977     gst_validate_pad_monitor_otherpad_add_pending_serialized_event
978     (GstValidatePadMonitor * monitor, GstEvent * event, GstClockTime last_ts)
979 {
980   GstIterator *iter;
981   gboolean done;
982   GstPad *otherpad;
983   GstValidatePadMonitor *othermonitor;
984
985   if (!GST_EVENT_IS_SERIALIZED (event))
986     return;
987
988   iter =
989       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
990       (monitor));
991   if (iter == NULL) {
992     /* inputselector will return NULL if the sinkpad is not the active one .... */
993     GST_FIXME_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD
994         (monitor), "No iterator");
995     return;
996   }
997   done = FALSE;
998   while (!done) {
999     GValue value = { 0, };
1000     switch (gst_iterator_next (iter, &value)) {
1001       case GST_ITERATOR_OK:
1002         otherpad = g_value_get_object (&value);
1003         othermonitor =
1004             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1005         if (othermonitor) {
1006           SerializedEventData *data = g_slice_new0 (SerializedEventData);
1007           data->timestamp = last_ts;
1008           data->event = gst_event_ref (event);
1009           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1010           GST_DEBUG_OBJECT (monitor->pad, "Storing for pad %s:%s event %p %s",
1011               GST_DEBUG_PAD_NAME (otherpad), event,
1012               GST_EVENT_TYPE_NAME (event));
1013           g_ptr_array_add (othermonitor->serialized_events, data);
1014           debug_pending_event (otherpad, othermonitor->serialized_events);
1015           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1016         }
1017         g_value_reset (&value);
1018         break;
1019       case GST_ITERATOR_RESYNC:
1020         gst_iterator_resync (iter);
1021         break;
1022       case GST_ITERATOR_ERROR:
1023         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1024         done = TRUE;
1025         break;
1026       case GST_ITERATOR_DONE:
1027         done = TRUE;
1028         break;
1029     }
1030   }
1031   gst_iterator_free (iter);
1032 }
1033
1034 static void
1035 gst_validate_pad_monitor_otherpad_add_pending_field (GstValidatePadMonitor *
1036     monitor, GstStructure * structure, const gchar * field)
1037 {
1038   GstIterator *iter;
1039   gboolean done;
1040   GstPad *otherpad;
1041   GstValidatePadMonitor *othermonitor;
1042   const GValue *v;
1043
1044   v = gst_structure_get_value (structure, field);
1045   if (v == NULL) {
1046     GST_DEBUG_OBJECT (monitor->pad, "Not adding pending field %s as it isn't "
1047         "present on structure %" GST_PTR_FORMAT, field, structure);
1048     return;
1049   }
1050
1051   iter =
1052       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1053       (monitor));
1054   done = FALSE;
1055   while (!done) {
1056     GValue value = { 0, };
1057     switch (gst_iterator_next (iter, &value)) {
1058       case GST_ITERATOR_OK:
1059         otherpad = g_value_get_object (&value);
1060         othermonitor =
1061             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1062         if (othermonitor) {
1063           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1064           g_assert (othermonitor->pending_setcaps_fields != NULL);
1065           gst_structure_set_value (othermonitor->pending_setcaps_fields,
1066               field, v);
1067           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1068         }
1069         g_value_reset (&value);
1070         break;
1071       case GST_ITERATOR_RESYNC:
1072         gst_iterator_resync (iter);
1073         break;
1074       case GST_ITERATOR_ERROR:
1075         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1076         done = TRUE;
1077         break;
1078       case GST_ITERATOR_DONE:
1079         done = TRUE;
1080         break;
1081     }
1082   }
1083   gst_iterator_free (iter);
1084 }
1085
1086 static void
1087 gst_validate_pad_monitor_otherpad_clear_pending_fields (GstValidatePadMonitor *
1088     monitor)
1089 {
1090   GstIterator *iter;
1091   gboolean done;
1092   GstPad *otherpad;
1093   GstValidatePadMonitor *othermonitor;
1094
1095   iter =
1096       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1097       (monitor));
1098   done = FALSE;
1099   while (!done) {
1100     GValue value = { 0, };
1101     switch (gst_iterator_next (iter, &value)) {
1102       case GST_ITERATOR_OK:
1103         otherpad = g_value_get_object (&value);
1104         othermonitor =
1105             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1106         if (othermonitor) {
1107           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1108           g_assert (othermonitor->pending_setcaps_fields != NULL);
1109           gst_structure_free (othermonitor->pending_setcaps_fields);
1110           othermonitor->pending_setcaps_fields =
1111               gst_structure_new_empty (PENDING_FIELDS);
1112           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1113         }
1114         g_value_reset (&value);
1115         break;
1116       case GST_ITERATOR_RESYNC:
1117         gst_iterator_resync (iter);
1118         break;
1119       case GST_ITERATOR_ERROR:
1120         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1121         done = TRUE;
1122         break;
1123       case GST_ITERATOR_DONE:
1124         done = TRUE;
1125         break;
1126     }
1127   }
1128   gst_iterator_free (iter);
1129 }
1130
1131 static void
1132 gst_validate_pad_monitor_add_expected_newsegment (GstValidatePadMonitor *
1133     monitor, GstEvent * event)
1134 {
1135   GstIterator *iter;
1136   gboolean done;
1137   GstPad *otherpad;
1138   GstValidatePadMonitor *othermonitor;
1139
1140   iter =
1141       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1142       (monitor));
1143   done = FALSE;
1144   while (!done) {
1145     GValue value = { 0, };
1146     switch (gst_iterator_next (iter, &value)) {
1147       case GST_ITERATOR_OK:
1148         otherpad = g_value_get_object (&value);
1149         othermonitor =
1150             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1151         GST_VALIDATE_MONITOR_LOCK (othermonitor);
1152         gst_event_replace (&othermonitor->expected_segment, event);
1153         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1154         g_value_reset (&value);
1155         break;
1156       case GST_ITERATOR_RESYNC:
1157         gst_iterator_resync (iter);
1158         break;
1159       case GST_ITERATOR_ERROR:
1160         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1161         done = TRUE;
1162         break;
1163       case GST_ITERATOR_DONE:
1164         done = TRUE;
1165         break;
1166     }
1167   }
1168   gst_iterator_free (iter);
1169 }
1170
1171 static void
1172 gst_validate_pad_monitor_flush (GstValidatePadMonitor * pad_monitor)
1173 {
1174   pad_monitor->current_timestamp = GST_CLOCK_TIME_NONE;
1175   pad_monitor->current_duration = GST_CLOCK_TIME_NONE;
1176   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
1177   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
1178   pad_monitor->has_segment = FALSE;
1179   pad_monitor->is_eos = FALSE;
1180   pad_monitor->last_flow_return = GST_FLOW_OK;
1181   gst_caps_replace (&pad_monitor->last_caps, NULL);
1182   pad_monitor->caps_is_audio = pad_monitor->caps_is_video = pad_monitor->caps_is_raw = FALSE;
1183
1184   g_list_free_full (pad_monitor->expired_events,
1185       (GDestroyNotify) gst_event_unref);
1186   pad_monitor->expired_events = NULL;
1187
1188   if (pad_monitor->serialized_events->len)
1189     g_ptr_array_remove_range (pad_monitor->serialized_events, 0,
1190         pad_monitor->serialized_events->len);
1191 }
1192
1193 /* common checks for both sink and src event functions */
1194 static void
1195 gst_validate_pad_monitor_common_event_check (GstValidatePadMonitor *
1196     pad_monitor, GstEvent * event)
1197 {
1198   guint32 seqnum = gst_event_get_seqnum (event);
1199
1200   switch (GST_EVENT_TYPE (event)) {
1201     case GST_EVENT_FLUSH_START:
1202     {
1203       if (pad_monitor->pending_flush_start_seqnum) {
1204         if (seqnum == pad_monitor->pending_flush_start_seqnum) {
1205           pad_monitor->pending_flush_start_seqnum = 0;
1206         } else {
1207           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1208               "The expected flush-start seqnum should be the same as the "
1209               "one from the event that caused it (probably a seek). Got: %u."
1210               " Expected: %u", seqnum, pad_monitor->pending_flush_start_seqnum);
1211         }
1212       }
1213
1214       if (pad_monitor->pending_flush_stop) {
1215         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_START_UNEXPECTED,
1216             "Received flush-start from " " when flush-stop was expected");
1217       }
1218       pad_monitor->pending_flush_stop = TRUE;
1219     }
1220       break;
1221     case GST_EVENT_FLUSH_STOP:
1222     {
1223       if (pad_monitor->pending_flush_stop_seqnum) {
1224         if (seqnum == pad_monitor->pending_flush_stop_seqnum) {
1225           pad_monitor->pending_flush_stop_seqnum = 0;
1226         } else {
1227           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1228               "The expected flush-stop seqnum should be the same as the "
1229               "one from the event that caused it (probably a seek). Got: %u."
1230               " Expected: %u", seqnum, pad_monitor->pending_flush_stop_seqnum);
1231         }
1232       }
1233
1234       if (!pad_monitor->pending_flush_stop) {
1235         gchar *event_str = _get_event_string (event);
1236
1237         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_STOP_UNEXPECTED,
1238             "Unexpected flush-stop %s", event_str);
1239         g_free (event_str);
1240       }
1241       pad_monitor->pending_flush_stop = FALSE;
1242
1243       /* cleanup our data */
1244       gst_validate_pad_monitor_flush (pad_monitor);
1245     }
1246       break;
1247     default:
1248       break;
1249   }
1250 }
1251
1252 static gboolean
1253 gst_validate_pad_monitor_downstream_event_check (GstValidatePadMonitor *
1254     pad_monitor, GstObject * parent, GstEvent * event,
1255     GstPadEventFunction handler)
1256 {
1257   gboolean ret = TRUE;
1258   const GstSegment *segment;
1259   guint32 seqnum = gst_event_get_seqnum (event);
1260   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1261
1262   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1263
1264   /* pre checks */
1265   switch (GST_EVENT_TYPE (event)) {
1266     case GST_EVENT_SEGMENT:
1267       /* parse segment data to be used if event is handled */
1268       gst_event_parse_segment (event, &segment);
1269
1270       if (pad_monitor->pending_newsegment_seqnum) {
1271         if (pad_monitor->pending_newsegment_seqnum == seqnum) {
1272           pad_monitor->pending_newsegment_seqnum = 0;
1273         } else {
1274           /* TODO is this an error? could be a segment from the start
1275            * received just before the seek segment */
1276         }
1277       }
1278
1279       /* got a segment, no need for EOS now */
1280       pad_monitor->pending_eos_seqnum = 0;
1281
1282       if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1283         gst_validate_pad_monitor_add_expected_newsegment (pad_monitor, event);
1284       } else {
1285         /* check if this segment is the expected one */
1286         if (pad_monitor->expected_segment) {
1287           const GstSegment *exp_segment;
1288
1289           if (pad_monitor->expected_segment != event) {
1290             gst_event_parse_segment (pad_monitor->expected_segment,
1291                 &exp_segment);
1292             if (segment->format == exp_segment->format) {
1293               if ((exp_segment->rate * exp_segment->applied_rate !=
1294                       segment->rate * segment->applied_rate)
1295                   || exp_segment->start != segment->start
1296                   || exp_segment->stop != segment->stop
1297                   || exp_segment->position != segment->position) {
1298                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1299                     "Expected segment didn't match received segment event");
1300               }
1301             }
1302           }
1303           gst_event_replace (&pad_monitor->expected_segment, NULL);
1304         }
1305       }
1306       break;
1307     case GST_EVENT_CAPS:{
1308       GstCaps *caps;
1309
1310       gst_event_parse_caps (event, &caps);
1311       gst_validate_pad_monitor_setcaps_pre (pad_monitor, caps);
1312       break;
1313     }
1314     case GST_EVENT_EOS:
1315       pad_monitor->is_eos = TRUE;
1316       if (pad_monitor->pending_eos_seqnum &&
1317           pad_monitor->pending_eos_seqnum != seqnum) {
1318         GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1319             "The expected EOS seqnum should be the same as the "
1320             "one from the seek that caused it. Got: %u."
1321             " Expected: %u", seqnum, pad_monitor->pending_eos_seqnum);
1322       }
1323       /*
1324        * TODO add end of stream checks for
1325        *  - events not pushed
1326        *  - buffer data not pushed
1327        *  - pending events not received
1328        */
1329       break;
1330
1331       /* both flushes are handled by the common event function */
1332     case GST_EVENT_FLUSH_START:
1333     case GST_EVENT_FLUSH_STOP:
1334     case GST_EVENT_TAG:
1335     case GST_EVENT_SINK_MESSAGE:
1336     default:
1337       break;
1338   }
1339
1340   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1341   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1342   gst_validate_pad_monitor_event_overrides (pad_monitor, event);
1343   if (handler) {
1344     gst_event_ref (event);
1345     ret = pad_monitor->event_func (pad, parent, event);
1346   }
1347   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1348   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1349
1350   /* post checks */
1351   switch (GST_EVENT_TYPE (event)) {
1352     case GST_EVENT_SEGMENT:
1353       if (ret) {
1354         if (!pad_monitor->has_segment
1355             && pad_monitor->segment.format != segment->format) {
1356           gst_segment_init (&pad_monitor->segment, segment->format);
1357         }
1358         gst_segment_copy_into (segment, &pad_monitor->segment);
1359         pad_monitor->has_segment = TRUE;
1360       }
1361       break;
1362     case GST_EVENT_CAPS:{
1363       GstCaps *caps;
1364
1365       gst_event_parse_caps (event, &caps);
1366       gst_validate_pad_monitor_setcaps_post (pad_monitor, caps, ret);
1367       break;
1368     }
1369     case GST_EVENT_FLUSH_START:
1370     case GST_EVENT_FLUSH_STOP:
1371     case GST_EVENT_EOS:
1372     case GST_EVENT_TAG:
1373     case GST_EVENT_SINK_MESSAGE:
1374     default:
1375       break;
1376   }
1377
1378   if (handler)
1379     gst_event_unref (event);
1380   return ret;
1381 }
1382
1383 static gboolean
1384 gst_validate_pad_monitor_src_event_check (GstValidatePadMonitor * pad_monitor,
1385     GstObject * parent, GstEvent * event, GstPadEventFunction handler)
1386 {
1387   gboolean ret = TRUE;
1388   gdouble rate;
1389   GstFormat format;
1390   gint64 start, stop;
1391   GstSeekFlags seek_flags;
1392   GstSeekType start_type, stop_type;
1393   guint32 seqnum = gst_event_get_seqnum (event);
1394   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1395
1396   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1397
1398   /* pre checks */
1399   switch (GST_EVENT_TYPE (event)) {
1400     case GST_EVENT_SEEK:
1401     {
1402       gst_event_parse_seek (event, &rate, &format, &seek_flags, &start_type,
1403           &start, &stop_type, &stop);
1404       /* upstream seek - store the seek event seqnum to check
1405        * flushes and newsegments share the same */
1406
1407       /* TODO we might need to use a list as multiple seeks can be sent
1408        * before the flushes arrive here */
1409       if (seek_flags & GST_SEEK_FLAG_FLUSH) {
1410         pad_monitor->pending_flush_start_seqnum = seqnum;
1411         pad_monitor->pending_flush_stop_seqnum = seqnum;
1412       }
1413       pad_monitor->pending_newsegment_seqnum = seqnum;
1414       pad_monitor->pending_eos_seqnum = seqnum;
1415     }
1416       break;
1417       /* both flushes are handled by the common event handling function */
1418     case GST_EVENT_FLUSH_START:
1419     case GST_EVENT_FLUSH_STOP:
1420     case GST_EVENT_NAVIGATION:
1421     case GST_EVENT_LATENCY:
1422     case GST_EVENT_STEP:
1423     case GST_EVENT_QOS:
1424     default:
1425       break;
1426   }
1427
1428   if (handler) {
1429     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1430     gst_event_ref (event);
1431     ret = pad_monitor->event_func (pad, parent, event);
1432     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1433   }
1434
1435   /* post checks */
1436   switch (GST_EVENT_TYPE (event)) {
1437     case GST_EVENT_FLUSH_START:
1438     case GST_EVENT_FLUSH_STOP:
1439     case GST_EVENT_QOS:
1440     case GST_EVENT_SEEK:
1441     {
1442       if (ret == FALSE) {
1443         /* do not expect any of these events anymore */
1444         pad_monitor->pending_flush_start_seqnum = 0;
1445         pad_monitor->pending_flush_stop_seqnum = 0;
1446         pad_monitor->pending_newsegment_seqnum = 0;
1447         pad_monitor->pending_eos_seqnum = 0;
1448       }
1449     }
1450       break;
1451     case GST_EVENT_NAVIGATION:
1452     case GST_EVENT_LATENCY:
1453     case GST_EVENT_STEP:
1454     default:
1455       break;
1456   }
1457
1458   if (handler)
1459     gst_event_unref (event);
1460   return ret;
1461 }
1462
1463 static GstFlowReturn
1464 gst_validate_pad_monitor_chain_func (GstPad * pad, GstObject * parent,
1465     GstBuffer * buffer)
1466 {
1467   GstValidatePadMonitor *pad_monitor =
1468       g_object_get_data ((GObject *) pad, "validate-monitor");
1469   GstFlowReturn ret;
1470
1471   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1472   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1473
1474   gst_validate_pad_monitor_check_first_buffer (pad_monitor, buffer);
1475   gst_validate_pad_monitor_update_buffer_data (pad_monitor, buffer);
1476   gst_validate_pad_monitor_check_eos (pad_monitor, buffer);
1477
1478   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1479   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1480
1481   gst_validate_pad_monitor_buffer_overrides (pad_monitor, buffer);
1482
1483   ret = pad_monitor->chain_func (pad, parent, buffer);
1484
1485   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1486   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1487
1488   pad_monitor->last_flow_return = ret;
1489   if (ret == GST_FLOW_EOS) {
1490     pad_monitor->is_eos = ret;
1491   }
1492   if (PAD_PARENT_IS_DEMUXER (pad_monitor))
1493     gst_validate_pad_monitor_check_aggregated_return (pad_monitor, ret);
1494
1495   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1496   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1497
1498   return ret;
1499 }
1500
1501 static gboolean
1502 gst_validate_pad_monitor_event_is_tracked (GstValidatePadMonitor * monitor,
1503     GstEvent * event)
1504 {
1505   if (!GST_EVENT_IS_SERIALIZED (event)) {
1506     return FALSE;
1507   }
1508
1509   /* we don't track Tag events because they mutate too much and it is hard
1510    * to match a tag event pushed on a source pad with the one that was received
1511    * on a sink pad.
1512    * One idea would be to use seqnum, but it seems that it is undefined whether
1513    * seqnums should be maintained in tag events that are created from others
1514    * up to today. (2013-08-29)
1515    */
1516   if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
1517     return FALSE;
1518
1519   return TRUE;
1520 }
1521
1522 static gboolean
1523 gst_validate_pad_monitor_sink_event_func (GstPad * pad, GstObject * parent,
1524     GstEvent * event)
1525 {
1526   GstValidatePadMonitor *pad_monitor =
1527       g_object_get_data ((GObject *) pad, "validate-monitor");
1528   gboolean ret;
1529
1530   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1531   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1532
1533   if (gst_validate_pad_monitor_event_is_tracked (pad_monitor, event)) {
1534     GstClockTime last_ts = GST_CLOCK_TIME_NONE;
1535     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_timestamp)) {
1536       last_ts = pad_monitor->current_timestamp;
1537       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_duration)) {
1538         last_ts += pad_monitor->current_duration;
1539       }
1540     }
1541     gst_validate_pad_monitor_otherpad_add_pending_serialized_event (pad_monitor,
1542         event, last_ts);
1543   }
1544
1545   ret =
1546       gst_validate_pad_monitor_downstream_event_check (pad_monitor, parent,
1547       event, pad_monitor->event_func);
1548
1549   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1550   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1551   return ret;
1552 }
1553
1554 static gboolean
1555 gst_validate_pad_monitor_src_event_func (GstPad * pad, GstObject * parent,
1556     GstEvent * event)
1557 {
1558   GstValidatePadMonitor *pad_monitor =
1559       g_object_get_data ((GObject *) pad, "validate-monitor");
1560   gboolean ret;
1561
1562   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1563   ret = gst_validate_pad_monitor_src_event_check (pad_monitor, parent, event,
1564       pad_monitor->event_func);
1565   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1566   return ret;
1567 }
1568
1569 static gboolean
1570 gst_validate_pad_monitor_query_func (GstPad * pad, GstObject * parent,
1571     GstQuery * query)
1572 {
1573   GstValidatePadMonitor *pad_monitor =
1574       g_object_get_data ((GObject *) pad, "validate-monitor");
1575   gboolean ret;
1576
1577   gst_validate_pad_monitor_query_overrides (pad_monitor, query);
1578
1579   ret = pad_monitor->query_func (pad, parent, query);
1580
1581   if (ret) {
1582     switch (GST_QUERY_TYPE (query)) {
1583       case GST_QUERY_CAPS:{
1584         GstCaps *res;
1585         /* We shouldn't need to lock the parent as this doesn't modify
1586          * other monitors, just does some peer_pad_caps */
1587         GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1588
1589         gst_query_parse_caps_result (query, &res);
1590         if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1591           gst_validate_pad_monitor_check_caps_fields_proxied (pad_monitor, res);
1592         }
1593         GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1594         break;
1595       }
1596       default:
1597         break;
1598     }
1599   }
1600
1601   return ret;
1602 }
1603
1604 static gboolean
1605 gst_validate_pad_monitor_activatemode_func (GstPad * pad, GstObject * parent,
1606     GstPadMode mode, gboolean active)
1607 {
1608   GstValidatePadMonitor *pad_monitor =
1609       g_object_get_data ((GObject *) pad, "validate-monitor");
1610   gboolean ret = TRUE;
1611
1612   /* TODO add overrides for activate func */
1613
1614   if (pad_monitor->activatemode_func)
1615     ret = pad_monitor->activatemode_func (pad, parent, mode, active);
1616   if (ret && active == FALSE) {
1617     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1618     gst_validate_pad_monitor_flush (pad_monitor);
1619     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1620   }
1621
1622   return ret;
1623 }
1624
1625 static gboolean
1626 gst_validate_pad_get_range_func (GstPad * pad, GstObject * parent,
1627     guint64 offset, guint size, GstBuffer ** buffer)
1628 {
1629   GstValidatePadMonitor *pad_monitor =
1630       g_object_get_data ((GObject *) pad, "validate-monitor");
1631   gboolean ret;
1632   ret = pad_monitor->getrange_func (pad, parent, offset, size, buffer);
1633   return ret;
1634 }
1635
1636 static gboolean
1637 gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
1638     gpointer udata)
1639 {
1640   GstValidatePadMonitor *monitor = udata;
1641
1642   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1643   GST_VALIDATE_MONITOR_LOCK (monitor);
1644
1645   gst_validate_pad_monitor_check_first_buffer (monitor, buffer);
1646   gst_validate_pad_monitor_update_buffer_data (monitor, buffer);
1647   gst_validate_pad_monitor_check_eos (monitor, buffer);
1648
1649   if (PAD_PARENT_IS_DECODER (monitor) || PAD_PARENT_IS_ENCODER (monitor)) {
1650     GstClockTime tolerance = 0;
1651
1652     if (monitor->caps_is_audio)
1653       tolerance = AUDIO_TIMESTAMP_TOLERANCE;
1654
1655     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range (monitor,
1656         buffer, tolerance);
1657   }
1658
1659   gst_validate_pad_monitor_check_late_serialized_events (monitor,
1660       GST_BUFFER_TIMESTAMP (buffer));
1661
1662   /* a GstValidatePadMonitor parent must be a GstValidateElementMonitor */
1663   if (PAD_PARENT_IS_DECODER (monitor)) {
1664
1665     /* should not push out of segment data */
1666     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)) &&
1667         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)) &&
1668         ((!gst_segment_clip (&monitor->segment, monitor->segment.format,
1669             GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer) +
1670             GST_BUFFER_DURATION (buffer), NULL, NULL)) ||
1671          /* In the case of raw data, buffers should be strictly contained inside the
1672           * segment */
1673          (monitor->caps_is_raw &&
1674           GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer) < monitor->segment.start))
1675          ) {
1676       /* TODO is this a timestamp issue? */
1677       GST_VALIDATE_REPORT (monitor, BUFFER_IS_OUT_OF_SEGMENT,
1678           "buffer is out of segment and shouldn't be pushed. Timestamp: %"
1679           GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT ". Range: %"
1680           GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1681           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1682           GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
1683           GST_TIME_ARGS (monitor->segment.start),
1684           GST_TIME_ARGS (monitor->segment.stop));
1685     }
1686   }
1687
1688   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1689   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1690   gst_validate_pad_monitor_buffer_probe_overrides (monitor, buffer);
1691   return TRUE;
1692 }
1693
1694 static gboolean
1695 gst_validate_pad_monitor_event_probe (GstPad * pad, GstEvent * event,
1696     gpointer udata)
1697 {
1698   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (udata);
1699   gboolean ret;
1700
1701   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1702   GST_VALIDATE_MONITOR_LOCK (monitor);
1703
1704   GST_DEBUG_OBJECT (pad, "event %p %s", event, GST_EVENT_TYPE_NAME (event));
1705
1706   if (GST_EVENT_IS_SERIALIZED (event)) {
1707     gint i;
1708
1709     /* Detect if events the element received are being forwarded in the same order
1710      *
1711      * Several scenarios:
1712      * 1) The element pushes the event as-is
1713      * 2) The element consumes the event and does not forward it
1714      * 3) The element consumes the event and creates another one instead
1715      * 4) The element pushes other serialized event before pushing out the
1716      *    one it received
1717      *
1718      * For each pad we have two lists to track serialized events:
1719      *  1) We received on input and expect to see (serialized_events)
1720      *  2) We received on input but don't expect to see (expired_events)
1721      *
1722      * To detect events that are pushed in a different order from the one they were
1723      * received in we check that:
1724      *
1725      * For each event being outputted:
1726      *   If it is in the expired_events list:
1727      *     RAISE WARNING
1728      *   If it is in the serialized_events list:
1729      *     If there are other events that were received before:
1730      *        Put those events on the expired_events list
1731      *     Remove that event and any previous ones from the serialized_events list
1732      *
1733      * Clear expired events list when flushing or on pad deactivation
1734      *
1735      */
1736
1737     if (g_list_find (monitor->expired_events, event)) {
1738       gchar *event_str = _get_event_string (event);
1739       /* If it's the expired events, we've failed */
1740       GST_WARNING_OBJECT (pad, "Did not expect event %p %s", event,
1741           GST_EVENT_TYPE_NAME (event));
1742       GST_VALIDATE_REPORT (monitor, EVENT_SERIALIZED_OUT_OF_ORDER,
1743           "Serialized event was pushed out of order: %s", event_str);
1744
1745       g_free (event_str);
1746       monitor->expired_events = g_list_remove (monitor->expired_events, event);
1747       gst_event_unref (event);  /* remove the ref that was on the list */
1748     } else if (monitor->serialized_events->len) {
1749       for (i = 0; i < monitor->serialized_events->len; i++) {
1750         SerializedEventData *next_event =
1751             g_ptr_array_index (monitor->serialized_events, i);
1752         GST_DEBUG_OBJECT (pad, "Checking against stored event #%d: %p %s", i,
1753             next_event->event, GST_EVENT_TYPE_NAME (next_event->event));
1754
1755         if (event == next_event->event
1756             || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1757           /* We have found our event */
1758           GST_DEBUG_OBJECT (pad, "Found matching event");
1759
1760           while (monitor->serialized_events->len > i
1761               && GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1762             /* Swallow all expected events of the same type */
1763             g_ptr_array_remove_index (monitor->serialized_events, i);
1764             next_event = g_ptr_array_index (monitor->serialized_events, i);
1765           }
1766
1767           /* Move all previous events to expired events */
1768           if (G_UNLIKELY (i > 0)) {
1769             GST_DEBUG_OBJECT (pad,
1770                 "Moving previous expected events to expired list");
1771             while (i--) {
1772               next_event = g_ptr_array_index (monitor->serialized_events, 0);
1773               monitor->expired_events =
1774                   g_list_append (monitor->expired_events,
1775                   gst_event_ref (next_event->event));
1776               g_ptr_array_remove_index (monitor->serialized_events, 0);
1777             }
1778           }
1779           debug_pending_event (pad, monitor->serialized_events);
1780           break;
1781         }
1782       }
1783     }
1784   }
1785
1786   /* This so far is just like an event that is flowing downstream,
1787    * so we do the same checks as a sinkpad event handler */
1788   ret =
1789       gst_validate_pad_monitor_downstream_event_check (monitor, NULL, event,
1790       NULL);
1791   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1792   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1793
1794   return ret;
1795 }
1796
1797 static GstPadProbeReturn
1798 gst_validate_pad_monitor_pad_probe (GstPad * pad, GstPadProbeInfo * info,
1799     gpointer udata)
1800 {
1801   if (info->type & GST_PAD_PROBE_TYPE_BUFFER)
1802     gst_validate_pad_monitor_buffer_probe (pad, info->data, udata);
1803   else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)
1804     gst_validate_pad_monitor_event_probe (pad, info->data, udata);
1805
1806   return GST_PAD_PROBE_OK;
1807 }
1808
1809 static void
1810 gst_validate_pad_monitor_update_caps_info (GstValidatePadMonitor * pad_monitor,
1811     GstCaps * caps)
1812 {
1813   GstStructure *structure;
1814
1815   g_return_if_fail (gst_caps_is_fixed (caps));
1816
1817   pad_monitor->caps_is_audio = FALSE;
1818   pad_monitor->caps_is_video = FALSE;
1819
1820   structure = gst_caps_get_structure (caps, 0);
1821   if (g_str_has_prefix (gst_structure_get_name (structure), "audio/")) {
1822     pad_monitor->caps_is_audio = TRUE;
1823   } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/")) {
1824     pad_monitor->caps_is_video = TRUE;
1825   }
1826
1827   if (g_str_has_prefix (gst_structure_get_name (structure), "audio/x-raw") ||
1828       g_str_has_prefix (gst_structure_get_name (structure), "video/x-raw")) {
1829     pad_monitor->caps_is_raw = TRUE;
1830   } else {
1831     pad_monitor->caps_is_raw = FALSE;
1832   }
1833 }
1834
1835 static void
1836 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
1837     GstCaps * caps)
1838 {
1839   GstStructure *structure;
1840
1841   /* Check if caps are identical to last caps and complain if so
1842    * Only checked for sink pads as src pads might push the same caps
1843    * multiple times during unlinked/autoplugging scenarios */
1844   if (GST_PAD_IS_SINK (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)) &&
1845       pad_monitor->last_caps
1846       && gst_caps_is_equal (caps, pad_monitor->last_caps)) {
1847     gchar *caps_str = gst_caps_to_string (caps);
1848
1849     GST_VALIDATE_REPORT (pad_monitor, EVENT_CAPS_DUPLICATE, "%s", caps_str);
1850     g_free (caps_str);
1851
1852   }
1853
1854   gst_validate_pad_monitor_check_caps_complete (pad_monitor, caps);
1855
1856   if (caps) {
1857     structure = gst_caps_get_structure (caps, 0);
1858     if (gst_structure_n_fields (pad_monitor->pending_setcaps_fields)) {
1859       gint i;
1860       for (i = 0;
1861           i < gst_structure_n_fields (pad_monitor->pending_setcaps_fields);
1862           i++) {
1863         const gchar *name =
1864             gst_structure_nth_field_name (pad_monitor->pending_setcaps_fields,
1865             i);
1866         const GValue *v = gst_structure_get_value (structure, name);
1867         const GValue *otherv =
1868             gst_structure_get_value (pad_monitor->pending_setcaps_fields, name);
1869
1870         if (v == NULL) {
1871           gchar *caps_str = gst_caps_to_string (caps);
1872
1873           GST_VALIDATE_REPORT (pad_monitor, CAPS_EXPECTED_FIELD_NOT_FOUND,
1874               "Field %s is missing from setcaps caps '%s'", name, caps_str);
1875           g_free (caps_str);
1876         } else if (gst_value_compare (v, otherv) != GST_VALUE_EQUAL) {
1877           gchar *caps_str = gst_caps_to_string (caps),
1878               *pending_setcaps_fields_str =
1879               gst_structure_to_string (pad_monitor->pending_setcaps_fields);
1880
1881
1882           GST_VALIDATE_REPORT (pad_monitor, CAPS_FIELD_UNEXPECTED_VALUE,
1883               "Field %s from setcaps caps '%s' is different "
1884               "from expected value in caps '%s'", name, caps_str,
1885               pending_setcaps_fields_str);
1886
1887           g_free (pending_setcaps_fields_str);
1888           g_free (caps_str);
1889         }
1890       }
1891     }
1892
1893     if (gst_validate_pad_monitor_pad_should_proxy_othercaps (pad_monitor)) {
1894       if (_structure_is_video (structure)) {
1895         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1896             structure, "width");
1897         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1898             structure, "height");
1899         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1900             structure, "framerate");
1901         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1902             structure, "pixel-aspect-ratio");
1903       } else if (_structure_is_audio (structure)) {
1904         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1905             structure, "rate");
1906         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1907             structure, "channels");
1908       }
1909     }
1910   }
1911
1912   gst_structure_free (pad_monitor->pending_setcaps_fields);
1913   pad_monitor->pending_setcaps_fields =
1914       gst_structure_new_empty (PENDING_FIELDS);
1915
1916   gst_validate_pad_monitor_setcaps_overrides (pad_monitor, caps);
1917 }
1918
1919 static void
1920 gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor * pad_monitor,
1921     GstCaps * caps, gboolean ret)
1922 {
1923   if (!ret)
1924     gst_validate_pad_monitor_otherpad_clear_pending_fields (pad_monitor);
1925   else {
1926     if (pad_monitor->last_caps) {
1927       gst_caps_unref (pad_monitor->last_caps);
1928     }
1929     pad_monitor->last_caps = gst_caps_ref (caps);
1930     gst_validate_pad_monitor_update_caps_info (pad_monitor, caps);
1931   }
1932 }
1933
1934 static gboolean
1935 gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
1936 {
1937   GstValidatePadMonitor *pad_monitor = GST_VALIDATE_PAD_MONITOR_CAST (monitor);
1938   GstPad *pad;
1939   if (!GST_IS_PAD (GST_VALIDATE_MONITOR_GET_OBJECT (monitor))) {
1940     GST_WARNING_OBJECT (monitor, "Trying to create pad monitor with other "
1941         "type of object");
1942     return FALSE;
1943   }
1944
1945   pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1946
1947   if (g_object_get_data ((GObject *) pad, "validate-monitor")) {
1948     GST_WARNING_OBJECT (pad_monitor,
1949         "Pad already has a validate-monitor associated");
1950     return FALSE;
1951   }
1952
1953   g_object_set_data ((GObject *) pad, "validate-monitor", pad_monitor);
1954
1955   pad_monitor->pad = pad;
1956
1957   pad_monitor->event_func = GST_PAD_EVENTFUNC (pad);
1958   pad_monitor->query_func = GST_PAD_QUERYFUNC (pad);
1959   pad_monitor->activatemode_func = GST_PAD_ACTIVATEMODEFUNC (pad);
1960   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1961
1962     pad_monitor->chain_func = GST_PAD_CHAINFUNC (pad);
1963     if (pad_monitor->chain_func)
1964       gst_pad_set_chain_function (pad, gst_validate_pad_monitor_chain_func);
1965
1966     gst_pad_set_event_function (pad, gst_validate_pad_monitor_sink_event_func);
1967   } else {
1968     pad_monitor->getrange_func = GST_PAD_GETRANGEFUNC (pad);
1969     if (pad_monitor->getrange_func)
1970       gst_pad_set_getrange_function (pad, gst_validate_pad_get_range_func);
1971
1972     gst_pad_set_event_function (pad, gst_validate_pad_monitor_src_event_func);
1973
1974     /* add buffer/event probes */
1975     pad_monitor->pad_probe_id =
1976         gst_pad_add_probe (pad,
1977         GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
1978         GST_PAD_PROBE_TYPE_EVENT_FLUSH,
1979         (GstPadProbeCallback) gst_validate_pad_monitor_pad_probe, pad_monitor,
1980         NULL);
1981   }
1982   gst_pad_set_query_function (pad, gst_validate_pad_monitor_query_func);
1983   gst_pad_set_activatemode_function (pad,
1984       gst_validate_pad_monitor_activatemode_func);
1985
1986   gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (monitor),
1987       g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad)));
1988
1989   if (G_UNLIKELY (GST_PAD_PARENT (pad) == NULL))
1990     GST_FIXME ("Saw a pad not belonging to any object");
1991
1992   return TRUE;
1993 }