validate:tools: Do not forget to give a ref for reporter's reports
[platform/upstream/gstreamer.git] / validate / gst / validate / gst-validate-pad-monitor.c
1 /* GStreamer
2  *
3  * Copyright (C) 2013 Collabora Ltd.
4  *  Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
5  *
6  * gst-validate-pad-monitor.c - Validate PadMonitor class
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "gst-validate-internal.h"
29 #include "gst-validate-pad-monitor.h"
30 #include "gst-validate-element-monitor.h"
31 #include "gst-validate-reporter.h"
32 #include <string.h>
33 #include <stdarg.h>
34
35 /**
36  * SECTION:gst-validate-pad-monitor
37  * @short_description: Class that wraps a #GstPad for Validate checks
38  *
39  * TODO
40  */
41
42 #define gst_validate_pad_monitor_parent_class parent_class
43 G_DEFINE_TYPE (GstValidatePadMonitor, gst_validate_pad_monitor,
44     GST_TYPE_VALIDATE_MONITOR);
45
46 #define PENDING_FIELDS "pending-fields"
47 #define AUDIO_TIMESTAMP_TOLERANCE (GST_MSECOND * 100)
48
49 #define PAD_PARENT_IS_DEMUXER(m) \
50     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
51         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DEMUXER ( \
52             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
53         FALSE)
54
55 #define PAD_PARENT_IS_DECODER(m) \
56     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
57         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DECODER ( \
58             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
59         FALSE)
60
61 #define PAD_PARENT_IS_ENCODER(m) \
62     (GST_VALIDATE_MONITOR_GET_PARENT(m) ? \
63         GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_ENCODER ( \
64             GST_VALIDATE_MONITOR_GET_PARENT(m)) : \
65         FALSE)
66
67
68 /*
69  * Locking the parent should always be done before locking the
70  * pad-monitor to prevent deadlocks in case another monitor from
71  * another pad on the same element starts an operation that also
72  * requires locking itself and some other monitors from internally
73  * linked pads.
74  *
75  * An example:
76  * An element has a sink and a src pad. Some test starts running at sinkpad
77  * and it locks the parent, and then it locks itself. In case it needs to get
78  * some information from the srcpad, it is able to lock the srcpad and get it
79  * because the srcpad should never lock itself before locking the parent (which
80  * it won't be able as sinkpad already locked it).
81  *
82  * As a side one, it is possible that srcpad locks itself without locking the
83  * parent in case it wants to do a check that won't need to use other internally
84  * linked pads (sinkpad). But in this case it might lock and unlock freely without
85  * causing deadlocks.
86  */
87 #define GST_VALIDATE_PAD_MONITOR_PARENT_LOCK(m)                  \
88 G_STMT_START {                                             \
89   if (G_LIKELY (GST_VALIDATE_MONITOR_GET_PARENT (m))) {          \
90     GST_VALIDATE_MONITOR_LOCK (GST_VALIDATE_MONITOR_GET_PARENT (m));   \
91   } else {                                                 \
92     GST_WARNING_OBJECT (m, "No parent found, can't lock"); \
93   }                                                        \
94 } G_STMT_END
95
96 #define GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK(m)                  \
97 G_STMT_START {                                               \
98   if (G_LIKELY (GST_VALIDATE_MONITOR_GET_PARENT (m))) {            \
99     GST_VALIDATE_MONITOR_UNLOCK (GST_VALIDATE_MONITOR_GET_PARENT (m));   \
100   } else {                                                   \
101     GST_WARNING_OBJECT (m, "No parent found, can't unlock"); \
102   }                                                          \
103 } G_STMT_END
104
105 typedef struct
106 {
107   GstClockTime timestamp;
108   GstEvent *event;
109 } SerializedEventData;
110
111 static void
112 debug_pending_event (GstPad * pad, GPtrArray * array)
113 {
114   guint i, len;
115
116   len = array->len;
117   for (i = 0; i < len; i++) {
118     SerializedEventData *data = g_ptr_array_index (array, i);
119     GST_DEBUG_OBJECT (pad, "event #%d %" GST_TIME_FORMAT " %s %p",
120         i, GST_TIME_ARGS (data->timestamp),
121         GST_EVENT_TYPE_NAME (data->event), data->event);
122   }
123 }
124
125 static void
126 _serialized_event_data_free (SerializedEventData * serialized_event)
127 {
128   gst_event_unref (serialized_event->event);
129   g_slice_free (SerializedEventData, serialized_event);
130 }
131
132 static gboolean gst_validate_pad_monitor_do_setup (GstValidateMonitor *
133     monitor);
134 static GstElement *gst_validate_pad_monitor_get_element (GstValidateMonitor *
135     monitor);
136 static void
137 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
138     GstCaps * caps);
139 static void gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor *
140     pad_monitor, GstCaps * caps, gboolean ret);
141
142 #define PAD_IS_IN_PUSH_MODE(p) ((p)->mode == GST_PAD_MODE_PUSH)
143
144 static gboolean
145 _structure_is_raw_video (GstStructure * structure)
146 {
147   return gst_structure_has_name (structure, "video/x-raw");
148 }
149
150 static gboolean
151 _structure_is_raw_audio (GstStructure * structure)
152 {
153   return gst_structure_has_name (structure, "audio/x-raw");
154 }
155
156 static void
157 _check_field_type (GstValidatePadMonitor * monitor, GstStructure * structure,
158     const gchar * field, ...)
159 {
160   va_list var_args;
161   GType type;
162   gchar *joined_types = NULL;
163   const gchar *rejected_types[5];
164   gint rejected_types_index = 0;
165
166   if (!gst_structure_has_field (structure, field)) {
167     gchar *str = gst_structure_to_string (structure);
168
169     GST_VALIDATE_REPORT (monitor, CAPS_IS_MISSING_FIELD,
170         "Field '%s' is missing from structure: %" GST_PTR_FORMAT, field,
171         str);
172     g_free(str);
173     return;
174   }
175
176   memset (rejected_types, 0, sizeof (rejected_types));
177   va_start (var_args, field);
178   while ((type = va_arg (var_args, GType)) != 0) {
179     if (gst_structure_has_field_typed (structure, field, type)) {
180       va_end (var_args);
181       return;
182     }
183     rejected_types[rejected_types_index++] = g_type_name (type);
184   }
185   va_end (var_args);
186
187   joined_types = g_strjoinv (" / ", (gchar **) rejected_types);
188   GST_VALIDATE_REPORT (monitor, CAPS_FIELD_HAS_BAD_TYPE,
189       "Field '%s' has wrong type %s in structure '%" GST_PTR_FORMAT
190       "'. Expected: %s", field,
191       g_type_name (gst_structure_get_field_type (structure, field)), structure,
192       joined_types);
193   g_free (joined_types);
194 }
195
196 static void
197 gst_validate_pad_monitor_check_raw_video_caps_complete (GstValidatePadMonitor *
198     monitor, GstStructure * structure)
199 {
200   _check_field_type (monitor, structure, "width", G_TYPE_INT,
201       GST_TYPE_INT_RANGE, 0);
202   _check_field_type (monitor, structure, "height", G_TYPE_INT,
203       GST_TYPE_INT_RANGE, 0);
204   _check_field_type (monitor, structure, "framerate", GST_TYPE_FRACTION,
205       GST_TYPE_FRACTION_RANGE, 0);
206   _check_field_type (monitor, structure, "pixel-aspect-ratio",
207       GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, 0);
208   _check_field_type (monitor, structure, "format", G_TYPE_STRING,
209       GST_TYPE_LIST);
210 }
211
212 static void
213 gst_validate_pad_monitor_check_raw_audio_caps_complete (GstValidatePadMonitor *
214     monitor, GstStructure * structure)
215 {
216   gint channels;
217   _check_field_type (monitor, structure, "format", G_TYPE_STRING, GST_TYPE_LIST,
218       0);
219   _check_field_type (monitor, structure, "layout", G_TYPE_STRING, GST_TYPE_LIST,
220       0);
221   _check_field_type (monitor, structure, "rate", G_TYPE_INT, GST_TYPE_LIST,
222       GST_TYPE_INT_RANGE, 0);
223   _check_field_type (monitor, structure, "channels", G_TYPE_INT, GST_TYPE_LIST,
224       GST_TYPE_INT_RANGE, 0);
225   if (gst_structure_get_int(structure, "channels", &channels)) {
226     if (channels > 2)
227       _check_field_type (monitor, structure, "channel-mask", GST_TYPE_BITMASK,
228           GST_TYPE_LIST, 0);
229   }
230 }
231
232 static void
233 gst_validate_pad_monitor_check_caps_complete (GstValidatePadMonitor * monitor,
234     GstCaps * caps)
235 {
236   GstStructure *structure;
237   gint i;
238
239   GST_DEBUG_OBJECT (monitor->pad, "Checking caps %" GST_PTR_FORMAT, caps);
240
241   for (i = 0; i < gst_caps_get_size (caps); i++) {
242     structure = gst_caps_get_structure (caps, i);
243
244     if (_structure_is_raw_video (structure)) {
245       gst_validate_pad_monitor_check_raw_video_caps_complete (monitor,
246           structure);
247
248     } else if (_structure_is_raw_audio (structure)) {
249       gst_validate_pad_monitor_check_raw_audio_caps_complete (monitor,
250           structure);
251     }
252   }
253 }
254
255 static GstCaps *
256 gst_validate_pad_monitor_get_othercaps (GstValidatePadMonitor * monitor)
257 {
258   GstCaps *caps = gst_caps_new_empty ();
259   GstIterator *iter;
260   gboolean done;
261   GstPad *otherpad;
262   GstCaps *peercaps;
263
264   iter =
265       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
266       (monitor));
267   done = FALSE;
268   while (!done) {
269     GValue value = { 0, };
270     switch (gst_iterator_next (iter, &value)) {
271       case GST_ITERATOR_OK:
272         otherpad = g_value_get_object (&value);
273
274         /* TODO What would be the correct caps operation to merge the caps in
275          * case one sink is internally linked to multiple srcs? */
276         peercaps = gst_pad_peer_query_caps (otherpad, NULL);
277         if (peercaps)
278           caps = gst_caps_merge (caps, peercaps);
279
280         g_value_reset (&value);
281         break;
282       case GST_ITERATOR_RESYNC:
283         gst_iterator_resync (iter);
284         gst_caps_replace (&caps, gst_caps_new_empty ());
285         break;
286       case GST_ITERATOR_ERROR:
287         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
288         done = TRUE;
289         break;
290       case GST_ITERATOR_DONE:
291         done = TRUE;
292         break;
293     }
294   }
295   gst_iterator_free (iter);
296
297   GST_DEBUG_OBJECT (monitor->pad, "Otherpad caps: %" GST_PTR_FORMAT, caps);
298
299   return caps;
300 }
301
302 static gboolean
303 _structure_is_video (GstStructure * structure)
304 {
305   const gchar *name = gst_structure_get_name (structure);
306
307   return g_strstr_len (name, 6, "video/")
308       && strcmp (name, "video/quicktime") != 0;
309 }
310
311 static gboolean
312 _structure_is_audio (GstStructure * structure)
313 {
314   const gchar *name = gst_structure_get_name (structure);
315
316   return g_strstr_len (name, 6, "audio/") != NULL;
317 }
318
319 static gboolean
320 gst_validate_pad_monitor_pad_should_proxy_othercaps (GstValidatePadMonitor *
321     monitor)
322 {
323   GstValidateMonitor *parent = GST_VALIDATE_MONITOR_GET_PARENT (monitor);
324
325   if (!parent)
326     return FALSE;
327
328   /* We only know how to handle othercaps checks for codecs so far */
329   return GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_DECODER (parent) ||
330       GST_VALIDATE_ELEMENT_MONITOR_ELEMENT_IS_ENCODER (parent);
331 }
332
333
334 /* Check if the field @f from @s2 (if present) is represented in @s1
335  * Represented here means either equal or @s1's value is in a list/range
336  * from @s2
337  */
338 static gboolean
339 _structures_field_is_contained (GstStructure * s1, GstStructure * s2,
340     const gchar * f)
341 {
342   const GValue *v1;
343   const GValue *v2;
344
345   v2 = gst_structure_get_value (s2, f);
346   if (!v2)
347     return TRUE;                /* nothing to compare to */
348
349   v1 = gst_structure_get_value (s1, f);
350   if (!v1)
351     return FALSE;
352
353   if (!gst_value_is_fixed (v1) && !gst_value_is_fixed (v2))
354     return TRUE;
355
356   if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
357     return TRUE;
358
359   if (GST_VALUE_HOLDS_LIST (v2)) {
360     gint i;
361     for (i = 0; i < gst_value_list_get_size (v2); i++) {
362       const GValue *v2_subvalue = gst_value_list_get_value (v2, i);
363       if (gst_value_compare (v1, v2_subvalue) == GST_VALUE_EQUAL)
364         return TRUE;
365     }
366   }
367
368   if (GST_VALUE_HOLDS_ARRAY (v2)) {
369     gint i;
370     for (i = 0; i < gst_value_array_get_size (v2); i++) {
371       const GValue *v2_subvalue = gst_value_array_get_value (v2, i);
372       if (gst_value_compare (v1, v2_subvalue) == GST_VALUE_EQUAL)
373         return TRUE;
374     }
375   }
376
377   if (GST_VALUE_HOLDS_INT_RANGE (v2)) {
378     gint min, max;
379
380     min = gst_value_get_int_range_min (v2);
381     max = gst_value_get_int_range_max (v2);
382
383     if (G_VALUE_HOLDS_INT (v1)) {
384       gint v = g_value_get_int (v1);
385
386       return v >= min && v <= max;
387     } else {
388       /* TODO compare int ranges with int ranges
389        * or with lists if useful */
390     }
391   }
392
393   if (GST_VALUE_HOLDS_FRACTION_RANGE (v2)) {
394     const GValue *min, *max;
395
396     min = gst_value_get_fraction_range_min (v2);
397     max = gst_value_get_fraction_range_max (v2);
398
399     if (GST_VALUE_HOLDS_FRACTION (v1)) {
400       gint v_min = gst_value_compare (v1, min);
401       gint v_max = gst_value_compare (v1, max);
402
403       return (v_min == GST_VALUE_EQUAL || v_min == GST_VALUE_GREATER_THAN) &&
404           (v_max == GST_VALUE_EQUAL || v_max == GST_VALUE_LESS_THAN);
405     } else {
406       /* TODO compare fraction ranges with fraction ranges
407        * or with lists if useful */
408     }
409   }
410
411   return FALSE;
412 }
413
414 static void
415 gst_validate_pad_monitor_check_caps_fields_proxied (GstValidatePadMonitor *
416     monitor, GstCaps * caps)
417 {
418   GstStructure *structure;
419   GstStructure *otherstructure;
420   GstCaps *othercaps;
421   gint i, j;
422
423   if (!gst_validate_pad_monitor_pad_should_proxy_othercaps (monitor))
424     return;
425
426   othercaps = gst_validate_pad_monitor_get_othercaps (monitor);
427
428   for (i = 0; i < gst_caps_get_size (othercaps); i++) {
429     gboolean found = FALSE;
430     gboolean type_match = FALSE;
431
432     otherstructure = gst_caps_get_structure (othercaps, i);
433
434     /* look for a proxied version of 'otherstructure' */
435     if (_structure_is_video (otherstructure)) {
436       for (j = 0; j < gst_caps_get_size (caps); j++) {
437         structure = gst_caps_get_structure (caps, j);
438         if (_structure_is_video (structure)) {
439           type_match = TRUE;
440           if (_structures_field_is_contained (structure, otherstructure,
441                   "width")
442               && _structures_field_is_contained (structure, otherstructure,
443                   "height")
444               && _structures_field_is_contained (structure, otherstructure,
445                   "framerate")
446               && _structures_field_is_contained (structure, otherstructure,
447                   "pixel-aspect-ratio")) {
448             found = TRUE;
449             break;
450           }
451         }
452       }
453     } else if (_structure_is_audio (otherstructure)) {
454       for (j = 0; j < gst_caps_get_size (caps); j++) {
455         structure = gst_caps_get_structure (caps, j);
456         if (_structure_is_audio (structure)) {
457           type_match = TRUE;
458           if (_structures_field_is_contained (structure, otherstructure, "rate")
459               && _structures_field_is_contained (structure, otherstructure,
460                   "channels")) {
461             found = TRUE;
462             break;
463           }
464         }
465       }
466     }
467
468     if (type_match && !found) {
469       GST_VALIDATE_REPORT (monitor, GET_CAPS_NOT_PROXYING_FIELDS,
470           "Peer pad structure '%" GST_PTR_FORMAT "' has no similar version "
471           "on pad's caps '%" GST_PTR_FORMAT "'", otherstructure, caps);
472     }
473   }
474 }
475
476 static void
477 gst_validate_pad_monitor_check_late_serialized_events (GstValidatePadMonitor *
478     monitor, GstClockTime ts)
479 {
480   gint i;
481
482   if (!GST_CLOCK_TIME_IS_VALID (ts))
483     return;
484
485   GST_DEBUG_OBJECT (monitor->pad, "Timestamp to check %" GST_TIME_FORMAT,
486       GST_TIME_ARGS (ts));
487
488   for (i = 0; i < monitor->serialized_events->len; i++) {
489     SerializedEventData *data =
490         g_ptr_array_index (monitor->serialized_events, i);
491
492     GST_DEBUG_OBJECT (monitor->pad, "Event #%d (%s) ts: %" GST_TIME_FORMAT,
493         i, GST_EVENT_TYPE_NAME (data->event), GST_TIME_ARGS (data->timestamp));
494
495     if (GST_CLOCK_TIME_IS_VALID (data->timestamp) && data->timestamp < ts) {
496       GST_VALIDATE_REPORT (monitor, SERIALIZED_EVENT_WASNT_PUSHED_IN_TIME,
497           "Serialized event %" GST_PTR_FORMAT " wasn't pushed before expected "
498           "timestamp %" GST_TIME_FORMAT " on pad %s:%s", data->event,
499           GST_TIME_ARGS (data->timestamp),
500           GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)));
501     } else {
502       /* events should be ordered by ts */
503       break;
504     }
505   }
506
507   if (i) {
508     debug_pending_event (monitor->pad, monitor->serialized_events);
509     g_ptr_array_remove_range (monitor->serialized_events, 0, i);
510   }
511 }
512
513 static void
514 gst_validate_pad_monitor_dispose (GObject * object)
515 {
516   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (object);
517   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
518
519   if (pad) {
520     if (monitor->pad_probe_id)
521       gst_pad_remove_probe (pad, monitor->pad_probe_id);
522   }
523
524   if (monitor->expected_segment)
525     gst_event_unref (monitor->expected_segment);
526
527   gst_structure_free (monitor->pending_setcaps_fields);
528   g_ptr_array_unref (monitor->serialized_events);
529   g_list_free_full (monitor->expired_events, (GDestroyNotify) gst_event_unref);
530
531   G_OBJECT_CLASS (parent_class)->dispose (object);
532 }
533
534 static void
535 gst_validate_pad_monitor_class_init (GstValidatePadMonitorClass * klass)
536 {
537   GObjectClass *gobject_class;
538   GstValidateMonitorClass *monitor_klass;
539
540   gobject_class = G_OBJECT_CLASS (klass);
541   monitor_klass = GST_VALIDATE_MONITOR_CLASS (klass);
542
543   gobject_class->dispose = gst_validate_pad_monitor_dispose;
544
545   monitor_klass->setup = gst_validate_pad_monitor_do_setup;
546   monitor_klass->get_element = gst_validate_pad_monitor_get_element;
547 }
548
549 static void
550 gst_validate_pad_monitor_init (GstValidatePadMonitor * pad_monitor)
551 {
552   pad_monitor->pending_setcaps_fields =
553       gst_structure_new_empty (PENDING_FIELDS);
554   pad_monitor->serialized_events =
555       g_ptr_array_new_with_free_func ((GDestroyNotify)
556       _serialized_event_data_free);
557   pad_monitor->expired_events = NULL;
558   gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES);
559   pad_monitor->first_buffer = TRUE;
560
561   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
562   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
563 }
564
565 /**
566  * gst_validate_pad_monitor_new:
567  * @pad: (transfer-none): a #GstPad to run Validate on
568  */
569 GstValidatePadMonitor *
570 gst_validate_pad_monitor_new (GstPad * pad, GstValidateRunner * runner,
571     GstValidateElementMonitor * parent)
572 {
573   GstValidatePadMonitor *monitor = g_object_new (GST_TYPE_VALIDATE_PAD_MONITOR,
574       "object", pad, "validate-runner", runner, "validate-parent",
575       parent, NULL);
576
577   if (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor) == NULL) {
578     g_object_unref (monitor);
579     return NULL;
580   }
581   return monitor;
582 }
583
584 static GstElement *
585 gst_validate_pad_monitor_get_element (GstValidateMonitor * monitor)
586 {
587   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
588
589   return GST_PAD_PARENT (pad);
590 }
591
592 static void
593 gst_validate_pad_monitor_event_overrides (GstValidatePadMonitor * pad_monitor,
594     GstEvent * event)
595 {
596   GList *iter;
597
598   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
599   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
600       iter = g_list_next (iter)) {
601     GstValidateOverride *override = iter->data;
602
603     gst_validate_override_event_handler (override,
604         GST_VALIDATE_MONITOR_CAST (pad_monitor), event);
605   }
606   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
607 }
608
609 static void
610 gst_validate_pad_monitor_buffer_overrides (GstValidatePadMonitor * pad_monitor,
611     GstBuffer * buffer)
612 {
613   GList *iter;
614
615   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
616   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
617       iter = g_list_next (iter)) {
618     GstValidateOverride *override = iter->data;
619
620     gst_validate_override_buffer_handler (override,
621         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
622   }
623   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
624 }
625
626 static void
627 gst_validate_pad_monitor_buffer_probe_overrides (GstValidatePadMonitor *
628     pad_monitor, GstBuffer * buffer)
629 {
630   GList *iter;
631
632   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
633   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
634       iter = g_list_next (iter)) {
635     GstValidateOverride *override = iter->data;
636
637     gst_validate_override_buffer_probe_handler (override,
638         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
639   }
640   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
641 }
642
643 static void
644 gst_validate_pad_monitor_query_overrides (GstValidatePadMonitor * pad_monitor,
645     GstQuery * query)
646 {
647   GList *iter;
648
649   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
650   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
651       iter = g_list_next (iter)) {
652     GstValidateOverride *override = iter->data;
653
654     gst_validate_override_query_handler (override,
655         GST_VALIDATE_MONITOR_CAST (pad_monitor), query);
656   }
657   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
658 }
659
660 static void
661 gst_validate_pad_monitor_setcaps_overrides (GstValidatePadMonitor * pad_monitor,
662     GstCaps * caps)
663 {
664   GList *iter;
665
666   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
667   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
668       iter = g_list_next (iter)) {
669     GstValidateOverride *override = iter->data;
670
671     gst_validate_override_setcaps_handler (override,
672         GST_VALIDATE_MONITOR_CAST (pad_monitor), caps);
673   }
674   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
675 }
676
677 /* FIXME : This is a bit dubious, what's the point of this check ? */
678 static gboolean
679 gst_validate_pad_monitor_timestamp_is_in_received_range (GstValidatePadMonitor *
680     monitor, GstClockTime ts, GstClockTime tolerance)
681 {
682   GST_DEBUG_OBJECT (monitor->pad, "Checking if timestamp %" GST_TIME_FORMAT
683       " is in range: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT " for pad "
684       "%s:%s with tolerance: %" GST_TIME_FORMAT, GST_TIME_ARGS (ts),
685       GST_TIME_ARGS (monitor->timestamp_range_start),
686       GST_TIME_ARGS (monitor->timestamp_range_end),
687       GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)),
688       GST_TIME_ARGS (tolerance));
689   return !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_start) ||
690       !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_end) ||
691       ((monitor->timestamp_range_start >= tolerance ?
692           monitor->timestamp_range_start - tolerance : 0) <= ts
693       && (ts >= tolerance ? ts - tolerance : 0) <=
694       monitor->timestamp_range_end);
695 }
696
697 /* Iterates over internal links (sinkpads) to check that this buffer has
698  * a timestamp that is in the range of the lastly received buffers */
699 static void
700     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range
701     (GstValidatePadMonitor * monitor, GstBuffer * buffer,
702     GstClockTime tolerance)
703 {
704   GstClockTime ts;
705   GstClockTime ts_end;
706   GstIterator *iter;
707   gboolean has_one = FALSE;
708   gboolean found = FALSE;
709   gboolean done;
710   GstPad *otherpad;
711   GstValidatePadMonitor *othermonitor;
712
713   if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))
714       || !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
715     GST_DEBUG_OBJECT (monitor->pad,
716         "Can't check buffer timestamps range as "
717         "buffer has no valid timestamp/duration");
718     return;
719   }
720   ts = GST_BUFFER_TIMESTAMP (buffer);
721   ts_end = ts + GST_BUFFER_DURATION (buffer);
722
723   iter =
724       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
725       (monitor));
726
727   if (iter == NULL) {
728     GST_WARNING_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor),
729         "No iterator available");
730     return;
731   }
732
733   done = FALSE;
734   while (!done) {
735     GValue value = { 0, };
736     switch (gst_iterator_next (iter, &value)) {
737       case GST_ITERATOR_OK:
738         otherpad = g_value_get_object (&value);
739         GST_DEBUG_OBJECT (monitor->pad, "Checking pad %s:%s input timestamps",
740             GST_DEBUG_PAD_NAME (otherpad));
741         othermonitor =
742             g_object_get_data ((GObject *) otherpad, "validate-monitor");
743         GST_VALIDATE_MONITOR_LOCK (othermonitor);
744         if (gst_validate_pad_monitor_timestamp_is_in_received_range
745             (othermonitor, ts, tolerance)
746             &&
747             gst_validate_pad_monitor_timestamp_is_in_received_range
748             (othermonitor, ts_end, tolerance)) {
749           done = TRUE;
750           found = TRUE;
751         }
752         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
753         g_value_reset (&value);
754         has_one = TRUE;
755         break;
756       case GST_ITERATOR_RESYNC:
757         gst_iterator_resync (iter);
758         has_one = FALSE;
759         found = FALSE;
760         break;
761       case GST_ITERATOR_ERROR:
762         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
763         done = TRUE;
764         break;
765       case GST_ITERATOR_DONE:
766         done = TRUE;
767         break;
768     }
769   }
770   gst_iterator_free (iter);
771
772   if (!has_one) {
773     GST_DEBUG_OBJECT (monitor->pad, "Skipping timestamp in range check as no "
774         "internal linked pad was found");
775     return;
776   }
777   if (!found) {
778     GST_VALIDATE_REPORT (monitor, BUFFER_TIMESTAMP_OUT_OF_RECEIVED_RANGE,
779         "Timestamp %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT
780         " is out of range of received input", GST_TIME_ARGS (ts),
781         GST_TIME_ARGS (ts_end));
782   }
783 }
784
785 static void
786 gst_validate_pad_monitor_check_first_buffer (GstValidatePadMonitor *
787     pad_monitor, GstBuffer * buffer)
788 {
789   if (G_UNLIKELY (pad_monitor->first_buffer)) {
790     pad_monitor->first_buffer = FALSE;
791
792     if (!pad_monitor->has_segment
793         && PAD_IS_IN_PUSH_MODE (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)))
794     {
795       GST_VALIDATE_REPORT (pad_monitor, BUFFER_BEFORE_SEGMENT,
796           "Received buffer before Segment event");
797     }
798     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
799       gint64 running_time = gst_segment_to_running_time (&pad_monitor->segment,
800           pad_monitor->segment.format, GST_BUFFER_TIMESTAMP (buffer));
801       if (running_time != 0) {
802         GST_VALIDATE_REPORT (pad_monitor, FIRST_BUFFER_RUNNING_TIME_IS_NOT_ZERO,
803             "First buffer running time is not 0, it is: %" GST_TIME_FORMAT,
804             GST_TIME_ARGS (running_time));
805       }
806     }
807   }
808 }
809
810 static void
811 gst_validate_pad_monitor_update_buffer_data (GstValidatePadMonitor *
812     pad_monitor, GstBuffer * buffer)
813 {
814   pad_monitor->current_timestamp = GST_BUFFER_TIMESTAMP (buffer);
815   pad_monitor->current_duration = GST_BUFFER_DURATION (buffer);
816   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
817     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_start)) {
818       pad_monitor->timestamp_range_start =
819           MIN (pad_monitor->timestamp_range_start,
820           GST_BUFFER_TIMESTAMP (buffer));
821     } else {
822       pad_monitor->timestamp_range_start = GST_BUFFER_TIMESTAMP (buffer);
823     }
824
825     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
826       GstClockTime endts =
827           GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
828       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_end)) {
829         pad_monitor->timestamp_range_end =
830             MAX (pad_monitor->timestamp_range_end, endts);
831       } else {
832         pad_monitor->timestamp_range_end = endts;
833       }
834     }
835   }
836   GST_DEBUG_OBJECT (pad_monitor->pad, "Current stored range: %" GST_TIME_FORMAT
837       " - %" GST_TIME_FORMAT,
838       GST_TIME_ARGS (pad_monitor->timestamp_range_start),
839       GST_TIME_ARGS (pad_monitor->timestamp_range_end));
840 }
841
842 static GstFlowReturn
843 _combine_flows (GstFlowReturn ret1, GstFlowReturn ret2)
844 {
845   if (ret1 == ret2)
846     return ret1;
847   if (ret1 <= GST_FLOW_NOT_NEGOTIATED)
848     return ret1;
849   if (ret2 <= GST_FLOW_NOT_NEGOTIATED)
850     return ret2;
851   if (ret1 == GST_FLOW_FLUSHING || ret2 == GST_FLOW_FLUSHING)
852     return GST_FLOW_FLUSHING;
853   if (ret1 == GST_FLOW_OK || ret2 == GST_FLOW_OK)
854     return GST_FLOW_OK;
855   return ret2;
856 }
857
858 static void
859 gst_validate_pad_monitor_check_aggregated_return (GstValidatePadMonitor *
860     monitor, GstFlowReturn ret)
861 {
862   GstIterator *iter;
863   gboolean done;
864   GstPad *otherpad;
865   GstPad *peerpad;
866   GstValidatePadMonitor *othermonitor;
867   GstFlowReturn aggregated = GST_FLOW_NOT_LINKED;
868   gboolean found_a_pad = FALSE;
869   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
870
871   iter = gst_pad_iterate_internal_links (pad);
872   done = FALSE;
873   while (!done) {
874     GValue value = { 0, };
875     switch (gst_iterator_next (iter, &value)) {
876       case GST_ITERATOR_OK:
877         otherpad = g_value_get_object (&value);
878         peerpad = gst_pad_get_peer (otherpad);
879         if (peerpad) {
880           othermonitor =
881               g_object_get_data ((GObject *) peerpad, "validate-monitor");
882           if (othermonitor) {
883             found_a_pad = TRUE;
884             GST_VALIDATE_MONITOR_LOCK (othermonitor);
885             aggregated =
886                 _combine_flows (aggregated, othermonitor->last_flow_return);
887             GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
888           }
889
890           gst_object_unref (peerpad);
891         }
892         g_value_reset (&value);
893         break;
894       case GST_ITERATOR_RESYNC:
895         gst_iterator_resync (iter);
896         break;
897       case GST_ITERATOR_ERROR:
898         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
899         done = TRUE;
900         break;
901       case GST_ITERATOR_DONE:
902         done = TRUE;
903         break;
904     }
905   }
906   gst_iterator_free (iter);
907   if (!found_a_pad) {
908     /* no peer pad found, nothing to do */
909     return;
910   }
911   if (aggregated == GST_FLOW_OK || aggregated == GST_FLOW_EOS) {
912     /* those are acceptable situations */
913
914     if (GST_PAD_IS_FLUSHING (pad) && ret == GST_FLOW_FLUSHING) {
915       /* pad is flushing, always acceptable to return flushing */
916       return;
917     }
918
919     if (monitor->is_eos && ret == GST_FLOW_EOS) {
920       /* this element received eos and returned eos */
921       return;
922     }
923
924     if (PAD_PARENT_IS_DEMUXER (monitor) && ret == GST_FLOW_EOS) {
925       /* a demuxer can return EOS when the samples end */
926       return;
927     }
928   }
929
930   if (aggregated != ret) {
931     GST_VALIDATE_REPORT (monitor, WRONG_FLOW_RETURN,
932         "Wrong combined flow return %s(%d). Expected: %s(%d)",
933         gst_flow_get_name (ret), ret, gst_flow_get_name (aggregated),
934         aggregated);
935   }
936 }
937
938 static void
939     gst_validate_pad_monitor_otherpad_add_pending_serialized_event
940     (GstValidatePadMonitor * monitor, GstEvent * event, GstClockTime last_ts)
941 {
942   GstIterator *iter;
943   gboolean done;
944   GstPad *otherpad;
945   GstValidatePadMonitor *othermonitor;
946
947   if (!GST_EVENT_IS_SERIALIZED (event))
948     return;
949
950   iter =
951       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
952       (monitor));
953   if (iter == NULL) {
954     /* inputselector will return NULL if the sinkpad is not the active one .... */
955     GST_FIXME_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD
956         (monitor), "No iterator");
957     return;
958   }
959   done = FALSE;
960   while (!done) {
961     GValue value = { 0, };
962     switch (gst_iterator_next (iter, &value)) {
963       case GST_ITERATOR_OK:
964         otherpad = g_value_get_object (&value);
965         othermonitor =
966             g_object_get_data ((GObject *) otherpad, "validate-monitor");
967         if (othermonitor) {
968           SerializedEventData *data = g_slice_new0 (SerializedEventData);
969           data->timestamp = last_ts;
970           data->event = gst_event_ref (event);
971           GST_VALIDATE_MONITOR_LOCK (othermonitor);
972           GST_DEBUG_OBJECT (monitor->pad, "Storing for pad %s:%s event %p %s",
973               GST_DEBUG_PAD_NAME (otherpad), event,
974               GST_EVENT_TYPE_NAME (event));
975           g_ptr_array_add (othermonitor->serialized_events, data);
976           debug_pending_event (otherpad, othermonitor->serialized_events);
977           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
978         }
979         g_value_reset (&value);
980         break;
981       case GST_ITERATOR_RESYNC:
982         gst_iterator_resync (iter);
983         break;
984       case GST_ITERATOR_ERROR:
985         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
986         done = TRUE;
987         break;
988       case GST_ITERATOR_DONE:
989         done = TRUE;
990         break;
991     }
992   }
993   gst_iterator_free (iter);
994 }
995
996 static void
997 gst_validate_pad_monitor_otherpad_add_pending_field (GstValidatePadMonitor *
998     monitor, GstStructure * structure, const gchar * field)
999 {
1000   GstIterator *iter;
1001   gboolean done;
1002   GstPad *otherpad;
1003   GstValidatePadMonitor *othermonitor;
1004   const GValue *v;
1005
1006   v = gst_structure_get_value (structure, field);
1007   if (v == NULL) {
1008     GST_DEBUG_OBJECT (monitor->pad, "Not adding pending field %s as it isn't "
1009         "present on structure %" GST_PTR_FORMAT, field, structure);
1010     return;
1011   }
1012
1013   iter =
1014       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1015       (monitor));
1016   done = FALSE;
1017   while (!done) {
1018     GValue value = { 0, };
1019     switch (gst_iterator_next (iter, &value)) {
1020       case GST_ITERATOR_OK:
1021         otherpad = g_value_get_object (&value);
1022         othermonitor =
1023             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1024         if (othermonitor) {
1025           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1026           g_assert (othermonitor->pending_setcaps_fields != NULL);
1027           gst_structure_set_value (othermonitor->pending_setcaps_fields,
1028               field, v);
1029           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1030         }
1031         g_value_reset (&value);
1032         break;
1033       case GST_ITERATOR_RESYNC:
1034         gst_iterator_resync (iter);
1035         break;
1036       case GST_ITERATOR_ERROR:
1037         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1038         done = TRUE;
1039         break;
1040       case GST_ITERATOR_DONE:
1041         done = TRUE;
1042         break;
1043     }
1044   }
1045   gst_iterator_free (iter);
1046 }
1047
1048 static void
1049 gst_validate_pad_monitor_otherpad_clear_pending_fields (GstValidatePadMonitor *
1050     monitor)
1051 {
1052   GstIterator *iter;
1053   gboolean done;
1054   GstPad *otherpad;
1055   GstValidatePadMonitor *othermonitor;
1056
1057   iter =
1058       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1059       (monitor));
1060   done = FALSE;
1061   while (!done) {
1062     GValue value = { 0, };
1063     switch (gst_iterator_next (iter, &value)) {
1064       case GST_ITERATOR_OK:
1065         otherpad = g_value_get_object (&value);
1066         othermonitor =
1067             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1068         if (othermonitor) {
1069           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1070           g_assert (othermonitor->pending_setcaps_fields != NULL);
1071           gst_structure_free (othermonitor->pending_setcaps_fields);
1072           othermonitor->pending_setcaps_fields =
1073               gst_structure_new_empty (PENDING_FIELDS);
1074           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1075         }
1076         g_value_reset (&value);
1077         break;
1078       case GST_ITERATOR_RESYNC:
1079         gst_iterator_resync (iter);
1080         break;
1081       case GST_ITERATOR_ERROR:
1082         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1083         done = TRUE;
1084         break;
1085       case GST_ITERATOR_DONE:
1086         done = TRUE;
1087         break;
1088     }
1089   }
1090   gst_iterator_free (iter);
1091 }
1092
1093 static void
1094 gst_validate_pad_monitor_add_expected_newsegment (GstValidatePadMonitor *
1095     monitor, GstEvent * event)
1096 {
1097   GstIterator *iter;
1098   gboolean done;
1099   GstPad *otherpad;
1100   GstValidatePadMonitor *othermonitor;
1101
1102   iter =
1103       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1104       (monitor));
1105   done = FALSE;
1106   while (!done) {
1107     GValue value = { 0, };
1108     switch (gst_iterator_next (iter, &value)) {
1109       case GST_ITERATOR_OK:
1110         otherpad = g_value_get_object (&value);
1111         othermonitor =
1112             g_object_get_data ((GObject *) otherpad, "validate-monitor");
1113         GST_VALIDATE_MONITOR_LOCK (othermonitor);
1114         gst_event_replace (&othermonitor->expected_segment, event);
1115         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1116         g_value_reset (&value);
1117         break;
1118       case GST_ITERATOR_RESYNC:
1119         gst_iterator_resync (iter);
1120         break;
1121       case GST_ITERATOR_ERROR:
1122         GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error");
1123         done = TRUE;
1124         break;
1125       case GST_ITERATOR_DONE:
1126         done = TRUE;
1127         break;
1128     }
1129   }
1130   gst_iterator_free (iter);
1131 }
1132
1133 static void
1134 gst_validate_pad_monitor_flush (GstValidatePadMonitor * pad_monitor)
1135 {
1136   pad_monitor->current_timestamp = GST_CLOCK_TIME_NONE;
1137   pad_monitor->current_duration = GST_CLOCK_TIME_NONE;
1138   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
1139   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
1140   pad_monitor->has_segment = FALSE;
1141   pad_monitor->is_eos = FALSE;
1142   pad_monitor->last_flow_return = GST_FLOW_OK;
1143   gst_caps_replace (&pad_monitor->last_caps, NULL);
1144   pad_monitor->caps_is_audio = pad_monitor->caps_is_video = FALSE;
1145
1146   g_list_free_full (pad_monitor->expired_events,
1147       (GDestroyNotify) gst_event_unref);
1148   pad_monitor->expired_events = NULL;
1149
1150   if (pad_monitor->serialized_events->len)
1151     g_ptr_array_remove_range (pad_monitor->serialized_events, 0,
1152         pad_monitor->serialized_events->len);
1153 }
1154
1155 /* common checks for both sink and src event functions */
1156 static void
1157 gst_validate_pad_monitor_common_event_check (GstValidatePadMonitor *
1158     pad_monitor, GstEvent * event)
1159 {
1160   guint32 seqnum = gst_event_get_seqnum (event);
1161
1162   switch (GST_EVENT_TYPE (event)) {
1163     case GST_EVENT_FLUSH_START:
1164     {
1165       if (pad_monitor->pending_flush_start_seqnum) {
1166         if (seqnum == pad_monitor->pending_flush_start_seqnum) {
1167           pad_monitor->pending_flush_start_seqnum = 0;
1168         } else {
1169           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1170               "The expected flush-start seqnum should be the same as the "
1171               "one from the event that caused it (probably a seek). Got: %u."
1172               " Expected: %u", seqnum, pad_monitor->pending_flush_start_seqnum);
1173         }
1174       }
1175
1176       if (pad_monitor->pending_flush_stop) {
1177         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_START_UNEXPECTED,
1178             "Received flush-start from " " when flush-stop was expected");
1179       }
1180       pad_monitor->pending_flush_stop = TRUE;
1181     }
1182       break;
1183     case GST_EVENT_FLUSH_STOP:
1184     {
1185       if (pad_monitor->pending_flush_stop_seqnum) {
1186         if (seqnum == pad_monitor->pending_flush_stop_seqnum) {
1187           pad_monitor->pending_flush_stop_seqnum = 0;
1188         } else {
1189           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1190               "The expected flush-stop seqnum should be the same as the "
1191               "one from the event that caused it (probably a seek). Got: %u."
1192               " Expected: %u", seqnum, pad_monitor->pending_flush_stop_seqnum);
1193         }
1194       }
1195
1196       if (!pad_monitor->pending_flush_stop) {
1197         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_STOP_UNEXPECTED,
1198             "Unexpected flush-stop %p" GST_PTR_FORMAT, event);
1199       }
1200       pad_monitor->pending_flush_stop = FALSE;
1201
1202       /* cleanup our data */
1203       gst_validate_pad_monitor_flush (pad_monitor);
1204     }
1205       break;
1206     default:
1207       break;
1208   }
1209 }
1210
1211 static gboolean
1212 gst_validate_pad_monitor_downstream_event_check (GstValidatePadMonitor *
1213     pad_monitor, GstObject * parent, GstEvent * event,
1214     GstPadEventFunction handler)
1215 {
1216   gboolean ret = TRUE;
1217   const GstSegment *segment;
1218   guint32 seqnum = gst_event_get_seqnum (event);
1219   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1220
1221   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1222
1223   /* pre checks */
1224   switch (GST_EVENT_TYPE (event)) {
1225     case GST_EVENT_SEGMENT:
1226       /* parse segment data to be used if event is handled */
1227       gst_event_parse_segment (event, &segment);
1228
1229       if (pad_monitor->pending_newsegment_seqnum) {
1230         if (pad_monitor->pending_newsegment_seqnum == seqnum) {
1231           pad_monitor->pending_newsegment_seqnum = 0;
1232         } else {
1233           /* TODO is this an error? could be a segment from the start
1234            * received just before the seek segment */
1235         }
1236       }
1237
1238       /* got a segment, no need for EOS now */
1239       pad_monitor->pending_eos_seqnum = 0;
1240
1241       if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1242         gst_validate_pad_monitor_add_expected_newsegment (pad_monitor, event);
1243       } else {
1244         /* check if this segment is the expected one */
1245         if (pad_monitor->expected_segment) {
1246           const GstSegment *exp_segment;
1247
1248           if (pad_monitor->expected_segment != event) {
1249             gst_event_parse_segment (pad_monitor->expected_segment,
1250                 &exp_segment);
1251             if (segment->format == exp_segment->format) {
1252               if ((exp_segment->rate * exp_segment->applied_rate !=
1253                       segment->rate * segment->applied_rate)
1254                   || exp_segment->start != segment->start
1255                   || exp_segment->stop != segment->stop
1256                   || exp_segment->position != segment->position) {
1257                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1258                     "Expected segment didn't match received segment event");
1259               }
1260             }
1261           }
1262           gst_event_replace (&pad_monitor->expected_segment, NULL);
1263         }
1264       }
1265       break;
1266     case GST_EVENT_CAPS:{
1267       GstCaps *caps;
1268
1269       gst_event_parse_caps (event, &caps);
1270       gst_validate_pad_monitor_setcaps_pre (pad_monitor, caps);
1271       break;
1272     }
1273     case GST_EVENT_EOS:
1274       pad_monitor->is_eos = TRUE;
1275       if (pad_monitor->pending_eos_seqnum &&
1276           pad_monitor->pending_eos_seqnum != seqnum) {
1277         GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1278             "The expected EOS seqnum should be the same as the "
1279             "one from the seek that caused it. Got: %u."
1280             " Expected: %u", seqnum, pad_monitor->pending_eos_seqnum);
1281       }
1282       /*
1283        * TODO add end of stream checks for
1284        *  - events not pushed
1285        *  - buffer data not pushed
1286        *  - pending events not received
1287        */
1288       break;
1289
1290       /* both flushes are handled by the common event function */
1291     case GST_EVENT_FLUSH_START:
1292     case GST_EVENT_FLUSH_STOP:
1293     case GST_EVENT_TAG:
1294     case GST_EVENT_SINK_MESSAGE:
1295     default:
1296       break;
1297   }
1298
1299   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1300   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1301   gst_validate_pad_monitor_event_overrides (pad_monitor, event);
1302   if (handler) {
1303     gst_event_ref (event);
1304     ret = pad_monitor->event_func (pad, parent, event);
1305   }
1306   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1307   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1308
1309   /* post checks */
1310   switch (GST_EVENT_TYPE (event)) {
1311     case GST_EVENT_SEGMENT:
1312       if (ret) {
1313         if (!pad_monitor->has_segment
1314             && pad_monitor->segment.format != segment->format) {
1315           gst_segment_init (&pad_monitor->segment, segment->format);
1316         }
1317         gst_segment_copy_into (segment, &pad_monitor->segment);
1318         pad_monitor->has_segment = TRUE;
1319       }
1320       break;
1321     case GST_EVENT_CAPS:{
1322       GstCaps *caps;
1323
1324       gst_event_parse_caps (event, &caps);
1325       gst_validate_pad_monitor_setcaps_post (pad_monitor, caps, ret);
1326       break;
1327     }
1328     case GST_EVENT_FLUSH_START:
1329     case GST_EVENT_FLUSH_STOP:
1330     case GST_EVENT_EOS:
1331     case GST_EVENT_TAG:
1332     case GST_EVENT_SINK_MESSAGE:
1333     default:
1334       break;
1335   }
1336
1337   if (handler)
1338     gst_event_unref (event);
1339   return ret;
1340 }
1341
1342 static gboolean
1343 gst_validate_pad_monitor_src_event_check (GstValidatePadMonitor * pad_monitor,
1344     GstObject * parent, GstEvent * event, GstPadEventFunction handler)
1345 {
1346   gboolean ret = TRUE;
1347   gdouble rate;
1348   GstFormat format;
1349   gint64 start, stop;
1350   GstSeekFlags seek_flags;
1351   GstSeekType start_type, stop_type;
1352   guint32 seqnum = gst_event_get_seqnum (event);
1353   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1354
1355   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1356
1357   /* pre checks */
1358   switch (GST_EVENT_TYPE (event)) {
1359     case GST_EVENT_SEEK:
1360     {
1361       gst_event_parse_seek (event, &rate, &format, &seek_flags, &start_type,
1362           &start, &stop_type, &stop);
1363       /* upstream seek - store the seek event seqnum to check
1364        * flushes and newsegments share the same */
1365
1366       /* TODO we might need to use a list as multiple seeks can be sent
1367        * before the flushes arrive here */
1368       if (seek_flags & GST_SEEK_FLAG_FLUSH) {
1369         pad_monitor->pending_flush_start_seqnum = seqnum;
1370         pad_monitor->pending_flush_stop_seqnum = seqnum;
1371       }
1372       pad_monitor->pending_newsegment_seqnum = seqnum;
1373       pad_monitor->pending_eos_seqnum = seqnum;
1374     }
1375       break;
1376       /* both flushes are handled by the common event handling function */
1377     case GST_EVENT_FLUSH_START:
1378     case GST_EVENT_FLUSH_STOP:
1379     case GST_EVENT_NAVIGATION:
1380     case GST_EVENT_LATENCY:
1381     case GST_EVENT_STEP:
1382     case GST_EVENT_QOS:
1383     default:
1384       break;
1385   }
1386
1387   if (handler) {
1388     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1389     gst_event_ref (event);
1390     ret = pad_monitor->event_func (pad, parent, event);
1391     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1392   }
1393
1394   /* post checks */
1395   switch (GST_EVENT_TYPE (event)) {
1396     case GST_EVENT_FLUSH_START:
1397     case GST_EVENT_FLUSH_STOP:
1398     case GST_EVENT_QOS:
1399     case GST_EVENT_SEEK:
1400     {
1401       if (ret == FALSE) {
1402         /* do not expect any of these events anymore */
1403         pad_monitor->pending_flush_start_seqnum = 0;
1404         pad_monitor->pending_flush_stop_seqnum = 0;
1405         pad_monitor->pending_newsegment_seqnum = 0;
1406         pad_monitor->pending_eos_seqnum = 0;
1407       }
1408     }
1409       break;
1410     case GST_EVENT_NAVIGATION:
1411     case GST_EVENT_LATENCY:
1412     case GST_EVENT_STEP:
1413     default:
1414       break;
1415   }
1416
1417   if (handler)
1418     gst_event_unref (event);
1419   return ret;
1420 }
1421
1422 static GstFlowReturn
1423 gst_validate_pad_monitor_chain_func (GstPad * pad, GstObject * parent,
1424     GstBuffer * buffer)
1425 {
1426   GstValidatePadMonitor *pad_monitor =
1427       g_object_get_data ((GObject *) pad, "validate-monitor");
1428   GstFlowReturn ret;
1429
1430   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1431   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1432
1433   gst_validate_pad_monitor_check_first_buffer (pad_monitor, buffer);
1434   gst_validate_pad_monitor_update_buffer_data (pad_monitor, buffer);
1435
1436   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1437   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1438
1439   gst_validate_pad_monitor_buffer_overrides (pad_monitor, buffer);
1440
1441   ret = pad_monitor->chain_func (pad, parent, buffer);
1442
1443   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1444   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1445
1446   pad_monitor->last_flow_return = ret;
1447   if (PAD_PARENT_IS_DEMUXER (pad_monitor))
1448     gst_validate_pad_monitor_check_aggregated_return (pad_monitor, ret);
1449
1450   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1451   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1452
1453   return ret;
1454 }
1455
1456 static gboolean
1457 gst_validate_pad_monitor_event_is_tracked (GstValidatePadMonitor * monitor,
1458     GstEvent * event)
1459 {
1460   if (!GST_EVENT_IS_SERIALIZED (event)) {
1461     return FALSE;
1462   }
1463
1464   /* we don't track Tag events because they mutate too much and it is hard
1465    * to match a tag event pushed on a source pad with the one that was received
1466    * on a sink pad.
1467    * One idea would be to use seqnum, but it seems that it is undefined whether
1468    * seqnums should be maintained in tag events that are created from others
1469    * up to today. (2013-08-29)
1470    */
1471   if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
1472     return FALSE;
1473
1474   return TRUE;
1475 }
1476
1477 static gboolean
1478 gst_validate_pad_monitor_sink_event_func (GstPad * pad, GstObject * parent,
1479     GstEvent * event)
1480 {
1481   GstValidatePadMonitor *pad_monitor =
1482       g_object_get_data ((GObject *) pad, "validate-monitor");
1483   gboolean ret;
1484
1485   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1486   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1487
1488   if (gst_validate_pad_monitor_event_is_tracked (pad_monitor, event)) {
1489     GstClockTime last_ts = GST_CLOCK_TIME_NONE;
1490     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_timestamp)) {
1491       last_ts = pad_monitor->current_timestamp;
1492       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_duration)) {
1493         last_ts += pad_monitor->current_duration;
1494       }
1495     }
1496     gst_validate_pad_monitor_otherpad_add_pending_serialized_event (pad_monitor,
1497         event, last_ts);
1498   }
1499
1500   ret =
1501       gst_validate_pad_monitor_downstream_event_check (pad_monitor, parent,
1502       event, pad_monitor->event_func);
1503
1504   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1505   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1506   return ret;
1507 }
1508
1509 static gboolean
1510 gst_validate_pad_monitor_src_event_func (GstPad * pad, GstObject * parent,
1511     GstEvent * event)
1512 {
1513   GstValidatePadMonitor *pad_monitor =
1514       g_object_get_data ((GObject *) pad, "validate-monitor");
1515   gboolean ret;
1516
1517   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1518   ret = gst_validate_pad_monitor_src_event_check (pad_monitor, parent, event,
1519       pad_monitor->event_func);
1520   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1521   return ret;
1522 }
1523
1524 static gboolean
1525 gst_validate_pad_monitor_query_func (GstPad * pad, GstObject * parent,
1526     GstQuery * query)
1527 {
1528   GstValidatePadMonitor *pad_monitor =
1529       g_object_get_data ((GObject *) pad, "validate-monitor");
1530   gboolean ret;
1531
1532   gst_validate_pad_monitor_query_overrides (pad_monitor, query);
1533
1534   ret = pad_monitor->query_func (pad, parent, query);
1535
1536   if (ret) {
1537     switch (GST_QUERY_TYPE (query)) {
1538       case GST_QUERY_CAPS:{
1539         GstCaps *res;
1540         /* We shouldn't need to lock the parent as this doesn't modify
1541          * other monitors, just does some peer_pad_caps */
1542         GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1543
1544         gst_query_parse_caps_result (query, &res);
1545         if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1546           gst_validate_pad_monitor_check_caps_fields_proxied (pad_monitor, res);
1547         }
1548         GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1549         break;
1550       }
1551       default:
1552         break;
1553     }
1554   }
1555
1556   return ret;
1557 }
1558
1559 static gboolean
1560 gst_validate_pad_monitor_activatemode_func (GstPad * pad, GstObject * parent,
1561     GstPadMode mode, gboolean active)
1562 {
1563   GstValidatePadMonitor *pad_monitor =
1564       g_object_get_data ((GObject *) pad, "validate-monitor");
1565   gboolean ret = TRUE;
1566
1567   /* TODO add overrides for activate func */
1568
1569   if (pad_monitor->activatemode_func)
1570     ret = pad_monitor->activatemode_func (pad, parent, mode, active);
1571   if (ret && active == FALSE) {
1572     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1573     gst_validate_pad_monitor_flush (pad_monitor);
1574     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1575   }
1576
1577   return ret;
1578 }
1579
1580 static gboolean
1581 gst_validate_pad_get_range_func (GstPad * pad, GstObject * parent,
1582     guint64 offset, guint size, GstBuffer ** buffer)
1583 {
1584   GstValidatePadMonitor *pad_monitor =
1585       g_object_get_data ((GObject *) pad, "validate-monitor");
1586   gboolean ret;
1587   ret = pad_monitor->getrange_func (pad, parent, offset, size, buffer);
1588   return ret;
1589 }
1590
1591 static gboolean
1592 gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
1593     gpointer udata)
1594 {
1595   GstValidatePadMonitor *monitor = udata;
1596
1597   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1598   GST_VALIDATE_MONITOR_LOCK (monitor);
1599
1600   gst_validate_pad_monitor_check_first_buffer (monitor, buffer);
1601   gst_validate_pad_monitor_update_buffer_data (monitor, buffer);
1602
1603   if (PAD_PARENT_IS_DECODER (monitor) || PAD_PARENT_IS_ENCODER (monitor)) {
1604     GstClockTime tolerance = 0;
1605
1606     if (monitor->caps_is_audio)
1607       tolerance = AUDIO_TIMESTAMP_TOLERANCE;
1608
1609     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range (monitor,
1610         buffer, tolerance);
1611   }
1612
1613   gst_validate_pad_monitor_check_late_serialized_events (monitor,
1614       GST_BUFFER_TIMESTAMP (buffer));
1615
1616   /* a GstValidatePadMonitor parent must be a GstValidateElementMonitor */
1617   if (PAD_PARENT_IS_DECODER (monitor)) {
1618
1619     /* should not push out of segment data */
1620     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)) &&
1621         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)) &&
1622         !gst_segment_clip (&monitor->segment, monitor->segment.format,
1623             GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer) +
1624             GST_BUFFER_DURATION (buffer), NULL, NULL)) {
1625       /* TODO is this a timestamp issue? */
1626       GST_VALIDATE_REPORT (monitor, BUFFER_IS_OUT_OF_SEGMENT,
1627           "buffer is out of segment and shouldn't be pushed. Timestamp: %"
1628           GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT ". Range: %"
1629           GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1630           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1631           GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
1632           GST_TIME_ARGS (monitor->segment.start),
1633           GST_TIME_ARGS (monitor->segment.stop));
1634     }
1635   }
1636
1637   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1638   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1639   gst_validate_pad_monitor_buffer_probe_overrides (monitor, buffer);
1640   return TRUE;
1641 }
1642
1643 static gboolean
1644 gst_validate_pad_monitor_event_probe (GstPad * pad, GstEvent * event,
1645     gpointer udata)
1646 {
1647   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (udata);
1648   gboolean ret;
1649
1650   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1651   GST_VALIDATE_MONITOR_LOCK (monitor);
1652
1653   GST_DEBUG_OBJECT (pad, "event %p %s", event, GST_EVENT_TYPE_NAME (event));
1654
1655   if (GST_EVENT_IS_SERIALIZED (event)) {
1656     gint i;
1657
1658     /* Detect if events the element received are being forwarded in the same order
1659      *
1660      * Several scenarios:
1661      * 1) The element pushes the event as-is
1662      * 2) The element consumes the event and does not forward it
1663      * 3) The element consumes the event and creates another one instead
1664      * 4) The element pushes other serialized event before pushing out the
1665      *    one it received
1666      *
1667      * For each pad we have two lists to track serialized events:
1668      *  1) We received on input and expect to see (serialized_events)
1669      *  2) We received on input but don't expect to see (expired_events)
1670      *
1671      * To detect events that are pushed in a different order from the one they were
1672      * received in we check that:
1673      *
1674      * For each event being outputted:
1675      *   If it is in the expired_events list:
1676      *     RAISE WARNING
1677      *   If it is in the serialized_events list:
1678      *     If there are other events that were received before:
1679      *        Put those events on the expired_events list
1680      *     Remove that event and any previous ones from the serialized_events list
1681      *
1682      * Clear expired events list when flushing or on pad deactivation
1683      *
1684      */
1685
1686     if (g_list_find (monitor->expired_events, event)) {
1687       /* If it's the expired events, we've failed */
1688       GST_WARNING_OBJECT (pad, "Did not expect event %p %s", event,
1689           GST_EVENT_TYPE_NAME (event));
1690       GST_VALIDATE_REPORT (monitor, EVENT_SERIALIZED_OUT_OF_ORDER,
1691           "Serialized event was pushed out of order: %" GST_PTR_FORMAT, event);
1692       monitor->expired_events = g_list_remove (monitor->expired_events, event);
1693       gst_event_unref (event);  /* remove the ref that was on the list */
1694     } else if (monitor->serialized_events->len) {
1695       for (i = 0; i < monitor->serialized_events->len; i++) {
1696         SerializedEventData *next_event =
1697             g_ptr_array_index (monitor->serialized_events, i);
1698         GST_DEBUG_OBJECT (pad, "Checking against stored event #%d: %p %s", i,
1699             next_event->event, GST_EVENT_TYPE_NAME (next_event->event));
1700
1701         if (event == next_event->event
1702             || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1703           /* We have found our event */
1704           GST_DEBUG_OBJECT (pad, "Found matching event");
1705
1706           while (monitor->serialized_events->len > i
1707               && GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1708             /* Swallow all expected events of the same type */
1709             g_ptr_array_remove_index (monitor->serialized_events, i);
1710             next_event = g_ptr_array_index (monitor->serialized_events, i);
1711           }
1712
1713           /* Move all previous events to expired events */
1714           if (G_UNLIKELY (i > 0)) {
1715             GST_DEBUG_OBJECT (pad,
1716                 "Moving previous expected events to expired list");
1717             while (i--) {
1718               next_event = g_ptr_array_index (monitor->serialized_events, 0);
1719               monitor->expired_events =
1720                   g_list_append (monitor->expired_events,
1721                   gst_event_ref (next_event->event));
1722               g_ptr_array_remove_index (monitor->serialized_events, 0);
1723             }
1724           }
1725           debug_pending_event (pad, monitor->serialized_events);
1726           break;
1727         }
1728       }
1729     }
1730   }
1731
1732   /* This so far is just like an event that is flowing downstream,
1733    * so we do the same checks as a sinkpad event handler */
1734   ret =
1735       gst_validate_pad_monitor_downstream_event_check (monitor, NULL, event,
1736       NULL);
1737   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1738   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1739
1740   return ret;
1741 }
1742
1743 static GstPadProbeReturn
1744 gst_validate_pad_monitor_pad_probe (GstPad * pad, GstPadProbeInfo * info,
1745     gpointer udata)
1746 {
1747   if (info->type & GST_PAD_PROBE_TYPE_BUFFER)
1748     gst_validate_pad_monitor_buffer_probe (pad, info->data, udata);
1749   else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)
1750     gst_validate_pad_monitor_event_probe (pad, info->data, udata);
1751
1752   return GST_PAD_PROBE_OK;
1753 }
1754
1755 static void
1756 gst_validate_pad_monitor_update_caps_info (GstValidatePadMonitor * pad_monitor,
1757     GstCaps * caps)
1758 {
1759   GstStructure *structure;
1760
1761   g_return_if_fail (gst_caps_is_fixed (caps));
1762
1763   pad_monitor->caps_is_audio = FALSE;
1764   pad_monitor->caps_is_video = FALSE;
1765
1766   structure = gst_caps_get_structure (caps, 0);
1767   if (g_str_has_prefix (gst_structure_get_name (structure), "audio/")) {
1768     pad_monitor->caps_is_audio = TRUE;
1769   } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/")) {
1770     pad_monitor->caps_is_video = TRUE;
1771   }
1772 }
1773
1774 static void
1775 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
1776     GstCaps * caps)
1777 {
1778   GstStructure *structure;
1779
1780   /* Check if caps are identical to last caps and complain if so
1781    * Only checked for sink pads as src pads might push the same caps
1782    * multiple times during unlinked/autoplugging scenarios */
1783   if (GST_PAD_IS_SINK (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)) &&
1784       pad_monitor->last_caps
1785       && gst_caps_is_equal (caps, pad_monitor->last_caps)) {
1786     GST_VALIDATE_REPORT (pad_monitor, EVENT_CAPS_DUPLICATE, "%" GST_PTR_FORMAT,
1787         caps);
1788   }
1789
1790   gst_validate_pad_monitor_check_caps_complete (pad_monitor, caps);
1791
1792   if (caps) {
1793     structure = gst_caps_get_structure (caps, 0);
1794     if (gst_structure_n_fields (pad_monitor->pending_setcaps_fields)) {
1795       gint i;
1796       for (i = 0;
1797           i < gst_structure_n_fields (pad_monitor->pending_setcaps_fields);
1798           i++) {
1799         const gchar *name =
1800             gst_structure_nth_field_name (pad_monitor->pending_setcaps_fields,
1801             i);
1802         const GValue *v = gst_structure_get_value (structure, name);
1803         const GValue *otherv =
1804             gst_structure_get_value (pad_monitor->pending_setcaps_fields, name);
1805
1806         if (v == NULL) {
1807           GST_VALIDATE_REPORT (pad_monitor, CAPS_EXPECTED_FIELD_NOT_FOUND,
1808               "Field %s is missing from setcaps caps '%" GST_PTR_FORMAT "'",
1809               name, caps);
1810         } else if (gst_value_compare (v, otherv) != GST_VALUE_EQUAL) {
1811           GST_VALIDATE_REPORT (pad_monitor, CAPS_FIELD_UNEXPECTED_VALUE,
1812               "Field %s from setcaps caps '%" GST_PTR_FORMAT "' is different "
1813               "from expected value in caps '%" GST_PTR_FORMAT "'", name, caps,
1814               pad_monitor->pending_setcaps_fields);
1815         }
1816       }
1817     }
1818
1819     if (gst_validate_pad_monitor_pad_should_proxy_othercaps (pad_monitor)) {
1820       if (_structure_is_video (structure)) {
1821         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1822             structure, "width");
1823         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1824             structure, "height");
1825         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1826             structure, "framerate");
1827         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1828             structure, "pixel-aspect-ratio");
1829       } else if (_structure_is_audio (structure)) {
1830         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1831             structure, "rate");
1832         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1833             structure, "channels");
1834       }
1835     }
1836   }
1837
1838   gst_structure_free (pad_monitor->pending_setcaps_fields);
1839   pad_monitor->pending_setcaps_fields =
1840       gst_structure_new_empty (PENDING_FIELDS);
1841
1842   gst_validate_pad_monitor_setcaps_overrides (pad_monitor, caps);
1843 }
1844
1845 static void
1846 gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor * pad_monitor,
1847     GstCaps * caps, gboolean ret)
1848 {
1849   if (!ret)
1850     gst_validate_pad_monitor_otherpad_clear_pending_fields (pad_monitor);
1851   else {
1852     if (pad_monitor->last_caps) {
1853       gst_caps_unref (pad_monitor->last_caps);
1854     }
1855     pad_monitor->last_caps = gst_caps_ref (caps);
1856     gst_validate_pad_monitor_update_caps_info (pad_monitor, caps);
1857   }
1858 }
1859
1860 static gboolean
1861 gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
1862 {
1863   GstValidatePadMonitor *pad_monitor = GST_VALIDATE_PAD_MONITOR_CAST (monitor);
1864   GstPad *pad;
1865   if (!GST_IS_PAD (GST_VALIDATE_MONITOR_GET_OBJECT (monitor))) {
1866     GST_WARNING_OBJECT (monitor, "Trying to create pad monitor with other "
1867         "type of object");
1868     return FALSE;
1869   }
1870
1871   pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1872
1873   if (g_object_get_data ((GObject *) pad, "validate-monitor")) {
1874     GST_WARNING_OBJECT (pad_monitor,
1875         "Pad already has a validate-monitor associated");
1876     return FALSE;
1877   }
1878
1879   g_object_set_data ((GObject *) pad, "validate-monitor", pad_monitor);
1880
1881   pad_monitor->pad = pad;
1882
1883   pad_monitor->event_func = GST_PAD_EVENTFUNC (pad);
1884   pad_monitor->query_func = GST_PAD_QUERYFUNC (pad);
1885   pad_monitor->activatemode_func = GST_PAD_ACTIVATEMODEFUNC (pad);
1886   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1887
1888     pad_monitor->chain_func = GST_PAD_CHAINFUNC (pad);
1889     if (pad_monitor->chain_func)
1890       gst_pad_set_chain_function (pad, gst_validate_pad_monitor_chain_func);
1891
1892     gst_pad_set_event_function (pad, gst_validate_pad_monitor_sink_event_func);
1893   } else {
1894     pad_monitor->getrange_func = GST_PAD_GETRANGEFUNC (pad);
1895     if (pad_monitor->getrange_func)
1896       gst_pad_set_getrange_function (pad, gst_validate_pad_get_range_func);
1897
1898     gst_pad_set_event_function (pad, gst_validate_pad_monitor_src_event_func);
1899
1900     /* add buffer/event probes */
1901     pad_monitor->pad_probe_id =
1902         gst_pad_add_probe (pad,
1903         GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
1904         GST_PAD_PROBE_TYPE_EVENT_FLUSH,
1905         (GstPadProbeCallback) gst_validate_pad_monitor_pad_probe, pad_monitor,
1906         NULL);
1907   }
1908   gst_pad_set_query_function (pad, gst_validate_pad_monitor_query_func);
1909   gst_pad_set_activatemode_function (pad,
1910       gst_validate_pad_monitor_activatemode_func);
1911
1912   gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (monitor),
1913       g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad)));
1914
1915   if (G_UNLIKELY (GST_PAD_PARENT (pad) == NULL))
1916     GST_FIXME ("Saw a pad not belonging to any object");
1917
1918   return TRUE;
1919 }