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