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