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