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