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