pad-monitor: use activate-mode function to detect when to clear pad data
[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, "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, "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, "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   if (!GST_CLOCK_TIME_IS_VALID (ts))
464     return;
465
466   for (i = 0; i < monitor->serialized_events->len; i++) {
467     SerializedEventData *data =
468         g_ptr_array_index (monitor->serialized_events, i);
469     if (data->timestamp < ts) {
470       GST_VALIDATE_REPORT (monitor, SERIALIZED_EVENT_WASNT_PUSHED_IN_TIME,
471           "Serialized event %" GST_PTR_FORMAT " wasn't pushed before expected "
472           "timestamp %" GST_TIME_FORMAT " on pad %s:%s", data->event,
473           GST_TIME_ARGS (data->timestamp),
474           GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)));
475     } else {
476       /* events should be ordered by ts */
477       break;
478     }
479   }
480
481   if (i) {
482     debug_pending_event (monitor->pad, monitor->serialized_events);
483     g_ptr_array_remove_range (monitor->serialized_events, 0, i);
484   }
485 }
486
487 static void
488 gst_validate_pad_monitor_dispose (GObject * object)
489 {
490   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (object);
491   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
492
493   if (pad) {
494     if (monitor->pad_probe_id)
495       gst_pad_remove_probe (pad, monitor->pad_probe_id);
496   }
497
498   if (monitor->expected_segment)
499     gst_event_unref (monitor->expected_segment);
500
501   gst_structure_free (monitor->pending_setcaps_fields);
502   g_ptr_array_unref (monitor->serialized_events);
503   g_list_free (monitor->expired_events);
504
505   G_OBJECT_CLASS (parent_class)->dispose (object);
506 }
507
508 static void
509 gst_validate_pad_monitor_class_init (GstValidatePadMonitorClass * klass)
510 {
511   GObjectClass *gobject_class;
512   GstValidateMonitorClass *monitor_klass;
513
514   gobject_class = G_OBJECT_CLASS (klass);
515   monitor_klass = GST_VALIDATE_MONITOR_CLASS (klass);
516
517   gobject_class->dispose = gst_validate_pad_monitor_dispose;
518
519   monitor_klass->setup = gst_validate_pad_monitor_do_setup;
520   monitor_klass->get_element = gst_validate_pad_monitor_get_element;
521 }
522
523 static void
524 gst_validate_pad_monitor_init (GstValidatePadMonitor * pad_monitor)
525 {
526   pad_monitor->pending_setcaps_fields =
527       gst_structure_new_empty (PENDING_FIELDS);
528   pad_monitor->serialized_events =
529       g_ptr_array_new_with_free_func ((GDestroyNotify)
530       _serialized_event_data_free);
531   pad_monitor->expired_events = NULL;
532   gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES);
533   pad_monitor->first_buffer = TRUE;
534
535   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
536   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
537 }
538
539 /**
540  * gst_validate_pad_monitor_new:
541  * @pad: (transfer-none): a #GstPad to run Validate on
542  */
543 GstValidatePadMonitor *
544 gst_validate_pad_monitor_new (GstPad * pad, GstValidateRunner * runner,
545     GstValidateElementMonitor * parent)
546 {
547   GstValidatePadMonitor *monitor = g_object_new (GST_TYPE_VALIDATE_PAD_MONITOR,
548       "object", pad, "qa-runner", runner, "qa-parent",
549       parent, NULL);
550
551   if (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor) == NULL) {
552     g_object_unref (monitor);
553     return NULL;
554   }
555   return monitor;
556 }
557
558 static GstElement *
559 gst_validate_pad_monitor_get_element (GstValidateMonitor * monitor)
560 {
561   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor);
562
563   return GST_PAD_PARENT (pad);
564 }
565
566 static void
567 gst_validate_pad_monitor_event_overrides (GstValidatePadMonitor * pad_monitor,
568     GstEvent * event)
569 {
570   GList *iter;
571
572   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
573   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
574       iter = g_list_next (iter)) {
575     GstValidateOverride *override = iter->data;
576
577     gst_validate_override_event_handler (override,
578         GST_VALIDATE_MONITOR_CAST (pad_monitor), event);
579   }
580   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
581 }
582
583 static void
584 gst_validate_pad_monitor_buffer_overrides (GstValidatePadMonitor * pad_monitor,
585     GstBuffer * buffer)
586 {
587   GList *iter;
588
589   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
590   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
591       iter = g_list_next (iter)) {
592     GstValidateOverride *override = iter->data;
593
594     gst_validate_override_buffer_handler (override,
595         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
596   }
597   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
598 }
599
600 static void
601 gst_validate_pad_monitor_buffer_probe_overrides (GstValidatePadMonitor *
602     pad_monitor, GstBuffer * buffer)
603 {
604   GList *iter;
605
606   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
607   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
608       iter = g_list_next (iter)) {
609     GstValidateOverride *override = iter->data;
610
611     gst_validate_override_buffer_probe_handler (override,
612         GST_VALIDATE_MONITOR_CAST (pad_monitor), buffer);
613   }
614   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
615 }
616
617 static void
618 gst_validate_pad_monitor_query_overrides (GstValidatePadMonitor * pad_monitor,
619     GstQuery * query)
620 {
621   GList *iter;
622
623   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
624   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
625       iter = g_list_next (iter)) {
626     GstValidateOverride *override = iter->data;
627
628     gst_validate_override_query_handler (override,
629         GST_VALIDATE_MONITOR_CAST (pad_monitor), query);
630   }
631   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
632 }
633
634 static void
635 gst_validate_pad_monitor_setcaps_overrides (GstValidatePadMonitor * pad_monitor,
636     GstCaps * caps)
637 {
638   GList *iter;
639
640   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (pad_monitor);
641   for (iter = GST_VALIDATE_MONITOR_OVERRIDES (pad_monitor).head; iter;
642       iter = g_list_next (iter)) {
643     GstValidateOverride *override = iter->data;
644
645     gst_validate_override_setcaps_handler (override,
646         GST_VALIDATE_MONITOR_CAST (pad_monitor), caps);
647   }
648   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (pad_monitor);
649 }
650
651 static gboolean
652 gst_validate_pad_monitor_timestamp_is_in_received_range (GstValidatePadMonitor *
653     monitor, GstClockTime ts)
654 {
655   GST_DEBUG_OBJECT (monitor, "Checking if timestamp %" GST_TIME_FORMAT
656       " is in range: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT " for pad "
657       "%s:%s", GST_TIME_ARGS (ts),
658       GST_TIME_ARGS (monitor->timestamp_range_start),
659       GST_TIME_ARGS (monitor->timestamp_range_end),
660       GST_DEBUG_PAD_NAME (GST_VALIDATE_PAD_MONITOR_GET_PAD (monitor)));
661   return !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_start) ||
662       !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_end) ||
663       (monitor->timestamp_range_start <= ts
664       && ts <= monitor->timestamp_range_end);
665 }
666
667 /* Iterates over internal links (sinkpads) to check that this buffer has
668  * a timestamp that is in the range of the lastly received buffers */
669 static void
670     gst_validate_pad_monitor_check_buffer_timestamp_in_received_range
671     (GstValidatePadMonitor * monitor, GstBuffer * buffer)
672 {
673   GstClockTime ts;
674   GstClockTime ts_end;
675   GstIterator *iter;
676   gboolean has_one = FALSE;
677   gboolean found = FALSE;
678   gboolean done;
679   GstPad *otherpad;
680   GstValidatePadMonitor *othermonitor;
681
682   if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))
683       || !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
684     GST_DEBUG_OBJECT (monitor,
685         "Can't check buffer timestamps range as "
686         "buffer has no valid timestamp/duration");
687     return;
688   }
689   ts = GST_BUFFER_TIMESTAMP (buffer);
690   ts_end = ts + GST_BUFFER_DURATION (buffer);
691
692   iter =
693       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
694       (monitor));
695   done = FALSE;
696   while (!done) {
697     GValue value = { 0, };
698     switch (gst_iterator_next (iter, &value)) {
699       case GST_ITERATOR_OK:
700         otherpad = g_value_get_object (&value);
701         GST_DEBUG_OBJECT (monitor, "Checking pad %s:%s input timestamps",
702             GST_DEBUG_PAD_NAME (otherpad));
703         othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
704         GST_VALIDATE_MONITOR_LOCK (othermonitor);
705         if (gst_validate_pad_monitor_timestamp_is_in_received_range
706             (othermonitor, ts)
707             &&
708             gst_validate_pad_monitor_timestamp_is_in_received_range
709             (othermonitor, ts_end)) {
710           done = TRUE;
711           found = TRUE;
712         }
713         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
714         g_value_reset (&value);
715         has_one = TRUE;
716         break;
717       case GST_ITERATOR_RESYNC:
718         gst_iterator_resync (iter);
719         has_one = FALSE;
720         found = FALSE;
721         break;
722       case GST_ITERATOR_ERROR:
723         GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
724         done = TRUE;
725         break;
726       case GST_ITERATOR_DONE:
727         done = TRUE;
728         break;
729     }
730   }
731   gst_iterator_free (iter);
732
733   if (!has_one) {
734     GST_DEBUG_OBJECT (monitor, "Skipping timestamp in range check as no "
735         "internal linked pad was found");
736     return;
737   }
738   if (!found) {
739     GST_VALIDATE_REPORT (monitor, BUFFER_TIMESTAMP_OUT_OF_RECEIVED_RANGE,
740         "Timestamp %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT
741         " is out of range of received input", GST_TIME_ARGS (ts),
742         GST_TIME_ARGS (ts_end));
743   }
744 }
745
746 static void
747 gst_validate_pad_monitor_check_first_buffer (GstValidatePadMonitor *
748     pad_monitor, GstBuffer * buffer)
749 {
750   if (G_UNLIKELY (pad_monitor->first_buffer)) {
751     pad_monitor->first_buffer = FALSE;
752
753     if (!pad_monitor->has_segment
754         && PAD_IS_IN_PUSH_MODE (GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor)))
755     {
756       GST_VALIDATE_REPORT (pad_monitor, BUFFER_BEFORE_SEGMENT,
757           "Received buffer before Segment event");
758     }
759     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
760       gint64 running_time = gst_segment_to_running_time (&pad_monitor->segment,
761           pad_monitor->segment.format, GST_BUFFER_TIMESTAMP (buffer));
762       if (running_time != 0) {
763         GST_VALIDATE_REPORT (pad_monitor, FIRST_BUFFER_RUNNING_TIME_IS_NOT_ZERO,
764             "First buffer running time is not 0, it is: %" GST_TIME_FORMAT,
765             GST_TIME_ARGS (running_time));
766       }
767     }
768   }
769 }
770
771 static void
772 gst_validate_pad_monitor_update_buffer_data (GstValidatePadMonitor *
773     pad_monitor, GstBuffer * buffer)
774 {
775   pad_monitor->current_timestamp = GST_BUFFER_TIMESTAMP (buffer);
776   pad_monitor->current_duration = GST_BUFFER_DURATION (buffer);
777   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
778     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_start)) {
779       pad_monitor->timestamp_range_start =
780           MIN (pad_monitor->timestamp_range_start,
781           GST_BUFFER_TIMESTAMP (buffer));
782     } else {
783       pad_monitor->timestamp_range_start = GST_BUFFER_TIMESTAMP (buffer);
784     }
785
786     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
787       GstClockTime endts =
788           GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
789       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->timestamp_range_end)) {
790         pad_monitor->timestamp_range_end =
791             MAX (pad_monitor->timestamp_range_end, endts);
792       } else {
793         pad_monitor->timestamp_range_end = endts;
794       }
795     }
796   }
797   GST_DEBUG_OBJECT (pad_monitor, "Current stored range: %" GST_TIME_FORMAT
798       " - %" GST_TIME_FORMAT,
799       GST_TIME_ARGS (pad_monitor->timestamp_range_start),
800       GST_TIME_ARGS (pad_monitor->timestamp_range_end));
801 }
802
803 static GstFlowReturn
804 _combine_flows (GstFlowReturn ret1, GstFlowReturn ret2)
805 {
806   if (ret1 == ret2)
807     return ret1;
808   if (ret1 <= GST_FLOW_NOT_NEGOTIATED)
809     return ret1;
810   if (ret2 <= GST_FLOW_NOT_NEGOTIATED)
811     return ret2;
812   if (ret1 == GST_FLOW_FLUSHING || ret2 == GST_FLOW_FLUSHING)
813     return GST_FLOW_FLUSHING;
814   if (ret1 == GST_FLOW_OK || ret2 == GST_FLOW_OK)
815     return GST_FLOW_OK;
816   return ret2;
817 }
818
819 static void
820 gst_validate_pad_monitor_check_aggregated_return (GstValidatePadMonitor *
821     monitor, GstFlowReturn ret)
822 {
823   GstIterator *iter;
824   gboolean done;
825   GstPad *otherpad;
826   GstPad *peerpad;
827   GstValidatePadMonitor *othermonitor;
828   GstFlowReturn aggregated = GST_FLOW_NOT_LINKED;
829   gboolean found_a_pad = FALSE;
830
831   iter =
832       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
833       (monitor));
834   done = FALSE;
835   while (!done) {
836     GValue value = { 0, };
837     switch (gst_iterator_next (iter, &value)) {
838       case GST_ITERATOR_OK:
839         otherpad = g_value_get_object (&value);
840         peerpad = gst_pad_get_peer (otherpad);
841         if (peerpad) {
842           othermonitor = g_object_get_data ((GObject *) peerpad, "qa-monitor");
843           if (othermonitor) {
844             found_a_pad = TRUE;
845             GST_VALIDATE_MONITOR_LOCK (othermonitor);
846             aggregated =
847                 _combine_flows (aggregated, othermonitor->last_flow_return);
848             GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
849           }
850
851           gst_object_unref (peerpad);
852         }
853         g_value_reset (&value);
854         break;
855       case GST_ITERATOR_RESYNC:
856         gst_iterator_resync (iter);
857         break;
858       case GST_ITERATOR_ERROR:
859         GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
860         done = TRUE;
861         break;
862       case GST_ITERATOR_DONE:
863         done = TRUE;
864         break;
865     }
866   }
867   gst_iterator_free (iter);
868   if (!found_a_pad) {
869     /* no peer pad found, nothing to do */
870     return;
871   }
872   if (aggregated == GST_FLOW_OK || aggregated == GST_FLOW_EOS) {
873     /* those are acceptable situations */
874
875     if (monitor->is_eos && ret == GST_FLOW_EOS) {
876       /* this element received eos and returned eos */
877       return;
878     }
879
880     if (PAD_PARENT_IS_DEMUXER (monitor) && ret == GST_FLOW_EOS) {
881       /* a demuxer can return EOS when the samples end */
882       return;
883     }
884   }
885
886   if (aggregated != ret) {
887     GST_VALIDATE_REPORT (monitor, WRONG_FLOW_RETURN,
888         "Wrong combined flow return %s(%d). Expected: %s(%d)",
889         gst_flow_get_name (ret), ret, gst_flow_get_name (aggregated),
890         aggregated);
891   }
892 }
893
894 static void
895     gst_validate_pad_monitor_otherpad_add_pending_serialized_event
896     (GstValidatePadMonitor * monitor, GstEvent * event, GstClockTime last_ts)
897 {
898   GstIterator *iter;
899   gboolean done;
900   GstPad *otherpad;
901   GstValidatePadMonitor *othermonitor;
902
903   if (!GST_EVENT_IS_SERIALIZED (event))
904     return;
905
906   iter =
907       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
908       (monitor));
909   if (iter == NULL) {
910     /* inputselector will return NULL if the sinkpad is not the active one .... */
911     GST_FIXME_OBJECT (GST_VALIDATE_PAD_MONITOR_GET_PAD
912         (monitor), "No iterator");
913     return;
914   }
915   done = FALSE;
916   while (!done) {
917     GValue value = { 0, };
918     switch (gst_iterator_next (iter, &value)) {
919       case GST_ITERATOR_OK:
920         otherpad = g_value_get_object (&value);
921         othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
922         if (othermonitor) {
923           SerializedEventData *data = g_slice_new0 (SerializedEventData);
924           data->timestamp = last_ts;
925           data->event = gst_event_ref (event);
926           GST_VALIDATE_MONITOR_LOCK (othermonitor);
927           GST_DEBUG_OBJECT (monitor->pad, "Storing for pad %s:%s event %p %s",
928               GST_DEBUG_PAD_NAME (otherpad), event,
929               GST_EVENT_TYPE_NAME (event));
930           g_ptr_array_add (othermonitor->serialized_events, data);
931           debug_pending_event (otherpad, othermonitor->serialized_events);
932           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
933         }
934         g_value_reset (&value);
935         break;
936       case GST_ITERATOR_RESYNC:
937         gst_iterator_resync (iter);
938         break;
939       case GST_ITERATOR_ERROR:
940         GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
941         done = TRUE;
942         break;
943       case GST_ITERATOR_DONE:
944         done = TRUE;
945         break;
946     }
947   }
948   gst_iterator_free (iter);
949 }
950
951 static void
952 gst_validate_pad_monitor_otherpad_add_pending_field (GstValidatePadMonitor *
953     monitor, GstStructure * structure, const gchar * field)
954 {
955   GstIterator *iter;
956   gboolean done;
957   GstPad *otherpad;
958   GstValidatePadMonitor *othermonitor;
959   const GValue *v;
960
961   v = gst_structure_get_value (structure, field);
962   if (v == NULL) {
963     GST_DEBUG_OBJECT (monitor, "Not adding pending field %s as it isn't "
964         "present on structure %" GST_PTR_FORMAT, field, structure);
965     return;
966   }
967
968   iter =
969       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
970       (monitor));
971   done = FALSE;
972   while (!done) {
973     GValue value = { 0, };
974     switch (gst_iterator_next (iter, &value)) {
975       case GST_ITERATOR_OK:
976         otherpad = g_value_get_object (&value);
977         othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
978         if (othermonitor) {
979           GST_VALIDATE_MONITOR_LOCK (othermonitor);
980           g_assert (othermonitor->pending_setcaps_fields != NULL);
981           gst_structure_set_value (othermonitor->pending_setcaps_fields,
982               field, v);
983           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
984         }
985         g_value_reset (&value);
986         break;
987       case GST_ITERATOR_RESYNC:
988         gst_iterator_resync (iter);
989         break;
990       case GST_ITERATOR_ERROR:
991         GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
992         done = TRUE;
993         break;
994       case GST_ITERATOR_DONE:
995         done = TRUE;
996         break;
997     }
998   }
999   gst_iterator_free (iter);
1000 }
1001
1002 static void
1003 gst_validate_pad_monitor_otherpad_clear_pending_fields (GstValidatePadMonitor *
1004     monitor)
1005 {
1006   GstIterator *iter;
1007   gboolean done;
1008   GstPad *otherpad;
1009   GstValidatePadMonitor *othermonitor;
1010
1011   iter =
1012       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1013       (monitor));
1014   done = FALSE;
1015   while (!done) {
1016     GValue value = { 0, };
1017     switch (gst_iterator_next (iter, &value)) {
1018       case GST_ITERATOR_OK:
1019         otherpad = g_value_get_object (&value);
1020         othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
1021         if (othermonitor) {
1022           GST_VALIDATE_MONITOR_LOCK (othermonitor);
1023           g_assert (othermonitor->pending_setcaps_fields != NULL);
1024           gst_structure_free (othermonitor->pending_setcaps_fields);
1025           othermonitor->pending_setcaps_fields =
1026               gst_structure_new_empty (PENDING_FIELDS);
1027           GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1028         }
1029         g_value_reset (&value);
1030         break;
1031       case GST_ITERATOR_RESYNC:
1032         gst_iterator_resync (iter);
1033         break;
1034       case GST_ITERATOR_ERROR:
1035         GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
1036         done = TRUE;
1037         break;
1038       case GST_ITERATOR_DONE:
1039         done = TRUE;
1040         break;
1041     }
1042   }
1043   gst_iterator_free (iter);
1044 }
1045
1046 static void
1047 gst_validate_pad_monitor_add_expected_newsegment (GstValidatePadMonitor *
1048     monitor, GstEvent * event)
1049 {
1050   GstIterator *iter;
1051   gboolean done;
1052   GstPad *otherpad;
1053   GstValidatePadMonitor *othermonitor;
1054
1055   iter =
1056       gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
1057       (monitor));
1058   done = FALSE;
1059   while (!done) {
1060     GValue value = { 0, };
1061     switch (gst_iterator_next (iter, &value)) {
1062       case GST_ITERATOR_OK:
1063         otherpad = g_value_get_object (&value);
1064         othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
1065         GST_VALIDATE_MONITOR_LOCK (othermonitor);
1066         if (othermonitor->expected_segment) {
1067           GST_VALIDATE_REPORT (othermonitor, EVENT_NEWSEGMENT_NOT_PUSHED, "");
1068           gst_event_unref (othermonitor->expected_segment);
1069         }
1070         othermonitor->expected_segment = gst_event_ref (event);
1071         GST_VALIDATE_MONITOR_UNLOCK (othermonitor);
1072         g_value_reset (&value);
1073         break;
1074       case GST_ITERATOR_RESYNC:
1075         gst_iterator_resync (iter);
1076         break;
1077       case GST_ITERATOR_ERROR:
1078         GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
1079         done = TRUE;
1080         break;
1081       case GST_ITERATOR_DONE:
1082         done = TRUE;
1083         break;
1084     }
1085   }
1086   gst_iterator_free (iter);
1087 }
1088
1089 static void
1090 gst_validate_pad_monitor_flush (GstValidatePadMonitor * pad_monitor)
1091 {
1092   pad_monitor->current_timestamp = GST_CLOCK_TIME_NONE;
1093   pad_monitor->current_duration = GST_CLOCK_TIME_NONE;
1094   pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
1095   pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
1096   pad_monitor->has_segment = FALSE;
1097   pad_monitor->is_eos = FALSE;
1098   gst_caps_replace (&pad_monitor->last_caps, NULL);
1099
1100   g_list_free_full (pad_monitor->expired_events,
1101       (GDestroyNotify) gst_event_unref);
1102   pad_monitor->expired_events = NULL;
1103
1104   if (pad_monitor->serialized_events->len)
1105     g_ptr_array_remove_range (pad_monitor->serialized_events, 0,
1106         pad_monitor->serialized_events->len);
1107 }
1108
1109 /* common checks for both sink and src event functions */
1110 static void
1111 gst_validate_pad_monitor_common_event_check (GstValidatePadMonitor *
1112     pad_monitor, GstEvent * event)
1113 {
1114   guint32 seqnum = gst_event_get_seqnum (event);
1115
1116   switch (GST_EVENT_TYPE (event)) {
1117     case GST_EVENT_FLUSH_START:
1118     {
1119       if (pad_monitor->pending_flush_start_seqnum) {
1120         if (seqnum == pad_monitor->pending_flush_start_seqnum) {
1121           pad_monitor->pending_flush_start_seqnum = 0;
1122         } else {
1123           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1124               "The expected flush-start seqnum should be the same as the "
1125               "one from the event that caused it (probably a seek). Got: %u."
1126               " Expected: %u", seqnum, pad_monitor->pending_flush_start_seqnum);
1127         }
1128       }
1129
1130       if (pad_monitor->pending_flush_stop) {
1131         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_START_UNEXPECTED,
1132             "Received flush-start from " " when flush-stop was expected");
1133       }
1134       pad_monitor->pending_flush_stop = TRUE;
1135     }
1136       break;
1137     case GST_EVENT_FLUSH_STOP:
1138     {
1139       if (pad_monitor->pending_flush_stop_seqnum) {
1140         if (seqnum == pad_monitor->pending_flush_stop_seqnum) {
1141           pad_monitor->pending_flush_stop_seqnum = 0;
1142         } else {
1143           GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1144               "The expected flush-stop seqnum should be the same as the "
1145               "one from the event that caused it (probably a seek). Got: %u."
1146               " Expected: %u", seqnum, pad_monitor->pending_flush_stop_seqnum);
1147         }
1148       }
1149
1150       if (!pad_monitor->pending_flush_stop) {
1151         GST_VALIDATE_REPORT (pad_monitor, EVENT_FLUSH_STOP_UNEXPECTED,
1152             "Unexpected flush-stop %p" GST_PTR_FORMAT, event);
1153       }
1154       pad_monitor->pending_flush_stop = FALSE;
1155
1156       /* cleanup our data */
1157       gst_validate_pad_monitor_flush (pad_monitor);
1158     }
1159       break;
1160     default:
1161       break;
1162   }
1163 }
1164
1165 static gboolean
1166 gst_validate_pad_monitor_downstream_event_check (GstValidatePadMonitor *
1167     pad_monitor, GstObject * parent, GstEvent * event,
1168     GstPadEventFunction handler)
1169 {
1170   gboolean ret = TRUE;
1171   const GstSegment *segment;
1172   guint32 seqnum = gst_event_get_seqnum (event);
1173   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1174
1175   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1176
1177   /* pre checks */
1178   switch (GST_EVENT_TYPE (event)) {
1179     case GST_EVENT_SEGMENT:
1180       /* parse segment data to be used if event is handled */
1181       gst_event_parse_segment (event, &segment);
1182
1183       if (pad_monitor->pending_newsegment_seqnum) {
1184         if (pad_monitor->pending_newsegment_seqnum == seqnum) {
1185           pad_monitor->pending_newsegment_seqnum = 0;
1186         } else {
1187           /* TODO is this an error? could be a segment from the start
1188            * received just before the seek segment */
1189         }
1190       }
1191
1192       /* got a segment, no need for EOS now */
1193       pad_monitor->pending_eos_seqnum = 0;
1194
1195       if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1196         gst_validate_pad_monitor_add_expected_newsegment (pad_monitor, event);
1197       } else {
1198         /* check if this segment is the expected one */
1199         if (pad_monitor->expected_segment) {
1200           const GstSegment *exp_segment;
1201
1202           if (pad_monitor->expected_segment != event) {
1203             gst_event_parse_segment (pad_monitor->expected_segment,
1204                 &exp_segment);
1205             if (segment->format == exp_segment->format) {
1206               if ((exp_segment->rate * exp_segment->applied_rate !=
1207                       segment->rate * segment->applied_rate)
1208                   || exp_segment->start != segment->start
1209                   || exp_segment->stop != segment->stop
1210                   || exp_segment->position != segment->position) {
1211                 GST_VALIDATE_REPORT (pad_monitor, EVENT_NEW_SEGMENT_MISMATCH,
1212                     "Expected segment didn't match received segment event");
1213               }
1214             }
1215           }
1216           gst_event_replace (&pad_monitor->expected_segment, NULL);
1217         }
1218       }
1219       break;
1220     case GST_EVENT_EOS:
1221       pad_monitor->is_eos = TRUE;
1222       if (pad_monitor->pending_eos_seqnum &&
1223           pad_monitor->pending_eos_seqnum != seqnum) {
1224         GST_VALIDATE_REPORT (pad_monitor, EVENT_HAS_WRONG_SEQNUM,
1225             "The expected EOS seqnum should be the same as the "
1226             "one from the seek that caused it. Got: %u."
1227             " Expected: %u", seqnum, pad_monitor->pending_eos_seqnum);
1228       }
1229       /*
1230        * TODO add end of stream checks for
1231        *  - events not pushed
1232        *  - buffer data not pushed
1233        *  - pending events not received
1234        */
1235       break;
1236
1237       /* both flushes are handled by the common event function */
1238     case GST_EVENT_FLUSH_START:
1239     case GST_EVENT_FLUSH_STOP:
1240     case GST_EVENT_TAG:
1241     case GST_EVENT_SINK_MESSAGE:
1242     default:
1243       break;
1244   }
1245
1246   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1247   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1248   gst_validate_pad_monitor_event_overrides (pad_monitor, event);
1249   if (handler) {
1250     gst_event_ref (event);
1251     ret = pad_monitor->event_func (pad, parent, event);
1252   }
1253   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1254   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1255
1256   /* post checks */
1257   switch (GST_EVENT_TYPE (event)) {
1258     case GST_EVENT_SEGMENT:
1259       if (ret) {
1260         if (!pad_monitor->has_segment
1261             && pad_monitor->segment.format != segment->format) {
1262           gst_segment_init (&pad_monitor->segment, segment->format);
1263         }
1264         gst_segment_copy_into (segment, &pad_monitor->segment);
1265         pad_monitor->has_segment = TRUE;
1266       }
1267       break;
1268     case GST_EVENT_FLUSH_START:
1269     case GST_EVENT_FLUSH_STOP:
1270     case GST_EVENT_EOS:
1271     case GST_EVENT_TAG:
1272     case GST_EVENT_SINK_MESSAGE:
1273     default:
1274       break;
1275   }
1276
1277   if (handler)
1278     gst_event_unref (event);
1279   return ret;
1280 }
1281
1282 static gboolean
1283 gst_validate_pad_monitor_src_event_check (GstValidatePadMonitor * pad_monitor,
1284     GstObject * parent, GstEvent * event, GstPadEventFunction handler)
1285 {
1286   gboolean ret = TRUE;
1287   gdouble rate;
1288   GstFormat format;
1289   gint64 start, stop;
1290   GstSeekFlags seek_flags;
1291   GstSeekType start_type, stop_type;
1292   guint32 seqnum = gst_event_get_seqnum (event);
1293   GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1294
1295   gst_validate_pad_monitor_common_event_check (pad_monitor, event);
1296
1297   /* pre checks */
1298   switch (GST_EVENT_TYPE (event)) {
1299     case GST_EVENT_SEEK:
1300     {
1301       gst_event_parse_seek (event, &rate, &format, &seek_flags, &start_type,
1302           &start, &stop_type, &stop);
1303       /* upstream seek - store the seek event seqnum to check
1304        * flushes and newsegments share the same */
1305
1306       /* TODO we might need to use a list as multiple seeks can be sent
1307        * before the flushes arrive here */
1308       if (seek_flags & GST_SEEK_FLAG_FLUSH) {
1309         pad_monitor->pending_flush_start_seqnum = seqnum;
1310         pad_monitor->pending_flush_stop_seqnum = seqnum;
1311       }
1312       pad_monitor->pending_newsegment_seqnum = seqnum;
1313       pad_monitor->pending_eos_seqnum = seqnum;
1314     }
1315       break;
1316       /* both flushes are handled by the common event handling function */
1317     case GST_EVENT_FLUSH_START:
1318     case GST_EVENT_FLUSH_STOP:
1319     case GST_EVENT_NAVIGATION:
1320     case GST_EVENT_LATENCY:
1321     case GST_EVENT_STEP:
1322     case GST_EVENT_QOS:
1323     default:
1324       break;
1325   }
1326
1327   if (handler) {
1328     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1329     gst_event_ref (event);
1330     ret = pad_monitor->event_func (pad, parent, event);
1331     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1332   }
1333
1334   /* post checks */
1335   switch (GST_EVENT_TYPE (event)) {
1336     case GST_EVENT_FLUSH_START:
1337     case GST_EVENT_FLUSH_STOP:
1338     case GST_EVENT_QOS:
1339     case GST_EVENT_SEEK:
1340     case GST_EVENT_NAVIGATION:
1341     case GST_EVENT_LATENCY:
1342     case GST_EVENT_STEP:
1343     default:
1344       break;
1345   }
1346
1347   if (handler)
1348     gst_event_unref (event);
1349   return ret;
1350 }
1351
1352 static GstFlowReturn
1353 gst_validate_pad_monitor_chain_func (GstPad * pad, GstObject * parent,
1354     GstBuffer * buffer)
1355 {
1356   GstValidatePadMonitor *pad_monitor =
1357       g_object_get_data ((GObject *) pad, "qa-monitor");
1358   GstFlowReturn ret;
1359
1360   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1361   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1362
1363   gst_validate_pad_monitor_check_first_buffer (pad_monitor, buffer);
1364   gst_validate_pad_monitor_update_buffer_data (pad_monitor, buffer);
1365
1366   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1367   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1368
1369   gst_validate_pad_monitor_buffer_overrides (pad_monitor, buffer);
1370
1371   ret = pad_monitor->chain_func (pad, parent, buffer);
1372
1373   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1374   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1375
1376   pad_monitor->last_flow_return = ret;
1377   if (PAD_PARENT_IS_DEMUXER (pad_monitor))
1378     gst_validate_pad_monitor_check_aggregated_return (pad_monitor, ret);
1379
1380   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1381   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1382
1383   return ret;
1384 }
1385
1386 static gboolean
1387 gst_validate_pad_monitor_event_is_tracked (GstValidatePadMonitor * monitor,
1388     GstEvent * event)
1389 {
1390   if (!GST_EVENT_IS_SERIALIZED (event)) {
1391     return FALSE;
1392   }
1393
1394   /* we don't track Tag events because they mutate too much and it is hard
1395    * to match a tag event pushed on a source pad with the one that was received
1396    * on a sink pad.
1397    * One idea would be to use seqnum, but it seems that it is undefined whether
1398    * seqnums should be maintained in tag events that are created from others
1399    * up to today. (2013-08-29)
1400    */
1401   if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
1402     return FALSE;
1403
1404   return TRUE;
1405 }
1406
1407 static gboolean
1408 gst_validate_pad_monitor_sink_event_func (GstPad * pad, GstObject * parent,
1409     GstEvent * event)
1410 {
1411   GstValidatePadMonitor *pad_monitor =
1412       g_object_get_data ((GObject *) pad, "qa-monitor");
1413   gboolean ret;
1414
1415   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor);
1416   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1417
1418   if (gst_validate_pad_monitor_event_is_tracked (pad_monitor, event)) {
1419     GstClockTime last_ts;
1420     if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_timestamp)) {
1421       last_ts = pad_monitor->current_timestamp;
1422       if (GST_CLOCK_TIME_IS_VALID (pad_monitor->current_duration)) {
1423         last_ts += pad_monitor->current_duration;
1424       }
1425     } else {
1426       last_ts = 0;
1427     }
1428     gst_validate_pad_monitor_otherpad_add_pending_serialized_event (pad_monitor,
1429         event, last_ts);
1430   }
1431
1432   /* pre checks */
1433   switch (GST_EVENT_TYPE (event)) {
1434     case GST_EVENT_CAPS:{
1435       GstCaps *caps;
1436
1437       gst_event_parse_caps (event, &caps);
1438       gst_validate_pad_monitor_setcaps_pre (pad_monitor, caps);
1439       break;
1440     }
1441     default:
1442       break;
1443   }
1444   ret =
1445       gst_validate_pad_monitor_downstream_event_check (pad_monitor, parent,
1446       event, pad_monitor->event_func);
1447   /* post checks */
1448   switch (GST_EVENT_TYPE (event)) {
1449     case GST_EVENT_CAPS:{
1450       GstCaps *caps;
1451
1452       gst_event_parse_caps (event, &caps);
1453       gst_validate_pad_monitor_setcaps_post (pad_monitor, caps, ret);
1454       break;
1455     }
1456     default:
1457       break;
1458   }
1459
1460   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1461   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (pad_monitor);
1462   return ret;
1463 }
1464
1465 static gboolean
1466 gst_validate_pad_monitor_src_event_func (GstPad * pad, GstObject * parent,
1467     GstEvent * event)
1468 {
1469   GstValidatePadMonitor *pad_monitor =
1470       g_object_get_data ((GObject *) pad, "qa-monitor");
1471   gboolean ret;
1472
1473   GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1474   ret = gst_validate_pad_monitor_src_event_check (pad_monitor, parent, event,
1475       pad_monitor->event_func);
1476   GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1477   return ret;
1478 }
1479
1480 static gboolean
1481 gst_validate_pad_monitor_query_func (GstPad * pad, GstObject * parent,
1482     GstQuery * query)
1483 {
1484   GstValidatePadMonitor *pad_monitor =
1485       g_object_get_data ((GObject *) pad, "qa-monitor");
1486   gboolean ret;
1487
1488   gst_validate_pad_monitor_query_overrides (pad_monitor, query);
1489
1490   ret = pad_monitor->query_func (pad, parent, query);
1491
1492   if (ret) {
1493     switch (GST_QUERY_TYPE (query)) {
1494       case GST_QUERY_CAPS:{
1495         GstCaps *res;
1496         /* We shouldn't need to lock the parent as this doesn't modify
1497          * other monitors, just does some peer_pad_caps */
1498         GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1499
1500         gst_query_parse_caps_result (query, &res);
1501         if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1502           gst_validate_pad_monitor_check_caps_fields_proxied (pad_monitor, res);
1503         }
1504         GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1505         break;
1506       }
1507       default:
1508         break;
1509     }
1510   }
1511
1512   return ret;
1513 }
1514
1515 static gboolean
1516 gst_validate_pad_monitor_activatemode_func (GstPad * pad, GstObject * parent,
1517     GstPadMode mode, gboolean active)
1518 {
1519   GstValidatePadMonitor *pad_monitor =
1520       g_object_get_data ((GObject *) pad, "qa-monitor");
1521   gboolean ret = TRUE;
1522
1523   /* TODO add overrides for activate func */
1524
1525   if (pad_monitor->activatemode_func)
1526     ret = pad_monitor->activatemode_func (pad, parent, mode, active);
1527   if (ret && active == FALSE) {
1528     GST_VALIDATE_MONITOR_LOCK (pad_monitor);
1529     gst_validate_pad_monitor_flush (pad_monitor);
1530     GST_VALIDATE_MONITOR_UNLOCK (pad_monitor);
1531   }
1532
1533   return ret;
1534 }
1535
1536 static gboolean
1537 gst_validate_pad_get_range_func (GstPad * pad, GstObject * parent,
1538     guint64 offset, guint size, GstBuffer ** buffer)
1539 {
1540   GstValidatePadMonitor *pad_monitor =
1541       g_object_get_data ((GObject *) pad, "qa-monitor");
1542   gboolean ret;
1543   ret = pad_monitor->getrange_func (pad, parent, offset, size, buffer);
1544   return ret;
1545 }
1546
1547 static gboolean
1548 gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
1549     gpointer udata)
1550 {
1551   GstValidatePadMonitor *monitor = udata;
1552   GstValidateMonitor *parent = GST_VALIDATE_MONITOR_GET_PARENT (monitor);
1553
1554   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1555   GST_VALIDATE_MONITOR_LOCK (monitor);
1556
1557   gst_validate_pad_monitor_check_first_buffer (monitor, buffer);
1558   gst_validate_pad_monitor_update_buffer_data (monitor, buffer);
1559
1560   gst_validate_pad_monitor_check_buffer_timestamp_in_received_range (monitor,
1561       buffer);
1562
1563   gst_validate_pad_monitor_check_late_serialized_events (monitor,
1564       GST_BUFFER_TIMESTAMP (buffer));
1565
1566   /* a GstValidatePadMonitor parent must be a GstValidateElementMonitor */
1567   if (PAD_PARENT_IS_DECODER (parent)) {
1568     /* should not push out of segment data */
1569     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)) &&
1570         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)) &&
1571         !gst_segment_clip (&monitor->segment, monitor->segment.format,
1572             GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer) +
1573             GST_BUFFER_DURATION (buffer), NULL, NULL)) {
1574       /* TODO is this a timestamp issue? */
1575       GST_VALIDATE_REPORT (monitor, BUFFER_IS_OUT_OF_SEGMENT,
1576           "buffer is out of segment and shouldn't be pushed. Timestamp: %"
1577           GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT ". Range: %"
1578           GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1579           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1580           GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
1581           GST_TIME_ARGS (monitor->segment.start),
1582           GST_TIME_ARGS (monitor->segment.stop));
1583     }
1584   }
1585
1586   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1587   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1588   gst_validate_pad_monitor_buffer_probe_overrides (monitor, buffer);
1589   return TRUE;
1590 }
1591
1592 static gboolean
1593 gst_validate_pad_monitor_event_probe (GstPad * pad, GstEvent * event,
1594     gpointer udata)
1595 {
1596   GstValidatePadMonitor *monitor = GST_VALIDATE_PAD_MONITOR_CAST (udata);
1597   gboolean ret;
1598
1599   GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (monitor);
1600   GST_VALIDATE_MONITOR_LOCK (monitor);
1601
1602   GST_DEBUG_OBJECT (pad, "event %p %s", event, GST_EVENT_TYPE_NAME (event));
1603
1604   if (GST_EVENT_IS_SERIALIZED (event)) {
1605     gint i;
1606
1607     /* Detect if events the element received are being forwarded in the same order
1608      *
1609      * Several scenarios:
1610      * 1) The element pushes the event as-is
1611      * 2) The element consumes the event and does not forward it
1612      * 3) The element consumes the event and creates another one instead
1613      * 4) The element pushes other serialized event before pushing out the
1614      *    one it received
1615      *
1616      * For each pad we have two lists to track serialized events:
1617      *  1) We received on input and expect to see (serialized_events)
1618      *  2) We received on input but don't expect to see (expired_events)
1619      *
1620      * To detect events that are pushed in a different order from the one they were
1621      * received in we check that:
1622      *
1623      * For each event being outputted:
1624      *   If it is in the expired_events list:
1625      *     RAISE WARNING
1626      *   If it is in the serialized_events list:
1627      *     If there are other events that were received before:
1628      *        Put those events on the expired_events list
1629      *     Remove that event and any previous ones from the serialized_events list
1630      *
1631      * Clear expired events list when flushing or on pad deactivation
1632      *
1633      */
1634
1635     if (g_list_find (monitor->expired_events, event)) {
1636       /* If it's the expired events, we've failed */
1637       GST_WARNING_OBJECT (pad, "Did not expect event %p %s", event,
1638           GST_EVENT_TYPE_NAME (event));
1639       GST_VALIDATE_REPORT (monitor, EVENT_SERIALIZED_OUT_OF_ORDER,
1640           "Serialized event was pushed out of order: %" GST_PTR_FORMAT, event);
1641       monitor->expired_events =
1642           g_list_remove (monitor->expired_events, monitor);
1643     } else if (monitor->serialized_events->len) {
1644       for (i = 0; i < monitor->serialized_events->len; i++) {
1645         SerializedEventData *next_event =
1646             g_ptr_array_index (monitor->serialized_events, i);
1647         GST_DEBUG_OBJECT (pad, "Checking against stored event #%d: %p %s", i,
1648             next_event->event, GST_EVENT_TYPE_NAME (next_event->event));
1649
1650         if (event == next_event->event
1651             || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1652           /* We have found our event */
1653           GST_DEBUG_OBJECT (pad, "Found matching event");
1654
1655           while (monitor->serialized_events->len > i
1656               && GST_EVENT_TYPE (event) == GST_EVENT_TYPE (next_event->event)) {
1657             /* Swallow all expected events of the same type */
1658             g_ptr_array_remove_index (monitor->serialized_events, i);
1659             next_event = g_ptr_array_index (monitor->serialized_events, i);
1660           }
1661
1662           /* Move all previous events to expired events */
1663           if (G_UNLIKELY (i > 0)) {
1664             GST_DEBUG_OBJECT (pad,
1665                 "Moving previous expected events to expired list");
1666             while (i--) {
1667               next_event = g_ptr_array_index (monitor->serialized_events, 0);
1668               monitor->expired_events =
1669                   g_list_append (monitor->expired_events, next_event->event);
1670               g_ptr_array_remove_index (monitor->serialized_events, 0);
1671             }
1672           }
1673           debug_pending_event (pad, monitor->serialized_events);
1674           break;
1675         }
1676       }
1677     }
1678   }
1679
1680   /* This so far is just like an event that is flowing downstream,
1681    * so we do the same checks as a sinkpad event handler */
1682   ret =
1683       gst_validate_pad_monitor_downstream_event_check (monitor, NULL, event,
1684       NULL);
1685   GST_VALIDATE_MONITOR_UNLOCK (monitor);
1686   GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
1687
1688   return ret;
1689 }
1690
1691 static GstPadProbeReturn
1692 gst_validate_pad_monitor_pad_probe (GstPad * pad, GstPadProbeInfo * info,
1693     gpointer udata)
1694 {
1695   if (info->type & GST_PAD_PROBE_TYPE_BUFFER)
1696     gst_validate_pad_monitor_buffer_probe (pad, info->data, udata);
1697   else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)
1698     gst_validate_pad_monitor_event_probe (pad, info->data, udata);
1699
1700   return GST_PAD_PROBE_OK;
1701 }
1702
1703 static void
1704 gst_validate_pad_monitor_setcaps_pre (GstValidatePadMonitor * pad_monitor,
1705     GstCaps * caps)
1706 {
1707   GstStructure *structure;
1708
1709   /* Check if caps are identical to last caps and complain if so */
1710   if (pad_monitor->last_caps
1711       && gst_caps_is_equal (caps, pad_monitor->last_caps)) {
1712     GST_VALIDATE_REPORT (pad_monitor, EVENT_CAPS_DUPLICATE, "%" GST_PTR_FORMAT,
1713         caps);
1714   }
1715
1716   gst_validate_pad_monitor_check_caps_complete (pad_monitor, caps);
1717
1718   if (caps) {
1719     structure = gst_caps_get_structure (caps, 0);
1720     if (gst_structure_n_fields (pad_monitor->pending_setcaps_fields)) {
1721       gint i;
1722       for (i = 0;
1723           i < gst_structure_n_fields (pad_monitor->pending_setcaps_fields);
1724           i++) {
1725         const gchar *name =
1726             gst_structure_nth_field_name (pad_monitor->pending_setcaps_fields,
1727             i);
1728         const GValue *v = gst_structure_get_value (structure, name);
1729         const GValue *otherv =
1730             gst_structure_get_value (pad_monitor->pending_setcaps_fields, name);
1731
1732         if (v == NULL) {
1733           GST_VALIDATE_REPORT (pad_monitor, CAPS_EXPECTED_FIELD_NOT_FOUND,
1734               "Field %s is missing from setcaps caps '%" GST_PTR_FORMAT "'",
1735               name, caps);
1736         } else if (gst_value_compare (v, otherv) != GST_VALUE_EQUAL) {
1737           GST_VALIDATE_REPORT (pad_monitor, CAPS_FIELD_UNEXPECTED_VALUE,
1738               "Field %s from setcaps caps '%" GST_PTR_FORMAT "' is different "
1739               "from expected value in caps '%" GST_PTR_FORMAT "'", name, caps,
1740               pad_monitor->pending_setcaps_fields);
1741         }
1742       }
1743     }
1744
1745     if (gst_validate_pad_monitor_pad_should_proxy_othercaps (pad_monitor)) {
1746       if (_structure_is_video (structure)) {
1747         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1748             structure, "width");
1749         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1750             structure, "height");
1751         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1752             structure, "framerate");
1753         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1754             structure, "pixel-aspect-ratio");
1755       } else if (_structure_is_audio (structure)) {
1756         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1757             structure, "rate");
1758         gst_validate_pad_monitor_otherpad_add_pending_field (pad_monitor,
1759             structure, "channels");
1760       }
1761     }
1762   }
1763
1764   gst_structure_free (pad_monitor->pending_setcaps_fields);
1765   pad_monitor->pending_setcaps_fields =
1766       gst_structure_new_empty (PENDING_FIELDS);
1767
1768   gst_validate_pad_monitor_setcaps_overrides (pad_monitor, caps);
1769 }
1770
1771 static void
1772 gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor * pad_monitor,
1773     GstCaps * caps, gboolean ret)
1774 {
1775   if (!ret)
1776     gst_validate_pad_monitor_otherpad_clear_pending_fields (pad_monitor);
1777   else {
1778     if (pad_monitor->last_caps) {
1779       gst_caps_unref (pad_monitor->last_caps);
1780     }
1781     pad_monitor->last_caps = gst_caps_ref (caps);
1782   }
1783 }
1784
1785 static gboolean
1786 gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
1787 {
1788   GstValidatePadMonitor *pad_monitor = GST_VALIDATE_PAD_MONITOR_CAST (monitor);
1789   GstPad *pad;
1790   if (!GST_IS_PAD (GST_VALIDATE_MONITOR_GET_OBJECT (monitor))) {
1791     GST_WARNING_OBJECT (monitor, "Trying to create pad monitor with other "
1792         "type of object");
1793     return FALSE;
1794   }
1795
1796   pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor);
1797
1798   if (g_object_get_data ((GObject *) pad, "qa-monitor")) {
1799     GST_WARNING_OBJECT (pad_monitor, "Pad already has a qa-monitor associated");
1800     return FALSE;
1801   }
1802
1803   g_object_set_data ((GObject *) pad, "qa-monitor", pad_monitor);
1804
1805   pad_monitor->pad = pad;
1806
1807   pad_monitor->event_func = GST_PAD_EVENTFUNC (pad);
1808   pad_monitor->query_func = GST_PAD_QUERYFUNC (pad);
1809   pad_monitor->activatemode_func = GST_PAD_ACTIVATEMODEFUNC (pad);
1810   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1811
1812     pad_monitor->chain_func = GST_PAD_CHAINFUNC (pad);
1813     if (pad_monitor->chain_func)
1814       gst_pad_set_chain_function (pad, gst_validate_pad_monitor_chain_func);
1815
1816     gst_pad_set_event_function (pad, gst_validate_pad_monitor_sink_event_func);
1817   } else {
1818     pad_monitor->getrange_func = GST_PAD_GETRANGEFUNC (pad);
1819     if (pad_monitor->getrange_func)
1820       gst_pad_set_getrange_function (pad, gst_validate_pad_get_range_func);
1821
1822     gst_pad_set_event_function (pad, gst_validate_pad_monitor_src_event_func);
1823
1824     /* add buffer/event probes */
1825     pad_monitor->pad_probe_id =
1826         gst_pad_add_probe (pad,
1827         GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
1828         GST_PAD_PROBE_TYPE_EVENT_FLUSH,
1829         (GstPadProbeCallback) gst_validate_pad_monitor_pad_probe, pad_monitor,
1830         NULL);
1831   }
1832   gst_pad_set_query_function (pad, gst_validate_pad_monitor_query_func);
1833   gst_pad_set_activatemode_function (pad,
1834       gst_validate_pad_monitor_activatemode_func);
1835
1836   gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (monitor),
1837       g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad)));
1838
1839   if (G_UNLIKELY (GST_PAD_PARENT (pad) == NULL))
1840     GST_FIXME ("Saw a pad not belonging to any object");
1841
1842   return TRUE;
1843 }