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