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