validate: pad-monitor: fix buffers list leak
[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 static GstValidateInterceptionReturn
43 gst_validate_pad_monitor_intercept_report (GstValidateReporter * reporter,
44     GstValidateReport * report);
45
46 #define _do_init \
47   G_IMPLEMENT_INTERFACE (GST_TYPE_VALIDATE_REPORTER, _reporter_iface_init)
48
49 static void
50 _reporter_iface_init (GstValidateReporterInterface * iface)
51 {
52   iface->intercept_report = gst_validate_pad_monitor_intercept_report;
53 }
54
55 #define gst_validate_pad_monitor_parent_class parent_class
56 G_DEFINE_TYPE_WITH_CODE (GstValidatePadMonitor, gst_validate_pad_monitor,
57     GST_TYPE_VALIDATE_MONITOR, _do_init);
58
59 #define PENDING_FIELDS "pending-fields"
60 #define AUDIO_TIMESTAMP_TOLERANCE (GST_MSECOND * 100)
61
62 #define PAD_PARENT_IS_DEMUXER(m) \
63     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
64         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DEMUXER ( \
65             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
66         FALSE)
67
68 #define PAD_PARENT_IS_DECODER(m) \
69     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
70         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DECODER ( \
71             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
72         FALSE)
73
74 #define PAD_PARENT_IS_ENCODER(m) \
75     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
76         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_ENCODER ( \
77             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
78         FALSE)
79
80
81 /*
82  * Locking the parent should always be done before locking the
83  * pad-monitor to prevent deadlocks in case another monitor from
84  * another pad on the same element starts an operation that also
85  * requires locking itself and some other monitors from internally
86  * linked pads.
87  *
88  * An example:
89  * An element has a sink and a src pad. Some test starts running at sinkpad
90  * and it locks the parent, and then it locks itself. In case it needs to get
91  * some information from the srcpad, it is able to lock the srcpad and get it
92  * because the srcpad should never lock itself before locking the parent (which
93  * it won't be able as sinkpad already locked it).
94  *
95  * As a side one, it is possible that srcpad locks itself without locking the
96  * parent in case it wants to do a check that won't need to use other internally
97  * linked pads (sinkpad). But in this case it might lock and unlock freely without
98  * causing deadlocks.
99  */
100 #define GST_VALIDATE_PAD_MONITOR_PARENT_LOCK(m)                  \
101 G_STMT_START {                                             \
102   if (G_LIKELY (GST_VALIDATE_MONITOR_GET_PARENT (m))) {          \
103     GST_VALIDATE_MONITOR_LOCK (GST_VALIDATE_MONITOR_GET_PARENT (m));   \
104   } else {                                                 \
105     GST_WARNING_OBJECT (m, "No parent found, can't lock"); \
106   }                                                        \
107 } G_STMT_END
108
109 #define GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK(m)                  \
110 G_STMT_START {                                               \
111   if (G_LIKELY (GST_VALIDATE_MONITOR_GET_PARENT (m))) {            \
112     GST_VALIDATE_MONITOR_UNLOCK (GST_VALIDATE_MONITOR_GET_PARENT (m));   \
113   } else {                                                   \
114     GST_WARNING_OBJECT (m, "No parent found, can't unlock"); \
115   }                                                          \
116 } G_STMT_END
117
118 typedef struct
119 {
120   GstClockTime timestamp;
121   GstEvent *event;
122 } SerializedEventData;
123
124 static GstPad *
125 _get_actual_pad (GstPad * pad)
126 {
127   GstPad *tmp_pad;
128
129   gst_object_ref (pad);
130
131   /* We don't monitor ghost pads */
132   while (GST_IS_GHOST_PAD (pad)) {
133     tmp_pad = pad;
134     pad = gst_ghost_pad_get_target ((GstGhostPad *) pad);
135     gst_object_unref (tmp_pad);
136   }
137
138   while (GST_IS_PROXY_PAD (pad)) {
139     tmp_pad = pad;
140     pad = gst_pad_get_peer (pad);
141     gst_object_unref (tmp_pad);
142   }
143
144   return pad;
145 }
146
147 static gboolean
148 _find_master_report_on_pad (GstPad * pad, GstValidateReport * report)
149 {
150   GstValidatePadMonitor *pad_monitor;
151   GstValidateReport *prev_report;
152   gboolean result = FALSE;
153   GstPad *tmppad = pad;
154
155   pad = _get_actual_pad (pad);
156   if (pad == NULL) {
157     GST_ERROR_OBJECT (tmppad, "Does not have a target yet");
158
159     return FALSE;
160   }
161
162   pad_monitor = g_object_get_data ((GObject *) pad, "validate-monitor");
163
164   /* For some reason this pad isn't monitored */
165   if (pad_monitor == NULL)
166     goto done;
167
168   prev_report = gst_validate_reporter_get_report ((GstValidateReporter *)
169       pad_monitor, report->issue->issue_id);
170
171   if (prev_report) {
172     if (prev_report->master_report)
173       result = gst_validate_report_set_master_report (report,
174           prev_report->master_report);
175     else
176       result = gst_validate_report_set_master_report (report, prev_report);
177   }
178
179 done:
180   gst_object_unref (pad);
181
182   return result;
183 }
184
185 static gboolean
186 _find_master_report_for_sink_pad (GstValidatePadMonitor * pad_monitor,
187     GstValidateReport * report)
188 {
189   GstPad *peerpad;
190   gboolean result = FALSE;
191
192   peerpad = gst_pad_get_peer (pad_monitor->pad);
193
194   /* If the peer src pad already has a similar report no need to look
195    * any further */
196   if (peerpad && _find_master_report_on_pad (peerpad, report))
197     result = TRUE;
198
199   if (peerpad)
200     gst_object_unref (peerpad);
201
202   return result;
203 }
204
205 static gboolean
206 _find_master_report_for_src_pad (GstValidatePadMonitor * pad_monitor,
207     GstValidateReport * report)
208 {
209   GstIterator *iter;
210   gboolean done;
211   GstPad *pad;
212   gboolean result = FALSE;
213
214   iter =
215       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
216       (pad_monitor));
217   done = FALSE;
218   while (!done) {
219     GValue value = { 0, };
220     switch (gst_iterator_next (iter, &value)) {
221       case GST_ITERATOR_OK:
222         pad = g_value_get_object (&value);
223
224         if (_find_master_report_on_pad (pad, report)) {
225           result = TRUE;
226           done = TRUE;
227         }
228
229         g_value_reset (&value);
230         break;
231       case GST_ITERATOR_RESYNC:
232         gst_iterator_resync (iter);
233         break;
234       case GST_ITERATOR_ERROR:
235         GST_WARNING_OBJECT (pad_monitor->pad,
236             "Internal links pad iteration error");
237         done = TRUE;
238         break;
239       case GST_ITERATOR_DONE:
240         done = TRUE;
241         break;
242     }
243   }
244   gst_iterator_free (iter);
245
246   return result;
247 }
248
249 static GstValidateInterceptionReturn
250 _concatenate_issues (GstValidatePadMonitor * pad_monitor,
251     GstValidateReport * report)
252 {
253   if (GST_PAD_IS_SINK (pad_monitor->pad)
254       && _find_master_report_for_sink_pad (pad_monitor, report))
255     return GST_VALIDATE_REPORTER_KEEP;
256   else if (GST_PAD_IS_SRC (pad_monitor->pad)
257       && _find_master_report_for_src_pad (pad_monitor, report))
258     return GST_VALIDATE_REPORTER_KEEP;
259
260   return GST_VALIDATE_REPORTER_REPORT;
261 }
262
263 static GstValidateInterceptionReturn
264 gst_validate_pad_monitor_intercept_report (GstValidateReporter *
265     reporter, GstValidateReport * report)
266 {
267   GstValidateReporterInterface *iface_class, *old_iface_class;
268   GstValidatePadMonitor *pad_monitor = GST_VALIDATE_PAD_MONITOR (reporter);
269   GstValidateReportingDetails monitor_reporting_level;
270   GstValidateInterceptionReturn ret;
271
272   monitor_reporting_level =
273       gst_validate_reporter_get_reporting_level (reporter);
274
275   iface_class =
276       G_TYPE_INSTANCE_GET_INTERFACE (reporter, GST_TYPE_VALIDATE_REPORTER,
277       GstValidateReporterInterface);
278   old_iface_class = g_type_interface_peek_parent (iface_class);
279
280   old_iface_class->intercept_report (reporter, report);
281
282   switch (monitor_reporting_level) {
283     case GST_VALIDATE_SHOW_NONE:
284       ret = GST_VALIDATE_REPORTER_DROP;
285       break;
286     case GST_VALIDATE_SHOW_UNKNOWN:
287       ret = _concatenate_issues (pad_monitor, report);
288       break;
289     default:
290       ret = GST_VALIDATE_REPORTER_REPORT;
291       break;
292   }
293
294   gst_validate_report_set_reporting_level (report, monitor_reporting_level);
295   return ret;
296 }
297
298 static void
299 debug_pending_event (GstPad * pad, GPtrArray * array)
300 {
301   guint i, len;
302
303   len = array->len;
304   for (i = 0; i < len; i++) {
305     SerializedEventData *data = g_ptr_array_index (array, i);
306     GST_DEBUG_OBJECT (pad, "event #%d %" GST_TIME_FORMAT " %s %p",
307         i, GST_TIME_ARGS (data->timestamp),
308         GST_EVENT_TYPE_NAME (data->event), data->event);
309   }
310 }
311
312 static void
313 _serialized_event_data_free (SerializedEventData * serialized_event)
314 {
315   gst_event_unref (serialized_event->event);
316   g_slice_free (SerializedEventData, serialized_event);
317 }
318
319 static gboolean gst_validate_pad_monitor_do_setup (GstValidateMonitor *
320     monitor);
321 static GstElement *gst_validate_pad_monitor_get_element (GstValidateMonitor *
322     monitor);
323 static void
324 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
325     GstCaps * caps);
326 static void gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor *
327     pad_monitor, GstCaps * caps, gboolean ret);
328
329 #define PAD_IS_IN_PUSH_MODE(p) ((p)->mode == GST_PAD_MODE_PUSH)
330
331 static gboolean
332 _structure_is_raw_video (GstStructure * structure)
333 {
334   return gst_structure_has_name (structure, "video/x-raw");
335 }
336
337 static gboolean
338 _structure_is_raw_audio (GstStructure * structure)
339 {
340   return gst_structure_has_name (structure, "audio/x-raw");
341 }
342
343 static gchar *
344 _get_event_string (GstEvent * event)
345 {
346   const GstStructure *st;
347
348   if ((st = gst_event_get_structure (event)))
349     return gst_structure_to_string (st);
350   else
351     return g_strdup_printf ("%s", GST_EVENT_TYPE_NAME (event));
352 }
353
354 static void
355 _check_field_type (GstValidatePadMonitor * monitor,
356     GstStructure * structure, gboolean mandatory, const gchar * field, ...)
357 {
358   va_list var_args;
359   GType type;
360   gchar *joined_types = NULL;
361   const gchar *rejected_types[5];
362   gint rejected_types_index = 0;
363   gchar *struct_str;
364
365   if (!gst_structure_has_field (structure, field)) {
366     if (mandatory) {
367       gchar *str = gst_structure_to_string (structure);
368
369       GST_VALIDATE_REPORT (monitor, CAPS_IS_MISSING_FIELD,
370           "Field '%s' is missing from structure: %s", field, str);
371       g_free (str);
372     } else {
373       GST_DEBUG_OBJECT (monitor, "Field %s is missing but is not mandatory",
374           field);
375     }
376     return;
377   }
378
379   memset (rejected_types, 0, sizeof (rejected_types));
380   va_start (var_args, field);
381   while ((type = va_arg (var_args, GType)) != 0) {
382     if (gst_structure_has_field_typed (structure, field, type)) {
383       va_end (var_args);
384       return;
385     }
386     rejected_types[rejected_types_index++] = g_type_name (type);
387   }
388   va_end (var_args);
389
390   joined_types = g_strjoinv (" / ", (gchar **) rejected_types);
391   struct_str = gst_structure_to_string (structure);
392   GST_VALIDATE_REPORT (monitor, CAPS_FIELD_HAS_BAD_TYPE,
393       "Field '%s' has wrong type %s in structure '%s'. Expected: %s", field,
394       g_type_name (gst_structure_get_field_type (structure, field)), struct_str,
395       joined_types);
396   g_free (joined_types);
397   g_free (struct_str);
398 }
399
400 static void
401 gst_validate_pad_monitor_check_raw_video_caps_complete (GstValidatePadMonitor *
402     monitor, GstStructure * structure)
403 {
404   _check_field_type (monitor, structure, TRUE, "width", G_TYPE_INT,
405       GST_TYPE_INT_RANGE, 0);
406   _check_field_type (monitor, structure, TRUE, "height", G_TYPE_INT,
407       GST_TYPE_INT_RANGE, 0);
408   _check_field_type (monitor, structure, TRUE, "framerate", GST_TYPE_FRACTION,
409       GST_TYPE_FRACTION_RANGE, 0);
410   _check_field_type (monitor, structure, FALSE, "pixel-aspect-ratio",
411       GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, 0);
412   _check_field_type (monitor, structure, TRUE, "format", G_TYPE_STRING,
413       GST_TYPE_LIST);
414 }
415
416 static void
417 gst_validate_pad_monitor_check_raw_audio_caps_complete (GstValidatePadMonitor *
418     monitor, GstStructure * structure)
419 {
420   gint channels;
421   _check_field_type (monitor, structure, TRUE, "format", G_TYPE_STRING,
422       GST_TYPE_LIST, 0);
423   _check_field_type (monitor, structure, TRUE, "layout", G_TYPE_STRING,
424       GST_TYPE_LIST, 0);
425   _check_field_type (monitor, structure, TRUE, "rate", G_TYPE_INT,
426       GST_TYPE_LIST, GST_TYPE_INT_RANGE, 0);
427   _check_field_type (monitor, structure, TRUE, "channels", G_TYPE_INT,
428       GST_TYPE_LIST, GST_TYPE_INT_RANGE, 0);
429   if (gst_structure_get_int (structure, "channels", &channels)) {
430     if (channels > 2)
431       _check_field_type (monitor, structure, TRUE, "channel-mask",
432           GST_TYPE_BITMASK, GST_TYPE_LIST, 0);
433   }
434 }
435
436 static void
437 gst_validate_pad_monitor_check_caps_complete (GstValidatePadMonitor * monitor,
438     GstCaps * caps)
439 {
440   GstStructure *structure;
441   gint i;
442
443   GST_DEBUG_OBJECT (monitor->pad, "Checking caps %" GST_PTR_FORMAT, caps);
444
445   for (i = 0; i < gst_caps_get_size (caps); i++) {
446     structure = gst_caps_get_structure (caps, i);
447
448     if (_structure_is_raw_video (structure)) {
449       gst_validate_pad_monitor_check_raw_video_caps_complete (monitor,
450           structure);
451
452     } else if (_structure_is_raw_audio (structure)) {
453       gst_validate_pad_monitor_check_raw_audio_caps_complete (monitor,
454           structure);
455     }
456   }
457 }
458
459 static GstCaps *
460 gst_validate_pad_monitor_get_othercaps (GstValidatePadMonitor * monitor,
461     GstCaps * filter)
462 {
463   GstCaps *caps = gst_caps_new_empty ();
464   GstIterator *iter;
465   gboolean done;
466   GstPad *otherpad;
467   GstCaps *peercaps;
468
469   iter =
470       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
471       (monitor));
472   done = FALSE;
473   while (!done) {
474     GValue value = { 0, };
475     switch (gst_iterator_next (iter, &value)) {
476       case GST_ITERATOR_OK:
477         otherpad = g_value_get_object (&value);
478
479         /* TODO What would be the correct caps operation to merge the caps in
480          * case one sink is internally linked to multiple srcs? */
481         peercaps = gst_pad_peer_query_caps (otherpad, filter);
482         if (peercaps)
483           caps = gst_caps_merge (caps, peercaps);
484
485         g_value_reset (&value);
486         break;
487       case GST_ITERATOR_RESYNC:
488         gst_iterator_resync (iter);
489         gst_caps_unref (caps);
490         caps = gst_caps_new_empty ();
491         break;
492       case GST_ITERATOR_ERROR:
493         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
494         done = TRUE;
495         break;
496       case GST_ITERATOR_DONE:
497         done = TRUE;
498         break;
499     }
500   }
501   gst_iterator_free (iter);
502
503   GST_DEBUG_OBJECT (monitor->pad, "Otherpad caps: %" GST_PTR_FORMAT, caps);
504
505   return caps;
506 }
507
508 static gboolean
509 _structure_is_video (GstStructure * structure)
510 {
511   const gchar *name = gst_structure_get_name (structure);
512
513   return g_strstr_len (name, 6, "video/")
514       && strcmp (name, "video/quicktime") != 0;
515 }
516
517 static gboolean
518 _structure_is_audio (GstStructure * structure)
519 {
520   const gchar *name = gst_structure_get_name (structure);
521
522   return g_strstr_len (name, 6, "audio/") != NULL;
523 }
524
525 static gboolean
526 gst_validate_pad_monitor_pad_should_proxy_othercaps (GstValidatePadMonitor *
527     monitor)
528 {
529   GstValidateMonitor *parent = GST_VALIDATE_MONITOR_GET_PARENT (monitor);
530
531   if (!parent)
532     return FALSE;
533
534   /* We only know how to handle othercaps checks for codecs so far */
535   return (GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DECODER (parent) ||
536       GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_ENCODER (parent)) &&
537       !GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_CONVERTER (parent);
538 }
539
540
541 /* Check if the field @f from @s2 (if present) is represented in @s1
542  * Represented here means either equal or @s1's value is in a list/range
543  * from @s2
544  */
545 static gboolean
546 _structures_field_is_contained (GstStructure * s1, GstStructure * s2,
547     gboolean mandatory, const gchar * f)
548 {
549   const GValue *v1;
550   const GValue *v2;
551
552   v2 = gst_structure_get_value (s2, f);
553   if (!v2)
554     return TRUE;                /* nothing to compare to */
555
556   v1 = gst_structure_get_value (s1, f);
557   if (!v1)
558     return !mandatory;
559
560   if (!gst_value_is_fixed (v1))
561     return TRUE;
562
563   if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
564     return TRUE;
565
566   if (GST_VALUE_HOLDS_LIST (v2)) {
567     gint i;
568     for (i = 0; i < gst_value_list_get_size (v2); i++) {
569       const GValue *v2_subvalue = gst_value_list_get_value (v2, i);
570       if (gst_value_compare (v1, v2_subvalue) == GST_VALUE_EQUAL)
571         return TRUE;
572     }
573   }
574
575   if (GST_VALUE_HOLDS_ARRAY (v2)) {
576     gint i;
577     for (i = 0; i < gst_value_array_get_size (v2); i++) {
578       const GValue *v2_subvalue = gst_value_array_get_value (v2, i);
579       if (gst_value_compare (v1, v2_subvalue) == GST_VALUE_EQUAL)
580         return TRUE;
581     }
582   }
583
584   if (GST_VALUE_HOLDS_INT_RANGE (v2)) {
585     gint min, max;
586
587     min = gst_value_get_int_range_min (v2);
588     max = gst_value_get_int_range_max (v2);
589
590     if (G_VALUE_HOLDS_INT (v1)) {
591       gint v = g_value_get_int (v1);
592
593       return v >= min && v <= max;
594     } else {
595       /* TODO compare int ranges with int ranges
596        * or with lists if useful */
597     }
598   }
599
600   if (GST_VALUE_HOLDS_FRACTION_RANGE (v2)) {
601     const GValue *min, *max;
602
603     min = gst_value_get_fraction_range_min (v2);
604     max = gst_value_get_fraction_range_max (v2);
605
606     if (GST_VALUE_HOLDS_FRACTION (v1)) {
607       gint v_min = gst_value_compare (v1, min);
608       gint v_max = gst_value_compare (v1, max);
609
610       return (v_min == GST_VALUE_EQUAL || v_min == GST_VALUE_GREATER_THAN) &&
611           (v_max == GST_VALUE_EQUAL || v_max == GST_VALUE_LESS_THAN);
612     } else {
613       /* TODO compare fraction ranges with fraction ranges
614        * or with lists if useful */
615     }
616   }
617
618   return FALSE;
619 }
620
621 static void
622 _check_and_copy_structure_field (GstStructure * from, GstStructure * to,
623     const gchar * name)
624 {
625   if (gst_structure_has_field (from, name)) {
626     gst_structure_set_value (to, name, gst_structure_get_value (from, name));
627   }
628 }
629
630 static GstCaps *
631 gst_validate_pad_monitor_copy_caps_fields_into_caps (GstValidatePadMonitor *
632     monitor, GstCaps * from_caps, GstCaps * into_caps)
633 {
634   gint i, j, into_size, from_size;
635   GstStructure *structure;
636   GstCaps *res = gst_caps_new_empty ();
637
638   into_size = gst_caps_get_size (into_caps);
639   from_size = gst_caps_get_size (from_caps);
640
641   for (i = 0; i < into_size; i++) {
642     GstStructure *s = gst_caps_get_structure (into_caps, i);
643
644     for (j = 0; j < from_size; j++) {
645       GstStructure *new_structure = gst_structure_copy (s);
646
647       structure = gst_caps_get_structure (from_caps, j);
648       if (_structure_is_video (structure)) {
649         _check_and_copy_structure_field (structure, new_structure, "width");
650         _check_and_copy_structure_field (structure, new_structure, "height");
651         _check_and_copy_structure_field (structure, new_structure, "framerate");
652         _check_and_copy_structure_field (structure, new_structure,
653             "pixel-aspect-ratio");
654       } else if (_structure_is_audio (s)) {
655         _check_and_copy_structure_field (structure, new_structure, "rate");
656         _check_and_copy_structure_field (structure, new_structure, "channels");
657       }
658
659       gst_caps_append_structure (res, new_structure);
660     }
661   }
662   return res;
663 }
664
665 static GstCaps *
666 gst_validate_pad_monitor_transform_caps (GstValidatePadMonitor * monitor,
667     GstCaps * caps)
668 {
669   GstCaps *othercaps = gst_caps_new_empty ();
670   GstCaps *new_caps;
671   GstIterator *iter;
672   gboolean done;
673   GstPad *otherpad;
674   GstCaps *template_caps;
675
676   GST_DEBUG_OBJECT (monitor->pad, "Transform caps %" GST_PTR_FORMAT, caps);
677
678   if (caps == NULL)
679     return NULL;
680
681   iter =
682       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
683       (monitor));
684   done = FALSE;
685   while (!done) {
686     GValue value = { 0, };
687     switch (gst_iterator_next (iter, &value)) {
688       case GST_ITERATOR_OK:
689         otherpad = g_value_get_object (&value);
690         template_caps = gst_pad_get_pad_template_caps (otherpad);
691
692         new_caps =
693             gst_validate_pad_monitor_copy_caps_fields_into_caps (monitor, caps,
694             template_caps);
695         if (!gst_caps_is_empty (new_caps))
696           gst_caps_append (othercaps, new_caps);
697         else
698           gst_caps_unref (new_caps);
699
700         gst_caps_unref (template_caps);
701         g_value_reset (&value);
702         break;
703       case GST_ITERATOR_RESYNC:
704         gst_iterator_resync (iter);
705         gst_caps_unref (othercaps);
706         othercaps = gst_caps_new_empty ();
707         break;
708       case GST_ITERATOR_ERROR:
709         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
710         done = TRUE;
711         break;
712       case GST_ITERATOR_DONE:
713         done = TRUE;
714         break;
715     }
716   }
717   gst_iterator_free (iter);
718
719   GST_DEBUG_OBJECT (monitor->pad, "Transformed caps: %" GST_PTR_FORMAT,
720       othercaps);
721
722   return othercaps;
723 }
724
725 static void
726 gst_validate_pad_monitor_check_caps_fields_proxied (GstValidatePadMonitor *
727     monitor, GstCaps * caps, GstCaps * filter)
728 {
729   GstStructure *structure;
730   GstStructure *otherstructure;
731   GstCaps *othercaps;
732   GstCaps *otherfilter;
733   gint i, j;
734
735   if (!gst_validate_pad_monitor_pad_should_proxy_othercaps (monitor))
736     return;
737
738   otherfilter = gst_validate_pad_monitor_transform_caps (monitor, filter);
739   othercaps = gst_validate_pad_monitor_get_othercaps (monitor, otherfilter);
740   if (otherfilter)
741     gst_caps_unref (otherfilter);
742
743   for (i = 0; i < gst_caps_get_size (othercaps); i++) {
744     gboolean found = FALSE;
745     gboolean type_match = FALSE;
746
747     otherstructure = gst_caps_get_structure (othercaps, i);
748
749     /* look for a proxied version of 'otherstructure' */
750     if (_structure_is_video (otherstructure)) {
751       for (j = 0; j < gst_caps_get_size (caps); j++) {
752         structure = gst_caps_get_structure (caps, j);
753         if (_structure_is_video (structure)) {
754           type_match = TRUE;
755           if (_structures_field_is_contained (structure, otherstructure, TRUE,
756                   "width")
757               && _structures_field_is_contained (structure, otherstructure,
758                   TRUE, "height")
759               && _structures_field_is_contained (structure, otherstructure,
760                   TRUE, "framerate")
761               && _structures_field_is_contained (structure, otherstructure,
762                   FALSE, "pixel-aspect-ratio")) {
763             found = TRUE;
764             break;
765           }
766         }
767       }
768     } else if (_structure_is_audio (otherstructure)) {
769       for (j = 0; j < gst_caps_get_size (caps); j++) {
770         structure = gst_caps_get_structure (caps, j);
771         if (_structure_is_audio (structure)) {
772           type_match = TRUE;
773           if (_structures_field_is_contained (structure, otherstructure, TRUE,
774                   "rate")
775               && _structures_field_is_contained (structure, otherstructure,
776                   TRUE, "channels")) {
777             found = TRUE;
778             break;
779           }
780         }
781       }
782     }
783
784     if (type_match && !found) {
785       gchar *otherstruct_str = gst_structure_to_string (otherstructure),
786           *caps_str = gst_caps_to_string (caps);
787
788       GST_VALIDATE_REPORT (monitor, GET_CAPS_NOT_PROXYING_FIELDS,
789           "Peer pad structure '%s' has no similar version "
790           "on pad's caps '%s'", otherstruct_str, caps_str);
791
792       g_free (otherstruct_str);
793       g_free (caps_str);
794     }
795   }
796
797   gst_caps_unref (othercaps);
798 }
799
800 static void
801 gst_validate_pad_monitor_check_late_serialized_events (GstValidatePadMonitor *
802     monitor, GstClockTime ts)
803 {
804   gint i;
805
806   if (!GST_CLOCK_TIME_IS_VALID (ts))
807     return;
808
809   GST_DEBUG_OBJECT (monitor->pad, "Timestamp to check %" GST_TIME_FORMAT,
810       GST_TIME_ARGS (ts));
811
812   for (i = 0; i < monitor->serialized_events->len; i++) {
813     SerializedEventData *data =
814         g_ptr_array_index (monitor->serialized_events, i);
815
816     GST_DEBUG_OBJECT (monitor->pad, "Event #%d (%s) ts: %" GST_TIME_FORMAT,
817         i, GST_EVENT_TYPE_NAME (data->event), GST_TIME_ARGS (data->timestamp));
818
819     if (GST_CLOCK_TIME_IS_VALID (data->timestamp) && data->timestamp < ts) {
820       gchar *event_str = _get_event_string (data->event);
821
822       GST_VALIDATE_REPORT (monitor, SERIALIZED_EVENT_WASNT_PUSHED_IN_TIME,
823           "Serialized event %s wasn't pushed before expected " "timestamp %"
824           GST_TIME_FORMAT " on pad %s:%s", event_str,
825           GST_TIME_ARGS (data->timestamp),
826           GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)));
827
828       g_free (event_str);
829     } else {
830       /* events should be ordered by ts */
831       break;
832     }
833   }
834
835   if (i) {
836     debug_pending_event (monitor->pad, monitor->serialized_events);
837     g_ptr_array_remove_range (monitor->serialized_events, 0, i);
838   }
839 }
840
841 static void
842 gst_validate_pad_monitor_dispose (GObject * object)
843 {
844   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (object);
845   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
846
847   if (pad) {
848     if (monitor->pad_probe_id)
849       gst_pad_remove_probe (pad, monitor->pad_probe_id);
850   }
851
852   if (monitor->expected_segment)
853     gst_event_unref (monitor->expected_segment);
854
855   gst_structure_free (monitor->pending_setcaps_fields);
856   g_ptr_array_unref (monitor->serialized_events);
857   g_list_free_full (monitor->expired_events, (GDestroyNotify) gst_event_unref);
858   g_list_free_full (monitor->all_bufs, (GDestroyNotify) gst_buffer_unref);
859
860   G_OBJECT_CLASS (parent_class)->dispose (object);
861 }
862
863 static void
864 gst_validate_pad_monitor_class_init (GstValidatePadMonitorClass * klass)
865 {
866   GObjectClass *gobject_class;
867   GstValidateMonitorClass *monitor_klass;
868
869   gobject_class = G_OBJECT_CLASS (klass);
870   monitor_klass = GST_VALIDATE_MONITOR_CLASS (klass);
871
872   gobject_class->dispose = gst_validate_pad_monitor_dispose;
873
874   monitor_klass->setup = gst_validate_pad_monitor_do_setup;
875   monitor_klass->get_element = gst_validate_pad_monitor_get_element;
876 }
877
878 static void
879 gst_validate_pad_monitor_init (GstValidatePadMonitor * pad_monitor)
880 {
881   pad_monitor->pending_setcaps_fields =
882       gst_structure_new_empty (PENDING_FIELDS);
883   pad_monitor->serialized_events =
884       g_ptr_array_new_with_free_func ((GDestroyNotify)
885       _serialized_event_data_free);
886   pad_monitor->expired_events = NULL;
887   gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES);
888   pad_monitor->first_buffer = TRUE;
889
890   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
891   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
892 }
893
894 /**
895  * gst_validate_pad_monitor_new:
896  * @pad: (transfer-none): a #GstPad to run Validate on
897  */
898 GstValidatePadMonitor *
899 gst_validate_pad_monitor_new (GstPad * pad, GstValidateRunner * runner,
900     GstValidateElementMonitor * parent)
901 {
902   GstValidatePadMonitor *monitor = g_object_new (GST_TYPE_VALIDATE_PAD_MONITOR,
903       "object", pad, "validate-runner", runner, "validate-parent",
904       parent, NULL);
905
906   if (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor) == NULL) {
907     g_object_unref (monitor);
908     return NULL;
909   }
910   return monitor;
911 }
912
913 static GstElement *
914 gst_validate_pad_monitor_get_element (GstValidateMonitor * monitor)
915 {
916   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
917
918   return GST_PAD_PARENT (pad);
919 }
920
921 static void
922 gst_validate_pad_monitor_event_overrides (GstValidatePadMonitor * pad_monitor,
923     GstEvent * event)
924 {
925   GList *iter;
926
927   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
928   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
929       iter = g_list_next (iter)) {
930     GstValidateOverride *override = iter->data;
931
932     gst_validate_override_event_handler (override,
933         GST_VALIDATE_MONITOR_CAST (pad_monitor), event);
934   }
935   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
936 }
937
938 static void
939 gst_validate_pad_monitor_buffer_overrides (GstValidatePadMonitor * pad_monitor,
940     GstBuffer * buffer)
941 {
942   GList *iter;
943
944   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
945   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
946       iter = g_list_next (iter)) {
947     GstValidateOverride *override = iter->data;
948
949     gst_validate_override_buffer_handler (override,
950         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
951   }
952   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
953 }
954
955 static void
956 gst_validate_pad_monitor_buffer_probe_overrides (GstValidatePadMonitor *
957     pad_monitor, GstBuffer * buffer)
958 {
959   GList *iter;
960
961   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
962   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
963       iter = g_list_next (iter)) {
964     GstValidateOverride *override = iter->data;
965
966     gst_validate_override_buffer_probe_handler (override,
967         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
968   }
969   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
970 }
971
972 static void
973 gst_validate_pad_monitor_query_overrides (GstValidatePadMonitor * pad_monitor,
974     GstQuery * query)
975 {
976   GList *iter;
977
978   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
979   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
980       iter = g_list_next (iter)) {
981     GstValidateOverride *override = iter->data;
982
983     gst_validate_override_query_handler (override,
984         GST_VALIDATE_MONITOR_CAST (pad_monitor), query);
985   }
986   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
987 }
988
989 static void
990 gst_validate_pad_monitor_setcaps_overrides (GstValidatePadMonitor * pad_monitor,
991     GstCaps * caps)
992 {
993   GList *iter;
994
995   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
996   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
997       iter = g_list_next (iter)) {
998     GstValidateOverride *override = iter->data;
999
1000     gst_validate_override_setcaps_handler (override,
1001         GST_VALIDATE_MONITOR_CAST (pad_monitor), caps);
1002   }
1003   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
1004 }
1005
1006 /* FIXME : This is a bit dubious, what's the point of this check ? */
1007 static gboolean
1008 gst_validate_pad_monitor_timestamp_is_in_received_range (GstValidatePadMonitor *
1009     monitor, GstClockTime ts, GstClockTime tolerance)
1010 {
1011   GST_DEBUG_OBJECT (monitor->pad, "Checking if timestamp %" GST_TIME_FORMAT
1012       " is in range: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT " for pad "
1013       "%s:%s with tolerance: %" GST_TIME_FORMAT, GST_TIME_ARGS (ts),
1014       GST_TIME_ARGS (monitor->timestamp_range_start),
1015       GST_TIME_ARGS (monitor->timestamp_range_end),
1016       GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)),
1017       GST_TIME_ARGS (tolerance));
1018   return !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_start) ||
1019       !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_end) ||
1020       ((monitor->timestamp_range_start >= tolerance ?
1021           monitor->timestamp_range_start - tolerance : 0) <= ts
1022       && (ts >= tolerance ? ts - tolerance : 0) <=
1023       monitor->timestamp_range_end);
1024 }
1025
1026 /* Iterates over internal links (sinkpads) to check that this buffer has
1027  * a timestamp that is in the range of the lastly received buffers */
1028 static void
1029     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range
1030     (GstValidatePadMonitor * monitor, GstBuffer * buffer,
1031     GstClockTime tolerance)
1032 {
1033   GstClockTime ts;
1034   GstClockTime ts_end;
1035   GstIterator *iter;
1036   gboolean has_one = FALSE;
1037   gboolean found = FALSE;
1038   gboolean done;
1039   GstPad *otherpad;
1040   GstValidatePadMonitor *othermonitor;
1041
1042   if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))
1043       || !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
1044     GST_DEBUG_OBJECT (monitor->pad,
1045         "Can't check buffer timestamps range as "
1046         "buffer has no valid timestamp/duration");
1047     return;
1048   }
1049   ts = GST_BUFFER_TIMESTAMP (buffer);
1050   ts_end = ts + GST_BUFFER_DURATION (buffer);
1051
1052   iter =
1053       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1054       (monitor));
1055
1056   if (iter == NULL) {
1057     GST_WARNING_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor),
1058         "No iterator available");
1059     return;
1060   }
1061
1062   done = FALSE;
1063   while (!done) {
1064     GValue value = { 0, };
1065     switch (gst_iterator_next (iter, &value)) {
1066       case GST_ITERATOR_OK:
1067         otherpad = g_value_get_object (&value);
1068         GST_DEBUG_OBJECT (monitor->pad, "Checking pad %s:%s input timestamps",
1069             GST_DEBUG_PAD_NAME (otherpad));
1070         othermonitor =
1071             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1072         GST_VALIDATE_MONITOR_LOCK (othermonitor);
1073         if (gst_validate_pad_monitor_timestamp_is_in_received_range
1074             (othermonitor, ts, tolerance)
1075             &&
1076             gst_validate_pad_monitor_timestamp_is_in_received_range
1077             (othermonitor, ts_end, tolerance)) {
1078           done = TRUE;
1079           found = TRUE;
1080         }
1081         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1082         g_value_reset (&value);
1083         has_one = TRUE;
1084         break;
1085       case GST_ITERATOR_RESYNC:
1086         gst_iterator_resync (iter);
1087         has_one = FALSE;
1088         found = FALSE;
1089         break;
1090       case GST_ITERATOR_ERROR:
1091         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1092         done = TRUE;
1093         break;
1094       case GST_ITERATOR_DONE:
1095         done = TRUE;
1096         break;
1097     }
1098   }
1099   gst_iterator_free (iter);
1100
1101   if (!has_one) {
1102     GST_DEBUG_OBJECT (monitor->pad, "Skipping timestamp in range check as no "
1103         "internal linked pad was found");
1104     return;
1105   }
1106   if (!found) {
1107     GST_VALIDATE_REPORT (monitor, BUFFER_TIMESTAMP_OUT_OF_RECEIVED_RANGE,
1108         "Timestamp %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT
1109         " is out of range of received input", GST_TIME_ARGS (ts),
1110         GST_TIME_ARGS (ts_end));
1111   }
1112 }
1113
1114 static void
1115 gst_validate_pad_monitor_check_first_buffer (GstValidatePadMonitor *
1116     pad_monitor, GstBuffer * buffer)
1117 {
1118   if (G_UNLIKELY (pad_monitor->first_buffer)) {
1119     pad_monitor->first_buffer = FALSE;
1120
1121     if (!pad_monitor->has_segment
1122         && PAD_IS_IN_PUSH_MODE (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)))
1123     {
1124       GST_VALIDATE_REPORT (pad_monitor, BUFFER_BEFORE_SEGMENT,
1125           "Received buffer before Segment event");
1126     }
1127
1128     GST_DEBUG_OBJECT (pad_monitor->pad,
1129         "Checking first buffer (pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
1130         ")", GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
1131         GST_TIME_ARGS (GST_BUFFER_DTS (buffer)));
1132
1133   }
1134 }
1135
1136 static void
1137 gst_validate_pad_monitor_check_eos (GstValidatePadMonitor *
1138     pad_monitor, GstBuffer * buffer)
1139 {
1140   if (G_UNLIKELY (pad_monitor->is_eos)) {
1141     GST_VALIDATE_REPORT (pad_monitor, BUFFER_AFTER_EOS,
1142         "Received buffer %" GST_PTR_FORMAT " after EOS", buffer);
1143   }
1144 }
1145
1146 static void
1147 gst_validate_pad_monitor_update_buffer_data (GstValidatePadMonitor *
1148     pad_monitor, GstBuffer * buffer)
1149 {
1150   pad_monitor->current_timestamp = GST_BUFFER_TIMESTAMP (buffer);
1151   pad_monitor->current_duration = GST_BUFFER_DURATION (buffer);
1152   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
1153     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_start)) {
1154       pad_monitor->timestamp_range_start =
1155           MIN (pad_monitor->timestamp_range_start,
1156           GST_BUFFER_TIMESTAMP (buffer));
1157     } else {
1158       pad_monitor->timestamp_range_start = GST_BUFFER_TIMESTAMP (buffer);
1159     }
1160
1161     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
1162       GstClockTime endts =
1163           GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
1164       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_end)) {
1165         pad_monitor->timestamp_range_end =
1166             MAX (pad_monitor->timestamp_range_end, endts);
1167       } else {
1168         pad_monitor->timestamp_range_end = endts;
1169       }
1170     }
1171   }
1172   GST_DEBUG_OBJECT (pad_monitor->pad, "Current stored range: %" GST_TIME_FORMAT
1173       " - %" GST_TIME_FORMAT,
1174       GST_TIME_ARGS (pad_monitor->timestamp_range_start),
1175       GST_TIME_ARGS (pad_monitor->timestamp_range_end));
1176 }
1177
1178 static GstFlowReturn
1179 _combine_flows (GstFlowReturn ret1, GstFlowReturn ret2)
1180 {
1181   if (ret1 == ret2)
1182     return ret1;
1183   if (ret1 <= GST_FLOW_NOT_NEGOTIATED)
1184     return ret1;
1185   if (ret2 <= GST_FLOW_NOT_NEGOTIATED)
1186     return ret2;
1187   if (ret1 == GST_FLOW_FLUSHING || ret2 == GST_FLOW_FLUSHING)
1188     return GST_FLOW_FLUSHING;
1189   if (ret1 == GST_FLOW_OK || ret2 == GST_FLOW_OK)
1190     return GST_FLOW_OK;
1191   return ret2;
1192 }
1193
1194 static void
1195 gst_validate_pad_monitor_check_aggregated_return (GstValidatePadMonitor *
1196     monitor, GstFlowReturn ret)
1197 {
1198   GstIterator *iter;
1199   gboolean done;
1200   GstPad *otherpad;
1201   GstPad *peerpad;
1202   GstValidatePadMonitor *othermonitor;
1203   GstFlowReturn aggregated = GST_FLOW_NOT_LINKED;
1204   gboolean found_a_pad = FALSE;
1205   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
1206
1207   iter = gst_pad_iterate_internal_links (pad);
1208   done = FALSE;
1209   while (!done) {
1210     GValue value = { 0, };
1211     switch (gst_iterator_next (iter, &value)) {
1212       case GST_ITERATOR_OK:
1213         otherpad = g_value_get_object (&value);
1214         peerpad = gst_pad_get_peer (otherpad);
1215         if (peerpad) {
1216           othermonitor =
1217               g_object_get_data ((GObject *) peerpad, "validate-monitor");
1218           if (othermonitor) {
1219             found_a_pad = TRUE;
1220             GST_VALIDATE_MONITOR_LOCK (othermonitor);
1221             aggregated =
1222                 _combine_flows (aggregated, othermonitor->last_flow_return);
1223             GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1224           }
1225
1226           gst_object_unref (peerpad);
1227         }
1228         g_value_reset (&value);
1229         break;
1230       case GST_ITERATOR_RESYNC:
1231         gst_iterator_resync (iter);
1232         break;
1233       case GST_ITERATOR_ERROR:
1234         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1235         done = TRUE;
1236         break;
1237       case GST_ITERATOR_DONE:
1238         done = TRUE;
1239         break;
1240     }
1241   }
1242   gst_iterator_free (iter);
1243   if (!found_a_pad) {
1244     /* no peer pad found, nothing to do */
1245     return;
1246   }
1247   if (aggregated == GST_FLOW_OK || aggregated == GST_FLOW_EOS) {
1248     /* those are acceptable situations */
1249
1250     if (GST_PAD_IS_FLUSHING (pad) && ret == GST_FLOW_FLUSHING) {
1251       /* pad is flushing, always acceptable to return flushing */
1252       return;
1253     }
1254
1255     if (monitor->is_eos && ret == GST_FLOW_EOS) {
1256       /* this element received eos and returned eos */
1257       return;
1258     }
1259
1260     if (PAD_PARENT_IS_DEMUXER (monitor) && ret == GST_FLOW_EOS) {
1261       /* a demuxer can return EOS when the samples end */
1262       return;
1263     }
1264   }
1265
1266   if (aggregated != ret) {
1267     GST_VALIDATE_REPORT (monitor, WRONG_FLOW_RETURN,
1268         "Wrong combined flow return %s(%d). Expected: %s(%d)",
1269         gst_flow_get_name (ret), ret, gst_flow_get_name (aggregated),
1270         aggregated);
1271   }
1272 }
1273
1274 static void
1275     gst_validate_pad_monitor_otherpad_add_pending_serialized_event
1276     (GstValidatePadMonitor * monitor, GstEvent * event, GstClockTime last_ts)
1277 {
1278   GstIterator *iter;
1279   gboolean done;
1280   GstPad *otherpad;
1281   GstValidatePadMonitor *othermonitor;
1282
1283   if (!GST_EVENT_IS_SERIALIZED (event))
1284     return;
1285
1286   iter =
1287       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1288       (monitor));
1289   if (iter == NULL) {
1290     /* inputselector will return NULL if the sinkpad is not the active one .... */
1291     GST_FIXME_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD
1292         (monitor), "No iterator");
1293     return;
1294   }
1295   done = FALSE;
1296   while (!done) {
1297     GValue value = { 0, };
1298     switch (gst_iterator_next (iter, &value)) {
1299       case GST_ITERATOR_OK:
1300         otherpad = g_value_get_object (&value);
1301         othermonitor =
1302             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1303         if (othermonitor) {
1304           SerializedEventData *data = g_slice_new0 (SerializedEventData);
1305           data->timestamp = last_ts;
1306           data->event = gst_event_ref (event);
1307           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1308           GST_DEBUG_OBJECT (monitor->pad, "Storing for pad %s:%s event %p %s",
1309               GST_DEBUG_PAD_NAME (otherpad), event,
1310               GST_EVENT_TYPE_NAME (event));
1311           g_ptr_array_add (othermonitor->serialized_events, data);
1312           debug_pending_event (otherpad, othermonitor->serialized_events);
1313           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1314         }
1315         g_value_reset (&value);
1316         break;
1317       case GST_ITERATOR_RESYNC:
1318         gst_iterator_resync (iter);
1319         break;
1320       case GST_ITERATOR_ERROR:
1321         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1322         done = TRUE;
1323         break;
1324       case GST_ITERATOR_DONE:
1325         done = TRUE;
1326         break;
1327     }
1328   }
1329   gst_iterator_free (iter);
1330 }
1331
1332 static void
1333 gst_validate_pad_monitor_otherpad_add_pending_field (GstValidatePadMonitor *
1334     monitor, GstStructure * structure, const gchar * field)
1335 {
1336   GstIterator *iter;
1337   gboolean done;
1338   GstPad *otherpad;
1339   GstValidatePadMonitor *othermonitor;
1340   const GValue *v;
1341
1342   v = gst_structure_get_value (structure, field);
1343   if (v == NULL) {
1344     GST_DEBUG_OBJECT (monitor->pad, "Not adding pending field %s as it isn't "
1345         "present on structure %" GST_PTR_FORMAT, field, structure);
1346     return;
1347   }
1348
1349   iter =
1350       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1351       (monitor));
1352   done = FALSE;
1353   while (!done) {
1354     GValue value = { 0, };
1355     switch (gst_iterator_next (iter, &value)) {
1356       case GST_ITERATOR_OK:
1357         otherpad = g_value_get_object (&value);
1358         othermonitor =
1359             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1360         if (othermonitor) {
1361           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1362           g_assert (othermonitor->pending_setcaps_fields != NULL);
1363           gst_structure_set_value (othermonitor->pending_setcaps_fields,
1364               field, v);
1365           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1366         }
1367         g_value_reset (&value);
1368         break;
1369       case GST_ITERATOR_RESYNC:
1370         gst_iterator_resync (iter);
1371         break;
1372       case GST_ITERATOR_ERROR:
1373         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1374         done = TRUE;
1375         break;
1376       case GST_ITERATOR_DONE:
1377         done = TRUE;
1378         break;
1379     }
1380   }
1381   gst_iterator_free (iter);
1382 }
1383
1384 static void
1385 gst_validate_pad_monitor_otherpad_clear_pending_fields (GstValidatePadMonitor *
1386     monitor)
1387 {
1388   GstIterator *iter;
1389   gboolean done;
1390   GstPad *otherpad;
1391   GstValidatePadMonitor *othermonitor;
1392
1393   iter =
1394       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1395       (monitor));
1396
1397   if (iter == NULL) {
1398     GST_DEBUG_OBJECT (monitor, "No internally linked pad");
1399
1400     return;
1401   }
1402
1403   done = FALSE;
1404   while (!done) {
1405     GValue value = { 0, };
1406     switch (gst_iterator_next (iter, &value)) {
1407       case GST_ITERATOR_OK:
1408         otherpad = g_value_get_object (&value);
1409         othermonitor =
1410             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1411         if (othermonitor) {
1412           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1413           g_assert (othermonitor->pending_setcaps_fields != NULL);
1414           gst_structure_free (othermonitor->pending_setcaps_fields);
1415           othermonitor->pending_setcaps_fields =
1416               gst_structure_new_empty (PENDING_FIELDS);
1417           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1418         }
1419         g_value_reset (&value);
1420         break;
1421       case GST_ITERATOR_RESYNC:
1422         gst_iterator_resync (iter);
1423         break;
1424       case GST_ITERATOR_ERROR:
1425         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1426         done = TRUE;
1427         break;
1428       case GST_ITERATOR_DONE:
1429         done = TRUE;
1430         break;
1431     }
1432   }
1433   gst_iterator_free (iter);
1434 }
1435
1436 static void
1437 gst_validate_pad_monitor_add_expected_newsegment (GstValidatePadMonitor *
1438     monitor, GstEvent * event)
1439 {
1440   GstIterator *iter;
1441   gboolean done;
1442   GstPad *otherpad;
1443   GstValidatePadMonitor *othermonitor;
1444
1445   iter =
1446       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1447       (monitor));
1448
1449   if (iter == NULL) {
1450     GST_DEBUG_OBJECT (monitor, "No internally linked pad");
1451     return;
1452   }
1453
1454   done = FALSE;
1455   while (!done) {
1456     GValue value = { 0, };
1457     switch (gst_iterator_next (iter, &value)) {
1458       case GST_ITERATOR_OK:
1459         otherpad = g_value_get_object (&value);
1460         if (!otherpad)
1461           continue;
1462         othermonitor =
1463             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1464         GST_VALIDATE_MONITOR_LOCK (othermonitor);
1465         gst_event_replace (&othermonitor->expected_segment, event);
1466         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1467         g_value_reset (&value);
1468         break;
1469       case GST_ITERATOR_RESYNC:
1470         gst_iterator_resync (iter);
1471         break;
1472       case GST_ITERATOR_ERROR:
1473         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1474         done = TRUE;
1475         break;
1476       case GST_ITERATOR_DONE:
1477         done = TRUE;
1478         break;
1479     }
1480   }
1481   gst_iterator_free (iter);
1482 }
1483
1484 static void
1485 gst_validate_pad_monitor_flush (GstValidatePadMonitor * pad_monitor)
1486 {
1487   pad_monitor->current_timestamp = GST_CLOCK_TIME_NONE;
1488   pad_monitor->current_duration = GST_CLOCK_TIME_NONE;
1489   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
1490   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
1491   pad_monitor->has_segment = FALSE;
1492   pad_monitor->is_eos = FALSE;
1493   pad_monitor->last_flow_return = GST_FLOW_OK;
1494   gst_caps_replace (&pad_monitor->last_caps, NULL);
1495   pad_monitor->caps_is_audio = pad_monitor->caps_is_video =
1496       pad_monitor->caps_is_raw = FALSE;
1497
1498   g_list_free_full (pad_monitor->expired_events,
1499       (GDestroyNotify) gst_event_unref);
1500   pad_monitor->expired_events = NULL;
1501
1502   if (pad_monitor->serialized_events->len)
1503     g_ptr_array_remove_range (pad_monitor->serialized_events, 0,
1504         pad_monitor->serialized_events->len);
1505 }
1506
1507 /* common checks for both sink and src event functions */
1508 static void
1509 gst_validate_pad_monitor_common_event_check (GstValidatePadMonitor *
1510     pad_monitor, GstEvent * event)
1511 {
1512   guint32 seqnum = gst_event_get_seqnum (event);
1513
1514   switch (GST_EVENT_TYPE (event)) {
1515     case GST_EVENT_FLUSH_START:
1516     {
1517       if (pad_monitor->pending_flush_start_seqnum) {
1518         if (seqnum == pad_monitor->pending_flush_start_seqnum) {
1519           pad_monitor->pending_flush_start_seqnum = 0;
1520         } else {
1521           GST_VALIDATE_REPORT (pad_monitor, FLUSH_START_HAS_WRONG_SEQNUM,
1522               "Got: %u Expected: %u", seqnum,
1523               pad_monitor->pending_flush_start_seqnum);
1524         }
1525       }
1526
1527       if (pad_monitor->pending_flush_stop) {
1528         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_START_UNEXPECTED,
1529             "Received flush-start from " " when flush-stop was expected");
1530       }
1531       pad_monitor->pending_flush_stop = TRUE;
1532     }
1533       break;
1534     case GST_EVENT_FLUSH_STOP:
1535     {
1536       if (pad_monitor->pending_flush_stop_seqnum) {
1537         if (seqnum == pad_monitor->pending_flush_stop_seqnum) {
1538           pad_monitor->pending_flush_stop_seqnum = 0;
1539         } else {
1540           GST_VALIDATE_REPORT (pad_monitor, FLUSH_STOP_HAS_WRONG_SEQNUM,
1541               "Got: %u Expected: %u", seqnum,
1542               pad_monitor->pending_flush_stop_seqnum);
1543         }
1544       }
1545
1546       pad_monitor->pending_newsegment_seqnum = seqnum;
1547       pad_monitor->pending_eos_seqnum = seqnum;
1548
1549       if (!pad_monitor->pending_flush_stop) {
1550         gchar *event_str = _get_event_string (event);
1551
1552         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_STOP_UNEXPECTED,
1553             "Unexpected flush-stop %s", event_str);
1554         g_free (event_str);
1555       }
1556       pad_monitor->pending_flush_stop = FALSE;
1557
1558       /* cleanup our data */
1559       gst_validate_pad_monitor_flush (pad_monitor);
1560     }
1561       break;
1562     default:
1563       break;
1564   }
1565 }
1566
1567 static void
1568 mark_pads_eos (GstValidatePadMonitor * pad_monitor)
1569 {
1570   GstValidatePadMonitor *peer_monitor;
1571   GstPad *peer = gst_pad_get_peer (pad_monitor->pad);
1572   GstPad *real_peer;
1573
1574   pad_monitor->is_eos = TRUE;
1575   if (peer) {
1576     real_peer = _get_actual_pad (peer);
1577     peer_monitor =
1578         g_object_get_data ((GObject *) real_peer, "validate-monitor");
1579     if (peer_monitor)
1580       peer_monitor->is_eos = TRUE;
1581     gst_object_unref (peer);
1582     gst_object_unref (real_peer);
1583   }
1584 }
1585
1586 static inline gboolean
1587 _should_check_buffers (GstValidatePadMonitor * pad_monitor,
1588     gboolean force_checks)
1589 {
1590   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1591   GstValidateMonitor *monitor = GST_VALIDATE_MONITOR (pad_monitor);
1592
1593   if (pad_monitor->first_buffer || force_checks) {
1594     if (pad_monitor->segment.rate != 1.0) {
1595       GST_INFO_OBJECT (pad_monitor, "We do not support buffer checking"
1596           " for trick modes");
1597
1598       pad_monitor->check_buffers = FALSE;
1599     } else if (!PAD_PARENT_IS_DECODER (pad_monitor)) {
1600       GST_DEBUG_OBJECT (pad, "Not on a decoder => no buffer checking");
1601
1602       pad_monitor->check_buffers = FALSE;
1603     } else if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK) {
1604       GST_DEBUG_OBJECT (pad, "Not a sinkpad => no buffer checking");
1605
1606       pad_monitor->check_buffers = FALSE;
1607     } else if (!pad_monitor->caps_is_video) {
1608       GST_DEBUG_OBJECT (pad, "Not working with video => no buffer checking");
1609
1610       pad_monitor->check_buffers = FALSE;
1611     } else if (monitor->media_descriptor == NULL) {
1612       GST_DEBUG_OBJECT (pad, "No media_descriptor set => no buffer checking");
1613
1614       pad_monitor->check_buffers = FALSE;
1615     } else if (!gst_media_descriptor_detects_frames (monitor->media_descriptor)) {
1616       GST_DEBUG_OBJECT (pad, "No frame detection media descriptor "
1617           "=> not buffer checking");
1618       pad_monitor->check_buffers = FALSE;
1619     } else if (pad_monitor->all_bufs == NULL &&
1620         !gst_media_descriptor_get_buffers (monitor->media_descriptor, pad, NULL,
1621             &pad_monitor->all_bufs)) {
1622
1623       GST_INFO_OBJECT (monitor,
1624           "The MediaInfo is marked as detecting frame, but getting frames"
1625           " from pad %" GST_PTR_FORMAT " did not work (some format conversion"
1626           " might be happening)", pad);
1627
1628       pad_monitor->check_buffers = FALSE;
1629     } else {
1630       if (!pad_monitor->current_buf)
1631         pad_monitor->current_buf = pad_monitor->all_bufs;
1632       pad_monitor->check_buffers = TRUE;
1633     }
1634   }
1635
1636   return pad_monitor->check_buffers;
1637 }
1638
1639 static void
1640 gst_validate_monitor_find_next_buffer (GstValidatePadMonitor * pad_monitor)
1641 {
1642   GList *tmp;
1643   gboolean passed_start = FALSE;
1644
1645   if (!_should_check_buffers (pad_monitor, TRUE))
1646     return;
1647
1648   for (tmp = g_list_last (pad_monitor->all_bufs); tmp; tmp = tmp->prev) {
1649     GstBuffer *cbuf = tmp->data;
1650     GstClockTime ts =
1651         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (cbuf)) ? GST_BUFFER_DTS (cbuf)
1652         : GST_BUFFER_PTS (cbuf);
1653
1654     if (!GST_CLOCK_TIME_IS_VALID (ts))
1655       continue;
1656
1657     if (ts <= pad_monitor->segment.start)
1658       passed_start = TRUE;
1659
1660     if (!passed_start)
1661       continue;
1662
1663     if (!GST_BUFFER_FLAG_IS_SET (cbuf, GST_BUFFER_FLAG_DELTA_UNIT)) {
1664       break;
1665     }
1666   }
1667
1668   if (tmp == NULL)
1669     pad_monitor->current_buf = pad_monitor->all_bufs;
1670   else
1671     pad_monitor->current_buf = tmp;
1672 }
1673
1674 static gboolean
1675 gst_validate_pad_monitor_downstream_event_check (GstValidatePadMonitor *
1676     pad_monitor, GstObject * parent, GstEvent * event,
1677     GstPadEventFunction handler)
1678 {
1679   gboolean ret = TRUE;
1680   const GstSegment *segment;
1681   guint32 seqnum = gst_event_get_seqnum (event);
1682   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1683
1684   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1685
1686   /* pre checks */
1687   switch (GST_EVENT_TYPE (event)) {
1688     case GST_EVENT_SEGMENT:
1689       /* parse segment data to be used if event is handled */
1690       gst_event_parse_segment (event, &segment);
1691
1692       GST_DEBUG_OBJECT (pad_monitor->pad, "Got segment %" GST_SEGMENT_FORMAT,
1693           segment);
1694
1695       if (pad_monitor->pending_newsegment_seqnum) {
1696         if (pad_monitor->pending_newsegment_seqnum == seqnum) {
1697           pad_monitor->pending_newsegment_seqnum = 0;
1698         } else {
1699           GST_VALIDATE_REPORT (pad_monitor, SEGMENT_HAS_WRONG_SEQNUM,
1700               "Got: %u Expected: %u", seqnum, pad_monitor->pending_eos_seqnum);
1701         }
1702       }
1703
1704       pad_monitor->pending_eos_seqnum = seqnum;
1705
1706       if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1707         gst_validate_pad_monitor_add_expected_newsegment (pad_monitor, event);
1708       } else {
1709         /* check if this segment is the expected one */
1710         if (pad_monitor->expected_segment) {
1711           const GstSegment *exp_segment;
1712
1713           if (pad_monitor->expected_segment != event) {
1714             gst_event_parse_segment (pad_monitor->expected_segment,
1715                 &exp_segment);
1716             if (segment->format == exp_segment->format) {
1717               if ((exp_segment->rate * exp_segment->applied_rate !=
1718                       segment->rate * segment->applied_rate))
1719                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1720                     "Rate * applied_rate %d != expected %d",
1721                     segment->rate * segment->applied_rate,
1722                     exp_segment->rate * exp_segment->applied_rate);
1723               if (exp_segment->start != segment->start)
1724                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1725                     "Start %" GST_TIME_FORMAT " != expected %" GST_TIME_FORMAT,
1726                     GST_TIME_ARGS (segment->start),
1727                     GST_TIME_ARGS (exp_segment->start));
1728               if (exp_segment->stop != segment->stop)
1729                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1730                     "Stop %" GST_TIME_FORMAT " != expected %" GST_TIME_FORMAT,
1731                     GST_TIME_ARGS (segment->stop),
1732                     GST_TIME_ARGS (exp_segment->stop));
1733               if (exp_segment->position != segment->position)
1734                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1735                     "Position %" GST_TIME_FORMAT " != expected %"
1736                     GST_TIME_FORMAT, GST_TIME_ARGS (segment->position),
1737                     GST_TIME_ARGS (exp_segment->position));
1738             }
1739           }
1740           gst_event_replace (&pad_monitor->expected_segment, NULL);
1741         }
1742       }
1743       break;
1744     case GST_EVENT_CAPS:{
1745       GstCaps *caps;
1746
1747       gst_event_parse_caps (event, &caps);
1748       gst_validate_pad_monitor_setcaps_pre (pad_monitor, caps);
1749       break;
1750     }
1751     case GST_EVENT_EOS:
1752       pad_monitor->is_eos = TRUE;
1753       if (pad_monitor->pending_eos_seqnum == 0) {
1754         GST_VALIDATE_REPORT (pad_monitor, EVENT_EOS_WITHOUT_SEGMENT,
1755             "EOS %" GST_PTR_FORMAT " received before a segment was received",
1756             event);
1757       } else if (pad_monitor->pending_eos_seqnum != seqnum) {
1758         GST_VALIDATE_REPORT (pad_monitor, EOS_HAS_WRONG_SEQNUM,
1759             "Got: %u. Expected: %u", seqnum, pad_monitor->pending_eos_seqnum);
1760       }
1761
1762       /*
1763        * TODO add end of stream checks for
1764        *  - events not pushed
1765        *  - buffer data not pushed
1766        *  - pending events not received
1767        */
1768       break;
1769
1770       /* both flushes are handled by the common event function */
1771     case GST_EVENT_FLUSH_START:
1772     case GST_EVENT_FLUSH_STOP:
1773     case GST_EVENT_TAG:
1774     case GST_EVENT_SINK_MESSAGE:
1775     default:
1776       break;
1777   }
1778
1779   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1780   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1781   gst_validate_pad_monitor_event_overrides (pad_monitor, event);
1782   if (handler) {
1783     gst_event_ref (event);
1784     ret = pad_monitor->event_func (pad, parent, event);
1785   }
1786   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1787   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1788
1789   /* post checks */
1790   switch (GST_EVENT_TYPE (event)) {
1791     case GST_EVENT_SEGMENT:
1792       if (ret) {
1793         if (!pad_monitor->has_segment
1794             && pad_monitor->segment.format != segment->format) {
1795           gst_segment_init (&pad_monitor->segment, segment->format);
1796         }
1797         gst_segment_copy_into (segment, &pad_monitor->segment);
1798         pad_monitor->has_segment = TRUE;
1799         gst_validate_monitor_find_next_buffer (pad_monitor);
1800       }
1801       break;
1802     case GST_EVENT_CAPS:{
1803       GstCaps *caps;
1804
1805       gst_event_parse_caps (event, &caps);
1806       gst_validate_pad_monitor_setcaps_post (pad_monitor, caps, ret);
1807       break;
1808     }
1809     case GST_EVENT_FLUSH_START:
1810     case GST_EVENT_FLUSH_STOP:
1811     case GST_EVENT_EOS:
1812     case GST_EVENT_TAG:
1813     case GST_EVENT_SINK_MESSAGE:
1814     default:
1815       break;
1816   }
1817
1818   if (handler)
1819     gst_event_unref (event);
1820   return ret;
1821 }
1822
1823 static gboolean
1824 gst_validate_pad_monitor_src_event_check (GstValidatePadMonitor * pad_monitor,
1825     GstObject * parent, GstEvent * event, GstPadEventFunction handler)
1826 {
1827   gboolean ret = TRUE;
1828   gdouble rate;
1829   GstFormat format;
1830   gint64 start, stop;
1831   GstSeekFlags seek_flags;
1832   GstSeekType start_type, stop_type;
1833   guint32 seqnum = gst_event_get_seqnum (event);
1834   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1835
1836   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1837
1838   /* pre checks */
1839   switch (GST_EVENT_TYPE (event)) {
1840     case GST_EVENT_SEEK:
1841     {
1842       gst_event_parse_seek (event, &rate, &format, &seek_flags, &start_type,
1843           &start, &stop_type, &stop);
1844       /* upstream seek - store the seek event seqnum to check
1845        * flushes and newsegments share the same */
1846
1847       /* TODO we might need to use a list as multiple seeks can be sent
1848        * before the flushes arrive here */
1849       if (seek_flags & GST_SEEK_FLAG_FLUSH) {
1850         pad_monitor->pending_flush_start_seqnum = seqnum;
1851         pad_monitor->pending_flush_stop_seqnum = seqnum;
1852       }
1853     }
1854       break;
1855       /* both flushes are handled by the common event handling function */
1856     case GST_EVENT_FLUSH_START:
1857     case GST_EVENT_FLUSH_STOP:
1858     case GST_EVENT_NAVIGATION:
1859     case GST_EVENT_LATENCY:
1860     case GST_EVENT_STEP:
1861     case GST_EVENT_QOS:
1862     default:
1863       break;
1864   }
1865
1866   if (handler) {
1867     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1868     gst_event_ref (event);
1869     ret = pad_monitor->event_func (pad, parent, event);
1870     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1871   }
1872
1873   /* post checks */
1874   switch (GST_EVENT_TYPE (event)) {
1875     case GST_EVENT_FLUSH_START:
1876     case GST_EVENT_FLUSH_STOP:
1877     case GST_EVENT_QOS:
1878     case GST_EVENT_SEEK:
1879     {
1880       if (ret == FALSE) {
1881         /* do not expect any of these events anymore */
1882         pad_monitor->pending_flush_start_seqnum = 0;
1883         pad_monitor->pending_flush_stop_seqnum = 0;
1884         pad_monitor->pending_newsegment_seqnum = 0;
1885         pad_monitor->pending_eos_seqnum = 0;
1886       }
1887     }
1888       break;
1889     case GST_EVENT_NAVIGATION:
1890     case GST_EVENT_LATENCY:
1891     case GST_EVENT_STEP:
1892     default:
1893       break;
1894   }
1895
1896   if (handler)
1897     gst_event_unref (event);
1898   return ret;
1899 }
1900
1901 static gboolean
1902 gst_validate_pad_monitor_check_right_buffer (GstValidatePadMonitor *
1903     pad_monitor, GstBuffer * buffer)
1904 {
1905   gchar *checksum;
1906   GstBuffer *wanted_buf;
1907   GstMapInfo map, wanted_map;
1908
1909   gboolean ret = TRUE;
1910   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1911
1912   if (_should_check_buffers (pad_monitor, FALSE) == FALSE)
1913     return FALSE;
1914
1915   if (pad_monitor->current_buf == NULL) {
1916     GST_INFO_OBJECT (pad, "No current buffer one pad, Why?");
1917     return FALSE;
1918   }
1919
1920   wanted_buf = pad_monitor->current_buf->data;
1921
1922   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (wanted_buf)) &&
1923       GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer)) &&
1924       GST_BUFFER_PTS (wanted_buf) != GST_BUFFER_PTS (buffer)) {
1925
1926     GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER,
1927         "buffer %" GST_PTR_FORMAT " PTS %ld"
1928         " different than expected: %ld", buffer,
1929         GST_BUFFER_PTS (buffer), GST_BUFFER_PTS (wanted_buf));
1930
1931     ret = FALSE;
1932   }
1933
1934   if (GST_BUFFER_DTS (wanted_buf) != GST_BUFFER_DTS (buffer)) {
1935     GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER,
1936         "buffer %" GST_PTR_FORMAT " DTS %" GST_TIME_FORMAT
1937         " different than expected: %" GST_TIME_FORMAT, buffer,
1938         GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
1939         GST_TIME_ARGS (GST_BUFFER_DTS (wanted_buf)));
1940     ret = FALSE;
1941   }
1942
1943   if (GST_BUFFER_DURATION (wanted_buf) != GST_BUFFER_DURATION (buffer)) {
1944     GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER,
1945         "buffer %" GST_PTR_FORMAT " DURATION %" GST_TIME_FORMAT
1946         " different than expected: %" GST_TIME_FORMAT, buffer,
1947         GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
1948         GST_TIME_ARGS (GST_BUFFER_DURATION (wanted_buf)));
1949     ret = FALSE;
1950   }
1951
1952   if (GST_BUFFER_FLAG_IS_SET (wanted_buf, GST_BUFFER_FLAG_DELTA_UNIT) !=
1953       GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
1954     GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER,
1955         "buffer %" GST_PTR_FORMAT "  Delta unit is set to %s but expected %s",
1956         buffer, GST_BUFFER_FLAG_IS_SET (buffer,
1957             GST_BUFFER_FLAG_DELTA_UNIT) ? "True" : "False",
1958         GST_BUFFER_FLAG_IS_SET (wanted_buf,
1959             GST_BUFFER_FLAG_DELTA_UNIT) ? "True" : "False");
1960     ret = FALSE;
1961   }
1962
1963   g_assert (gst_buffer_map (wanted_buf, &wanted_map, GST_MAP_READ));
1964   g_assert (gst_buffer_map (buffer, &map, GST_MAP_READ));
1965
1966   checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5,
1967       (const guchar *) map.data, map.size);
1968
1969   if (g_strcmp0 ((gchar *) wanted_map.data, checksum)) {
1970     GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER,
1971         "buffer %" GST_PTR_FORMAT " checksum %s different from expected: %s",
1972         buffer, checksum, wanted_map.data);
1973     ret = FALSE;
1974   }
1975
1976   gst_buffer_unmap (wanted_buf, &wanted_map);
1977   gst_buffer_unmap (buffer, &map);
1978   g_free (checksum);
1979
1980   pad_monitor->current_buf = pad_monitor->current_buf->next;
1981
1982   return ret;
1983 }
1984
1985 static GstFlowReturn
1986 gst_validate_pad_monitor_chain_func (GstPad * pad, GstObject * parent,
1987     GstBuffer * buffer)
1988 {
1989   GstValidatePadMonitor *pad_monitor =
1990       g_object_get_data ((GObject *) pad, "validate-monitor");
1991   GstFlowReturn ret;
1992
1993   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1994   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1995
1996   gst_validate_pad_monitor_check_right_buffer (pad_monitor, buffer);
1997   gst_validate_pad_monitor_check_first_buffer (pad_monitor, buffer);
1998   gst_validate_pad_monitor_update_buffer_data (pad_monitor, buffer);
1999   gst_validate_pad_monitor_check_eos (pad_monitor, buffer);
2000
2001   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
2002   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
2003
2004   gst_validate_pad_monitor_buffer_overrides (pad_monitor, buffer);
2005
2006   ret = pad_monitor->chain_func (pad, parent, buffer);
2007
2008   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
2009   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
2010
2011   pad_monitor->last_flow_return = ret;
2012   if (ret == GST_FLOW_EOS) {
2013     mark_pads_eos (pad_monitor);
2014   }
2015   if (PAD_PARENT_IS_DEMUXER (pad_monitor))
2016     gst_validate_pad_monitor_check_aggregated_return (pad_monitor, ret);
2017
2018   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
2019   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
2020
2021   return ret;
2022 }
2023
2024 static gboolean
2025 gst_validate_pad_monitor_event_is_tracked (GstValidatePadMonitor * monitor,
2026     GstEvent * event)
2027 {
2028   if (!GST_EVENT_IS_SERIALIZED (event)) {
2029     return FALSE;
2030   }
2031
2032   /* we don't track Tag events because they mutate too much and it is hard
2033    * to match a tag event pushed on a source pad with the one that was received
2034    * on a sink pad.
2035    * One idea would be to use seqnum, but it seems that it is undefined whether
2036    * seqnums should be maintained in tag events that are created from others
2037    * up to today. (2013-08-29)
2038    */
2039   if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
2040     return FALSE;
2041
2042   return TRUE;
2043 }
2044
2045 static gboolean
2046 gst_validate_pad_monitor_sink_event_func (GstPad * pad, GstObject * parent,
2047     GstEvent * event)
2048 {
2049   GstValidatePadMonitor *pad_monitor =
2050       g_object_get_data ((GObject *) pad, "validate-monitor");
2051   gboolean ret;
2052
2053   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
2054   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
2055
2056   if (gst_validate_pad_monitor_event_is_tracked (pad_monitor, event)) {
2057     GstClockTime last_ts = GST_CLOCK_TIME_NONE;
2058     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_timestamp)) {
2059       last_ts = pad_monitor->current_timestamp;
2060       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_duration)) {
2061         last_ts += pad_monitor->current_duration;
2062       }
2063     }
2064     gst_validate_pad_monitor_otherpad_add_pending_serialized_event (pad_monitor,
2065         event, last_ts);
2066   }
2067
2068   ret =
2069       gst_validate_pad_monitor_downstream_event_check (pad_monitor, parent,
2070       event, pad_monitor->event_func);
2071
2072   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
2073   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
2074   return ret;
2075 }
2076
2077 static gboolean
2078 gst_validate_pad_monitor_src_event_func (GstPad * pad, GstObject * parent,
2079     GstEvent * event)
2080 {
2081   GstValidatePadMonitor *pad_monitor =
2082       g_object_get_data ((GObject *) pad, "validate-monitor");
2083   gboolean ret;
2084
2085   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
2086   ret = gst_validate_pad_monitor_src_event_check (pad_monitor, parent, event,
2087       pad_monitor->event_func);
2088   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
2089   return ret;
2090 }
2091
2092 static gboolean
2093 gst_validate_pad_monitor_query_func (GstPad * pad, GstObject * parent,
2094     GstQuery * query)
2095 {
2096   GstValidatePadMonitor *pad_monitor =
2097       g_object_get_data ((GObject *) pad, "validate-monitor");
2098   gboolean ret;
2099
2100   gst_validate_pad_monitor_query_overrides (pad_monitor, query);
2101
2102   ret = pad_monitor->query_func (pad, parent, query);
2103
2104   if (ret) {
2105     switch (GST_QUERY_TYPE (query)) {
2106       case GST_QUERY_CAPS:{
2107         GstCaps *res;
2108         GstCaps *filter;
2109
2110         /* We shouldn't need to lock the parent as this doesn't modify
2111          * other monitors, just does some peer_pad_caps */
2112         GST_VALIDATE_MONITOR_LOCK (pad_monitor);
2113
2114         gst_query_parse_caps (query, &filter);
2115         gst_query_parse_caps_result (query, &res);
2116         if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
2117           gst_validate_pad_monitor_check_caps_fields_proxied (pad_monitor, res,
2118               filter);
2119         }
2120         GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
2121         break;
2122       }
2123       default:
2124         break;
2125     }
2126   }
2127
2128   return ret;
2129 }
2130
2131 static gboolean
2132 gst_validate_pad_monitor_activatemode_func (GstPad * pad, GstObject * parent,
2133     GstPadMode mode, gboolean active)
2134 {
2135   GstValidatePadMonitor *pad_monitor =
2136       g_object_get_data ((GObject *) pad, "validate-monitor");
2137   gboolean ret = TRUE;
2138
2139   /* TODO add overrides for activate func */
2140
2141   if (pad_monitor->activatemode_func)
2142     ret = pad_monitor->activatemode_func (pad, parent, mode, active);
2143   if (ret && active == FALSE) {
2144     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
2145     gst_validate_pad_monitor_flush (pad_monitor);
2146     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
2147   }
2148
2149   return ret;
2150 }
2151
2152 static gboolean
2153 gst_validate_pad_get_range_func (GstPad * pad, GstObject * parent,
2154     guint64 offset, guint size, GstBuffer ** buffer)
2155 {
2156   GstValidatePadMonitor *pad_monitor =
2157       g_object_get_data ((GObject *) pad, "validate-monitor");
2158   gboolean ret;
2159   ret = pad_monitor->getrange_func (pad, parent, offset, size, buffer);
2160   return ret;
2161 }
2162
2163 static gboolean
2164 gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
2165     gpointer udata)
2166 {
2167   GstValidatePadMonitor *monitor = udata;
2168
2169   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
2170   GST_VALIDATE_MONITOR_LOCK (monitor);
2171
2172   gst_validate_pad_monitor_check_first_buffer (monitor, buffer);
2173   gst_validate_pad_monitor_update_buffer_data (monitor, buffer);
2174   gst_validate_pad_monitor_check_eos (monitor, buffer);
2175
2176   if (PAD_PARENT_IS_DECODER (monitor) || PAD_PARENT_IS_ENCODER (monitor)) {
2177     GstClockTime tolerance = 0;
2178
2179     if (monitor->caps_is_audio)
2180       tolerance = AUDIO_TIMESTAMP_TOLERANCE;
2181
2182     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range (monitor,
2183         buffer, tolerance);
2184   }
2185
2186   gst_validate_pad_monitor_check_late_serialized_events (monitor,
2187       GST_BUFFER_TIMESTAMP (buffer));
2188
2189   /* a GstValidatePadMonitor parent must be a GstValidateElementMonitor */
2190   if (PAD_PARENT_IS_DECODER (monitor)) {
2191
2192     /* should not push out of segment data */
2193     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)) &&
2194         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)) &&
2195         ((!gst_segment_clip (&monitor->segment, monitor->segment.format,
2196                     GST_BUFFER_TIMESTAMP (buffer),
2197                     GST_BUFFER_TIMESTAMP (buffer) +
2198                     GST_BUFFER_DURATION (buffer), NULL, NULL)) ||
2199             /* In the case of raw data, buffers should be strictly contained inside the
2200              * segment */
2201             (monitor->caps_is_raw &&
2202                 GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer) <
2203                 monitor->segment.start))
2204         ) {
2205       /* TODO is this a timestamp issue? */
2206       GST_VALIDATE_REPORT (monitor, BUFFER_IS_OUT_OF_SEGMENT,
2207           "buffer is out of segment and shouldn't be pushed. Timestamp: %"
2208           GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT ". Range: %"
2209           GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2210           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
2211           GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
2212           GST_TIME_ARGS (monitor->segment.start),
2213           GST_TIME_ARGS (monitor->segment.stop));
2214     }
2215   }
2216
2217   GST_VALIDATE_MONITOR_UNLOCK (monitor);
2218   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
2219   gst_validate_pad_monitor_buffer_probe_overrides (monitor, buffer);
2220   return TRUE;
2221 }
2222
2223 static gboolean
2224 gst_validate_pad_monitor_event_probe (GstPad * pad, GstEvent * event,
2225     gpointer udata)
2226 {
2227   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (udata);
2228   gboolean ret;
2229
2230   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
2231   GST_VALIDATE_MONITOR_LOCK (monitor);
2232
2233   GST_DEBUG_OBJECT (pad, "event %p %s", event, GST_EVENT_TYPE_NAME (event));
2234
2235   if (GST_EVENT_IS_SERIALIZED (event)) {
2236     gint i;
2237
2238     /* Detect if events the element received are being forwarded in the same order
2239      *
2240      * Several scenarios:
2241      * 1) The element pushes the event as-is
2242      * 2) The element consumes the event and does not forward it
2243      * 3) The element consumes the event and creates another one instead
2244      * 4) The element pushes other serialized event before pushing out the
2245      *    one it received
2246      *
2247      * For each pad we have two lists to track serialized events:
2248      *  1) We received on input and expect to see (serialized_events)
2249      *  2) We received on input but don't expect to see (expired_events)
2250      *
2251      * To detect events that are pushed in a different order from the one they were
2252      * received in we check that:
2253      *
2254      * For each event being outputted:
2255      *   If it is in the expired_events list:
2256      *     RAISE WARNING
2257      *   If it is in the serialized_events list:
2258      *     If there are other events that were received before:
2259      *        Put those events on the expired_events list
2260      *     Remove that event and any previous ones from the serialized_events list
2261      *
2262      * Clear expired events list when flushing or on pad deactivation
2263      *
2264      */
2265
2266     if (g_list_find (monitor->expired_events, event)) {
2267       gchar *event_str = _get_event_string (event);
2268       /* If it's the expired events, we've failed */
2269       GST_WARNING_OBJECT (pad, "Did not expect event %p %s", event,
2270           GST_EVENT_TYPE_NAME (event));
2271       GST_VALIDATE_REPORT (monitor, EVENT_SERIALIZED_OUT_OF_ORDER,
2272           "Serialized event was pushed out of order: %s", event_str);
2273
2274       g_free (event_str);
2275       monitor->expired_events = g_list_remove (monitor->expired_events, event);
2276       gst_event_unref (event);  /* remove the ref that was on the list */
2277     } else if (monitor->serialized_events->len) {
2278       for (i = 0; i < monitor->serialized_events->len; i++) {
2279         SerializedEventData *next_event =
2280             g_ptr_array_index (monitor->serialized_events, i);
2281         GST_DEBUG_OBJECT (pad, "Checking against stored event #%d: %p %s", i,
2282             next_event->event, GST_EVENT_TYPE_NAME (next_event->event));
2283
2284         if (event == next_event->event
2285             || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
2286           /* We have found our event */
2287           GST_DEBUG_OBJECT (pad, "Found matching event");
2288
2289           while (monitor->serialized_events->len > i
2290               && GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
2291             /* Swallow all expected events of the same type */
2292             g_ptr_array_remove_index (monitor->serialized_events, i);
2293             next_event = g_ptr_array_index (monitor->serialized_events, i);
2294           }
2295
2296           /* Move all previous events to expired events */
2297           if (G_UNLIKELY (i > 0)) {
2298             GST_DEBUG_OBJECT (pad,
2299                 "Moving previous expected events to expired list");
2300             while (i--) {
2301               next_event = g_ptr_array_index (monitor->serialized_events, 0);
2302               monitor->expired_events =
2303                   g_list_append (monitor->expired_events,
2304                   gst_event_ref (next_event->event));
2305               g_ptr_array_remove_index (monitor->serialized_events, 0);
2306             }
2307           }
2308           debug_pending_event (pad, monitor->serialized_events);
2309           break;
2310         }
2311       }
2312     }
2313   }
2314
2315   /* This so far is just like an event that is flowing downstream,
2316    * so we do the same checks as a sinkpad event handler */
2317   ret =
2318       gst_validate_pad_monitor_downstream_event_check (monitor, NULL, event,
2319       NULL);
2320   GST_VALIDATE_MONITOR_UNLOCK (monitor);
2321   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
2322
2323   return ret;
2324 }
2325
2326 static GstPadProbeReturn
2327 gst_validate_pad_monitor_pad_probe (GstPad * pad, GstPadProbeInfo * info,
2328     gpointer udata)
2329 {
2330   if (info->type & GST_PAD_PROBE_TYPE_BUFFER)
2331     gst_validate_pad_monitor_buffer_probe (pad, info->data, udata);
2332   else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)
2333     gst_validate_pad_monitor_event_probe (pad, info->data, udata);
2334
2335   return GST_PAD_PROBE_OK;
2336 }
2337
2338 static void
2339 gst_validate_pad_monitor_update_caps_info (GstValidatePadMonitor * pad_monitor,
2340     GstCaps * caps)
2341 {
2342   GstStructure *structure;
2343
2344   g_return_if_fail (gst_caps_is_fixed (caps));
2345
2346   pad_monitor->caps_is_audio = FALSE;
2347   pad_monitor->caps_is_video = FALSE;
2348
2349   structure = gst_caps_get_structure (caps, 0);
2350   if (g_str_has_prefix (gst_structure_get_name (structure), "audio/")) {
2351     pad_monitor->caps_is_audio = TRUE;
2352   } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/")) {
2353     pad_monitor->caps_is_video = TRUE;
2354   }
2355
2356   if (g_str_has_prefix (gst_structure_get_name (structure), "audio/x-raw") ||
2357       g_str_has_prefix (gst_structure_get_name (structure), "video/x-raw")) {
2358     pad_monitor->caps_is_raw = TRUE;
2359   } else {
2360     pad_monitor->caps_is_raw = FALSE;
2361   }
2362 }
2363
2364 static void
2365 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
2366     GstCaps * caps)
2367 {
2368   GstStructure *structure;
2369
2370   /* Check if caps are identical to last caps and complain if so
2371    * Only checked for sink pads as src pads might push the same caps
2372    * multiple times during unlinked/autoplugging scenarios */
2373   if (GST_PAD_IS_SINK (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)) &&
2374       pad_monitor->last_caps
2375       && gst_caps_is_equal (caps, pad_monitor->last_caps)) {
2376     gchar *caps_str = gst_caps_to_string (caps);
2377
2378     GST_VALIDATE_REPORT (pad_monitor, EVENT_CAPS_DUPLICATE, "%s", caps_str);
2379     g_free (caps_str);
2380
2381   }
2382
2383   gst_validate_pad_monitor_check_caps_complete (pad_monitor, caps);
2384
2385   if (caps) {
2386     structure = gst_caps_get_structure (caps, 0);
2387     if (gst_structure_n_fields (pad_monitor->pending_setcaps_fields)) {
2388       gint i;
2389       for (i = 0;
2390           i < gst_structure_n_fields (pad_monitor->pending_setcaps_fields);
2391           i++) {
2392         const gchar *name =
2393             gst_structure_nth_field_name (pad_monitor->pending_setcaps_fields,
2394             i);
2395         const GValue *v = gst_structure_get_value (structure, name);
2396         const GValue *otherv =
2397             gst_structure_get_value (pad_monitor->pending_setcaps_fields, name);
2398
2399         if (v == NULL) {
2400           gchar *caps_str = gst_caps_to_string (caps);
2401
2402           GST_VALIDATE_REPORT (pad_monitor, CAPS_EXPECTED_FIELD_NOT_FOUND,
2403               "Field %s is missing from setcaps caps '%s'", name, caps_str);
2404           g_free (caps_str);
2405         } else if (gst_value_compare (v, otherv) != GST_VALUE_EQUAL) {
2406           gchar *caps_str = gst_caps_to_string (caps),
2407               *pending_setcaps_fields_str =
2408               gst_structure_to_string (pad_monitor->pending_setcaps_fields);
2409
2410
2411           GST_VALIDATE_REPORT (pad_monitor, CAPS_FIELD_UNEXPECTED_VALUE,
2412               "Field %s from setcaps caps '%s' is different "
2413               "from expected value in caps '%s'", name, caps_str,
2414               pending_setcaps_fields_str);
2415
2416           g_free (pending_setcaps_fields_str);
2417           g_free (caps_str);
2418         }
2419       }
2420     }
2421
2422     if (GST_PAD_IS_SINK (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)) &&
2423         gst_validate_pad_monitor_pad_should_proxy_othercaps (pad_monitor)) {
2424       if (_structure_is_video (structure)) {
2425         GST_DEBUG_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor),
2426             "Adding video common pending fields to other pad: %" GST_PTR_FORMAT,
2427             structure);
2428         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
2429             structure, "width");
2430         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
2431             structure, "height");
2432         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
2433             structure, "framerate");
2434         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
2435             structure, "pixel-aspect-ratio");
2436       } else if (_structure_is_audio (structure)) {
2437         GST_DEBUG_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor),
2438             "Adding audio common pending fields to other pad: %" GST_PTR_FORMAT,
2439             structure);
2440         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
2441             structure, "rate");
2442         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
2443             structure, "channels");
2444       }
2445     }
2446   }
2447
2448   gst_structure_free (pad_monitor->pending_setcaps_fields);
2449   pad_monitor->pending_setcaps_fields =
2450       gst_structure_new_empty (PENDING_FIELDS);
2451
2452   gst_validate_pad_monitor_setcaps_overrides (pad_monitor, caps);
2453 }
2454
2455 static void
2456 gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor * pad_monitor,
2457     GstCaps * caps, gboolean ret)
2458 {
2459   if (!ret)
2460     gst_validate_pad_monitor_otherpad_clear_pending_fields (pad_monitor);
2461   else {
2462     if (pad_monitor->last_caps) {
2463       gst_caps_unref (pad_monitor->last_caps);
2464     }
2465     pad_monitor->last_caps = gst_caps_ref (caps);
2466     gst_validate_pad_monitor_update_caps_info (pad_monitor, caps);
2467   }
2468 }
2469
2470 static gboolean
2471 gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
2472 {
2473   GstValidatePadMonitor *pad_monitor = GST_VALIDATE_PAD_MONITOR_CAST (monitor);
2474   GstPad *pad;
2475   if (!GST_IS_PAD (GST_VALIDATE_MONITOR_GET_OBJECT (monitor))) {
2476     GST_WARNING_OBJECT (monitor, "Trying to create pad monitor with other "
2477         "type of object");
2478     return FALSE;
2479   }
2480
2481   pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
2482
2483   if (g_object_get_data ((GObject *) pad, "validate-monitor")) {
2484     GST_WARNING_OBJECT (pad_monitor,
2485         "Pad already has a validate-monitor associated");
2486     return FALSE;
2487   }
2488
2489   g_object_set_data ((GObject *) pad, "validate-monitor", pad_monitor);
2490
2491   pad_monitor->pad = pad;
2492
2493   pad_monitor->event_func = GST_PAD_EVENTFUNC (pad);
2494   pad_monitor->query_func = GST_PAD_QUERYFUNC (pad);
2495   pad_monitor->activatemode_func = GST_PAD_ACTIVATEMODEFUNC (pad);
2496   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
2497
2498     pad_monitor->chain_func = GST_PAD_CHAINFUNC (pad);
2499     if (pad_monitor->chain_func)
2500       gst_pad_set_chain_function (pad, gst_validate_pad_monitor_chain_func);
2501
2502     gst_pad_set_event_function (pad, gst_validate_pad_monitor_sink_event_func);
2503   } else {
2504     pad_monitor->getrange_func = GST_PAD_GETRANGEFUNC (pad);
2505     if (pad_monitor->getrange_func)
2506       gst_pad_set_getrange_function (pad, gst_validate_pad_get_range_func);
2507
2508     gst_pad_set_event_function (pad, gst_validate_pad_monitor_src_event_func);
2509
2510     /* add buffer/event probes */
2511     pad_monitor->pad_probe_id =
2512         gst_pad_add_probe (pad,
2513         GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
2514         GST_PAD_PROBE_TYPE_EVENT_FLUSH,
2515         (GstPadProbeCallback) gst_validate_pad_monitor_pad_probe, pad_monitor,
2516         NULL);
2517   }
2518   gst_pad_set_query_function (pad, gst_validate_pad_monitor_query_func);
2519   gst_pad_set_activatemode_function (pad,
2520       gst_validate_pad_monitor_activatemode_func);
2521
2522   gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (monitor),
2523       g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad)));
2524
2525   if (G_UNLIKELY (GST_PAD_PARENT (pad) == NULL))
2526     GST_FIXME ("Saw a pad not belonging to any object");
2527
2528   return TRUE;
2529 }