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