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