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