event: add new seek parameter, "trickmode-interval"
[platform/upstream/gstreamer.git] / tests / check / gst / gstevent.c
1 /* GStreamer
2  * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
3  *
4  * gstevent.c: Unit test for event handling
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/check/gstcheck.h>
26
27 GST_START_TEST (create_events)
28 {
29   GstEvent *event, *event2;
30   GstStructure *structure;
31
32   /* FLUSH_START */
33   {
34     event = gst_event_new_flush_start ();
35     fail_if (event == NULL);
36     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START);
37     fail_unless (GST_EVENT_IS_UPSTREAM (event));
38     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
39     fail_if (GST_EVENT_IS_SERIALIZED (event));
40     gst_event_unref (event);
41   }
42   /* FLUSH_STOP */
43   {
44     gboolean reset_time;
45
46     event = gst_event_new_flush_stop (TRUE);
47     fail_if (event == NULL);
48     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP);
49     fail_unless (GST_EVENT_IS_UPSTREAM (event));
50     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
51     fail_unless (GST_EVENT_IS_SERIALIZED (event));
52
53     gst_event_parse_flush_stop (event, &reset_time);
54     fail_unless (reset_time == TRUE);
55     gst_event_unref (event);
56   }
57
58   /* SELECT_STREAMS */
59   {
60     GList *streams = NULL;
61     GList *res = NULL;
62     GList *tmp;
63     streams = g_list_append (streams, (gpointer) "stream1");
64     streams = g_list_append (streams, (gpointer) "stream2");
65     event = gst_event_new_select_streams (streams);
66     fail_if (event == NULL);
67     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SELECT_STREAMS);
68     fail_unless (GST_EVENT_IS_UPSTREAM (event));
69
70     gst_event_parse_select_streams (event, &res);
71     fail_if (res == NULL);
72     fail_unless_equals_int (g_list_length (res), 2);
73     tmp = res;
74     fail_unless_equals_string (tmp->data, "stream1");
75     tmp = tmp->next;
76     fail_unless_equals_string (tmp->data, "stream2");
77
78     gst_event_unref (event);
79
80     g_list_free (streams);
81     g_list_free_full (res, g_free);
82   }
83
84   /* STREAM_GROUP_DONE */
85   {
86     guint group_id = 0;
87
88     event = gst_event_new_stream_group_done (0x42);
89     fail_if (event == NULL);
90     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_GROUP_DONE);
91     fail_if (GST_EVENT_IS_UPSTREAM (event));
92     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
93     fail_unless (GST_EVENT_IS_SERIALIZED (event));
94     gst_event_parse_stream_group_done (event, &group_id);
95     fail_unless (group_id == 0x42);
96     gst_event_unref (event);
97   }
98
99   /* EOS */
100   {
101     event = gst_event_new_eos ();
102     fail_if (event == NULL);
103     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
104     fail_if (GST_EVENT_IS_UPSTREAM (event));
105     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
106     fail_unless (GST_EVENT_IS_SERIALIZED (event));
107     gst_event_unref (event);
108   }
109   /* GAP */
110   {
111     GstClockTime ts = 0, dur = 0;
112
113     ASSERT_CRITICAL (gst_event_new_gap (GST_CLOCK_TIME_NONE, GST_SECOND));
114
115     event = gst_event_new_gap (90 * GST_SECOND, GST_SECOND);
116     fail_if (event == NULL);
117     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_GAP);
118     fail_if (GST_EVENT_IS_UPSTREAM (event));
119     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
120     fail_unless (GST_EVENT_IS_SERIALIZED (event));
121     gst_event_parse_gap (event, &ts, NULL);
122     fail_unless_equals_int64 (ts, 90 * GST_SECOND);
123     gst_event_parse_gap (event, &ts, &dur);
124     fail_unless_equals_int64 (dur, GST_SECOND);
125     gst_event_unref (event);
126   }
127   /* SEGMENT */
128   {
129     GstSegment segment, parsed;
130
131     gst_segment_init (&segment, GST_FORMAT_TIME);
132     segment.rate = 0.5;
133     segment.applied_rate = 1.0;
134     segment.start = 1;
135     segment.stop = G_MAXINT64;
136     segment.time = 0xdeadbeef;
137
138     event = gst_event_new_segment (&segment);
139     fail_if (event == NULL);
140     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
141     fail_if (GST_EVENT_IS_UPSTREAM (event));
142     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
143     fail_unless (GST_EVENT_IS_SERIALIZED (event));
144
145     gst_event_copy_segment (event, &parsed);
146     fail_unless (parsed.rate == 0.5);
147     fail_unless (parsed.applied_rate == 1.0);
148     fail_unless (parsed.format == GST_FORMAT_TIME);
149     fail_unless (parsed.start == 1);
150     fail_unless (parsed.stop == G_MAXINT64);
151     fail_unless (parsed.time == 0xdeadbeef);
152
153     gst_event_unref (event);
154   }
155
156   /* TAGS */
157   {
158     GstTagList *taglist = gst_tag_list_new_empty ();
159     GstTagList *tl2 = NULL;
160
161     event = gst_event_new_tag (taglist);
162     fail_if (taglist == NULL);
163     fail_if (event == NULL);
164     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
165     fail_if (GST_EVENT_IS_UPSTREAM (event));
166     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
167     fail_unless (GST_EVENT_IS_SERIALIZED (event));
168
169     gst_event_parse_tag (event, &tl2);
170     fail_unless (taglist == tl2);
171     gst_event_unref (event);
172   }
173
174   /* QOS */
175   {
176     GstQOSType t1 = GST_QOS_TYPE_THROTTLE, t2;
177     gdouble p1 = 1.0, p2;
178     GstClockTimeDiff ctd1 = G_GINT64_CONSTANT (10), ctd2;
179     GstClockTime ct1 = G_GUINT64_CONSTANT (20), ct2;
180
181     event = gst_event_new_qos (t1, p1, ctd1, ct1);
182     fail_if (event == NULL);
183     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
184     fail_unless (GST_EVENT_IS_UPSTREAM (event));
185     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
186     fail_if (GST_EVENT_IS_SERIALIZED (event));
187
188     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
189     fail_unless (p1 == p2);
190     fail_unless (ctd1 == ctd2);
191     fail_unless (ct1 == ct2);
192     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
193     fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
194     fail_unless (p1 == p2);
195     fail_unless (ctd1 == ctd2);
196     fail_unless (ct1 == ct2);
197     gst_event_unref (event);
198
199     ctd1 = G_GINT64_CONSTANT (-10);
200     event = gst_event_new_qos (t1, p1, ctd1, ct1);
201     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
202     fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
203     gst_event_unref (event);
204
205     event = gst_event_new_qos (t1, p1, ctd1, ct1);
206     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
207     fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
208     fail_unless (p1 == p2);
209     fail_unless (ctd1 == ctd2);
210     fail_unless (ct1 == ct2);
211     gst_event_unref (event);
212   }
213
214   /* SEEK */
215   {
216     gdouble rate;
217     GstFormat format;
218     GstSeekFlags flags;
219     GstSeekType start_type, stop_type;
220     gint64 start, stop;
221     GstClockTime trickmode_interval;
222
223     event = gst_event_new_seek (0.5, GST_FORMAT_BYTES,
224         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
225         GST_SEEK_TYPE_SET, 1, GST_SEEK_TYPE_NONE, 0xdeadbeef);
226
227     fail_if (event == NULL);
228     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
229     fail_unless (GST_EVENT_IS_UPSTREAM (event));
230     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
231     fail_if (GST_EVENT_IS_SERIALIZED (event));
232
233     gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
234         &stop_type, &stop);
235     fail_unless (rate == 0.5);
236     fail_unless (format == GST_FORMAT_BYTES);
237     fail_unless (flags == (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE));
238     fail_unless (start_type == GST_SEEK_TYPE_SET);
239     fail_unless (start == 1);
240     fail_unless (stop_type == GST_SEEK_TYPE_NONE);
241     fail_unless (stop == 0xdeadbeef);
242
243     gst_event_parse_seek_trickmode_interval (event, &trickmode_interval);
244     fail_unless_equals_uint64 (trickmode_interval, 0);
245
246     gst_event_set_seek_trickmode_interval (event, GST_SECOND);
247     gst_event_parse_seek_trickmode_interval (event, &trickmode_interval);
248     fail_unless_equals_uint64 (trickmode_interval, GST_SECOND);
249
250     gst_event_ref (event);
251     ASSERT_CRITICAL (gst_event_set_seek_trickmode_interval (event,
252             2 * GST_SECOND));
253     gst_event_unref (event);
254
255     gst_event_unref (event);
256
257     event = gst_event_new_flush_start ();
258     ASSERT_CRITICAL (gst_event_set_seek_trickmode_interval (event, GST_SECOND));
259     gst_event_unref (event);
260   }
261
262   /* STREAM_START */
263   {
264     GstStreamFlags flags = ~GST_STREAM_FLAG_NONE;
265
266     event = gst_event_new_stream_start ("7f4b2f0/audio_02");
267     fail_if (event == NULL);
268     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
269     fail_if (GST_EVENT_IS_UPSTREAM (event));
270     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
271     fail_unless (GST_EVENT_IS_SERIALIZED (event));
272     gst_event_parse_stream_flags (event, &flags);
273     fail_unless_equals_int (flags, GST_STREAM_FLAG_NONE);
274     gst_event_set_stream_flags (event, GST_STREAM_FLAG_SPARSE);
275     gst_event_parse_stream_flags (event, &flags);
276     fail_unless_equals_int (flags, GST_STREAM_FLAG_SPARSE);
277     gst_event_ref (event);
278     ASSERT_CRITICAL (gst_event_set_stream_flags (event, GST_STREAM_FLAG_NONE));
279     gst_event_unref (event);
280     gst_event_unref (event);
281   }
282
283   /* STREAM_COLLECTION */
284   {
285     GstStreamCollection *collection, *res = NULL;
286     GstStream *stream1, *stream2;
287     GstCaps *caps1, *caps2;
288
289     /* Create a collection of two streams */
290     caps1 = gst_caps_from_string ("some/caps");
291     caps2 = gst_caps_from_string ("some/other-string");
292
293     stream1 = gst_stream_new ("stream-1", caps1, GST_STREAM_TYPE_AUDIO, 0);
294     stream2 = gst_stream_new ("stream-2", caps2, GST_STREAM_TYPE_VIDEO, 0);
295
296     collection = gst_stream_collection_new ("something");
297     fail_unless (gst_stream_collection_add_stream (collection, stream1));
298     fail_unless (gst_stream_collection_add_stream (collection, stream2));
299
300     event = gst_event_new_stream_collection (collection);
301     fail_unless (event != NULL);
302
303     gst_event_parse_stream_collection (event, &res);
304     fail_unless (res != NULL);
305     fail_unless (res == collection);
306
307     gst_event_unref (event);
308     gst_object_unref (res);
309     gst_object_unref (collection);
310     gst_caps_unref (caps1);
311     gst_caps_unref (caps2);
312   }
313
314   /* NAVIGATION */
315   {
316     structure = gst_structure_new ("application/x-gst-navigation", "event",
317         G_TYPE_STRING, "key-press", "key", G_TYPE_STRING, "mon", NULL);
318     fail_if (structure == NULL);
319     event = gst_event_new_navigation (structure);
320     fail_if (event == NULL);
321     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NAVIGATION);
322     fail_unless (GST_EVENT_IS_UPSTREAM (event));
323     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
324     fail_if (GST_EVENT_IS_SERIALIZED (event));
325
326     fail_unless (gst_event_get_structure (event) == structure);
327     gst_event_unref (event);
328   }
329
330   /* Protection */
331   {
332     GstBuffer *data;
333     GstMemory *mem;
334     const gchar *parsed_origin;
335     const gchar *parsed_id;
336     GstBuffer *parsed_data;
337     const gchar clearkey_sys_id[] = "78f32170-d883-11e0-9572-0800200c9a66";
338     gsize offset;
339
340     data = gst_buffer_new ();
341     mem = gst_allocator_alloc (NULL, 40, NULL);
342     gst_buffer_insert_memory (data, -1, mem);
343     for (offset = 0; offset < 40; offset += 4) {
344       gst_buffer_fill (data, offset, "pssi", 4);
345     }
346     ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 1);
347     event = gst_event_new_protection (clearkey_sys_id, data, "test");
348     fail_if (event == NULL);
349     ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 2);
350     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_PROTECTION);
351     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
352     fail_unless (GST_EVENT_IS_SERIALIZED (event));
353     gst_event_parse_protection (event, &parsed_id, &parsed_data,
354         &parsed_origin);
355     fail_if (parsed_id == NULL);
356     fail_unless (g_strcmp0 (clearkey_sys_id, parsed_id) == 0);
357     fail_if (parsed_data == NULL);
358     fail_if (parsed_data != data);
359     ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 2);
360     fail_if (parsed_origin == NULL);
361     fail_unless (g_strcmp0 ("test", parsed_origin) == 0);
362     gst_event_unref (event);
363     ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 1);
364     gst_buffer_unref (data);
365   }
366
367   /* Custom event types */
368   {
369     structure = gst_structure_new_empty ("application/x-custom");
370     fail_if (structure == NULL);
371     event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
372     fail_if (event == NULL);
373     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM);
374     fail_unless (GST_EVENT_IS_UPSTREAM (event));
375     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
376     fail_if (GST_EVENT_IS_SERIALIZED (event));
377     fail_unless (gst_event_get_structure (event) == structure);
378     fail_unless (gst_event_has_name (event, "application/x-custom"));
379     gst_event_unref (event);
380
381     /* Decided not to test the other custom enum types, as they
382      * only differ by the value of the enum passed to gst_event_new_custom
383      */
384   }
385
386   /* Event copying */
387   {
388     structure = gst_structure_new_empty ("application/x-custom");
389     fail_if (structure == NULL);
390     event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
391
392     fail_if (event == NULL);
393     event2 = gst_event_copy (event);
394     fail_if (event2 == NULL);
395     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TYPE (event2));
396     fail_unless (gst_event_has_name (event, "application/x-custom"));
397
398     /* The structure should have been duplicated */
399     fail_if (gst_event_get_structure (event) ==
400         gst_event_get_structure (event2));
401
402     gst_event_unref (event);
403     gst_event_unref (event2);
404   }
405
406   /* Make events writable */
407   {
408     structure = gst_structure_new_empty ("application/x-custom");
409     fail_if (structure == NULL);
410     event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
411     /* ref the event so that it becomes non-writable */
412     gst_event_ref (event);
413     gst_event_ref (event);
414     /* this should fail if the structure isn't writable */
415     ASSERT_CRITICAL (gst_structure_remove_all_fields ((GstStructure *)
416             gst_event_get_structure (event)));
417     fail_unless (gst_event_has_name (event, "application/x-custom"));
418
419     /* now make writable */
420     event2 =
421         GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event)));
422     fail_unless (event != event2);
423     /* this fail if the structure isn't writable */
424     gst_structure_remove_all_fields ((GstStructure *)
425         gst_event_get_structure (event2));
426     fail_unless (gst_event_has_name (event2, "application/x-custom"));
427
428     gst_event_unref (event);
429     gst_event_unref (event);
430     gst_event_unref (event2);
431   }
432 }
433
434 GST_END_TEST;
435
436 static GTimeVal sent_event_time;
437 static GstEvent *got_event_before_q, *got_event_after_q;
438 static GTimeVal got_event_time;
439
440 static GstPadProbeReturn
441 event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
442 {
443   GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info);
444   gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data);
445
446   GST_DEBUG ("event probe called %p", data);
447
448   fail_unless (GST_IS_EVENT (data));
449
450   if (before_q) {
451     switch (GST_EVENT_TYPE (GST_EVENT (data))) {
452       case GST_EVENT_CUSTOM_UPSTREAM:
453       case GST_EVENT_CUSTOM_BOTH:
454       case GST_EVENT_CUSTOM_BOTH_OOB:
455         if (got_event_before_q != NULL)
456           break;
457         gst_event_ref ((GstEvent *) data);
458         g_get_current_time (&got_event_time);
459         got_event_before_q = GST_EVENT (data);
460         break;
461       default:
462         break;
463     }
464   } else {
465     switch (GST_EVENT_TYPE (GST_EVENT (data))) {
466       case GST_EVENT_CUSTOM_DOWNSTREAM:
467       case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
468       case GST_EVENT_CUSTOM_BOTH:
469       case GST_EVENT_CUSTOM_BOTH_OOB:
470         if (got_event_after_q != NULL)
471           break;
472         gst_event_ref ((GstEvent *) data);
473         g_get_current_time (&got_event_time);
474         got_event_after_q = GST_EVENT (data);
475         break;
476       default:
477         break;
478     }
479   }
480
481   return GST_PAD_PROBE_OK;
482 }
483
484
485 typedef struct
486 {
487   GMutex lock;
488   GCond cond;
489   gboolean signaled;
490 } SignalData;
491
492 static void
493 signal_data_init (SignalData * data)
494 {
495   GST_DEBUG ("init %p", data);
496   g_mutex_init (&data->lock);
497   g_cond_init (&data->cond);
498   data->signaled = FALSE;
499 }
500
501 static void
502 signal_data_cleanup (SignalData * data)
503 {
504   GST_DEBUG ("free %p", data);
505   g_mutex_clear (&data->lock);
506   g_cond_clear (&data->cond);
507 }
508
509 static void
510 signal_data_signal (SignalData * data)
511 {
512   g_mutex_lock (&data->lock);
513   data->signaled = TRUE;
514   g_cond_broadcast (&data->cond);
515   GST_DEBUG ("signaling %p", data);
516   g_mutex_unlock (&data->lock);
517 }
518
519 static void
520 signal_data_wait (SignalData * data)
521 {
522   g_mutex_lock (&data->lock);
523   GST_DEBUG ("signal wait %p", data);
524   while (!data->signaled)
525     g_cond_wait (&data->cond, &data->lock);
526   GST_DEBUG ("signal wait done %p", data);
527   g_mutex_unlock (&data->lock);
528 }
529
530 static GstPadProbeReturn
531 signal_blocked (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
532 {
533   SignalData *data = (SignalData *) user_data;
534
535   GST_DEBUG ("signal called %p", data);
536   signal_data_signal (data);
537   GST_DEBUG ("signal done %p", data);
538
539   return GST_PAD_PROBE_OK;
540 }
541
542 static void test_event
543     (GstBin * pipeline, GstEventType type, GstPad * pad,
544     gboolean expect_before_q, GstPad * fake_srcpad)
545 {
546   GstEvent *event;
547   GstPad *peer;
548   gint i;
549   SignalData data;
550   gulong id;
551
552   got_event_before_q = got_event_after_q = NULL;
553
554   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
555   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
556       GST_CLOCK_TIME_NONE);
557
558   GST_DEBUG ("test event called");
559
560   event = gst_event_new_custom (type,
561       gst_structure_new_empty ("application/x-custom"));
562   g_get_current_time (&sent_event_time);
563   got_event_time.tv_sec = 0;
564   got_event_time.tv_usec = 0;
565
566   signal_data_init (&data);
567
568   /* We block the pad so the stream lock is released and we can send the event */
569   id = gst_pad_add_probe (fake_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
570       signal_blocked, &data, NULL);
571   fail_unless (id != 0);
572
573   signal_data_wait (&data);
574
575   /* We send on the peer pad, since the pad is blocked */
576   GST_DEBUG ("sending event %p", event);
577   fail_unless ((peer = gst_pad_get_peer (pad)) != NULL);
578   gst_pad_send_event (peer, event);
579   gst_object_unref (peer);
580
581   gst_pad_remove_probe (fake_srcpad, id);
582
583   if (expect_before_q) {
584     /* Wait up to 5 seconds for the event to appear */
585     for (i = 0; i < 500; i++) {
586       g_usleep (G_USEC_PER_SEC / 100);
587       if (got_event_before_q != NULL)
588         break;
589     }
590     fail_if (got_event_before_q == NULL,
591         "Expected event failed to appear upstream of the queue "
592         "within 5 seconds");
593     fail_unless (GST_EVENT_TYPE (got_event_before_q) == type);
594   } else {
595     /* Wait up to 10 seconds for the event to appear */
596     for (i = 0; i < 1000; i++) {
597       g_usleep (G_USEC_PER_SEC / 100);
598       if (got_event_after_q != NULL)
599         break;
600     }
601     fail_if (got_event_after_q == NULL,
602         "Expected event failed to appear after the queue within 10 seconds");
603     fail_unless (GST_EVENT_TYPE (got_event_after_q) == type);
604   }
605
606   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
607   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
608       GST_CLOCK_TIME_NONE);
609
610   if (got_event_before_q)
611     gst_event_unref (got_event_before_q);
612   if (got_event_after_q)
613     gst_event_unref (got_event_after_q);
614
615   got_event_before_q = got_event_after_q = NULL;
616
617   signal_data_cleanup (&data);
618 }
619
620 static gint64
621 timediff (GTimeVal * end, GTimeVal * start)
622 {
623   return (end->tv_sec - start->tv_sec) * G_USEC_PER_SEC +
624       (end->tv_usec - start->tv_usec);
625 }
626
627 GST_START_TEST (send_custom_events)
628 {
629   /* Run some tests on custom events. Checking for serialisation and whatnot.
630    * pipeline is fakesrc ! queue ! fakesink */
631   GstBin *pipeline;
632   GstElement *fakesrc, *fakesink, *queue;
633   GstPad *srcpad, *sinkpad;
634
635   fail_if ((pipeline = (GstBin *) gst_pipeline_new ("testpipe")) == NULL);
636   fail_if ((fakesrc = gst_element_factory_make ("fakesrc", NULL)) == NULL);
637   fail_if ((fakesink = gst_element_factory_make ("fakesink", NULL)) == NULL);
638   fail_if ((queue = gst_element_factory_make ("queue", NULL)) == NULL);
639
640   gst_bin_add_many (pipeline, fakesrc, queue, fakesink, NULL);
641   fail_unless (gst_element_link_many (fakesrc, queue, fakesink, NULL));
642
643   g_object_set (G_OBJECT (fakesink), "sync", FALSE, NULL);
644
645   /* Send 100 buffers per sec */
646   g_object_set (G_OBJECT (fakesrc), "silent", TRUE, "datarate", 100,
647       "sizemax", 1, "sizetype", 2, NULL);
648   g_object_set (G_OBJECT (queue), "max-size-buffers", 0, "max-size-time",
649       (guint64) GST_SECOND, "max-size-bytes", 0, NULL);
650   g_object_set (G_OBJECT (fakesink), "silent", TRUE, "sync", TRUE, NULL);
651
652   /* add pad-probes to faksrc.src and fakesink.sink */
653   fail_if ((srcpad = gst_element_get_static_pad (fakesrc, "src")) == NULL);
654   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
655       event_probe, GINT_TO_POINTER (TRUE), NULL);
656
657   fail_if ((sinkpad = gst_element_get_static_pad (fakesink, "sink")) == NULL);
658   gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
659       event_probe, GINT_TO_POINTER (FALSE), NULL);
660
661   /* Upstream events */
662   test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad);
663   fail_unless (timediff (&got_event_time,
664           &sent_event_time) < G_USEC_PER_SEC / 2,
665       "GST_EVENT_CUSTOM_UP took too long to reach source: %"
666       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
667
668   test_event (pipeline, GST_EVENT_CUSTOM_BOTH, sinkpad, TRUE, srcpad);
669   fail_unless (timediff (&got_event_time,
670           &sent_event_time) < G_USEC_PER_SEC / 2,
671       "GST_EVENT_CUSTOM_BOTH took too long to reach source: %"
672       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
673
674   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, sinkpad, TRUE, srcpad);
675   fail_unless (timediff (&got_event_time,
676           &sent_event_time) < G_USEC_PER_SEC / 2,
677       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
678       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
679
680   /* Out of band downstream events */
681   test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM_OOB, srcpad, FALSE, srcpad);
682   fail_unless (timediff (&got_event_time,
683           &sent_event_time) < G_USEC_PER_SEC / 2,
684       "GST_EVENT_CUSTOM_DS_OOB took too long to reach source: %"
685       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
686
687   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, srcpad, FALSE, srcpad);
688   fail_unless (timediff (&got_event_time,
689           &sent_event_time) < G_USEC_PER_SEC / 2,
690       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
691       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
692
693   /* In-band downstream events are expected to take at least 1 second
694    * to traverse the queue */
695   test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM, srcpad, FALSE, srcpad);
696   fail_unless (timediff (&got_event_time,
697           &sent_event_time) >= G_USEC_PER_SEC / 2,
698       "GST_EVENT_CUSTOM_DS arrived too quickly for an in-band event: %"
699       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
700
701   test_event (pipeline, GST_EVENT_CUSTOM_BOTH, srcpad, FALSE, srcpad);
702   fail_unless (timediff (&got_event_time,
703           &sent_event_time) >= G_USEC_PER_SEC / 2,
704       "GST_EVENT_CUSTOM_BOTH arrived too quickly for an in-band event: %"
705       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
706
707   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
708   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
709       GST_CLOCK_TIME_NONE);
710
711   gst_object_unref (sinkpad);
712   gst_object_unref (srcpad);
713   gst_object_unref (pipeline);
714 }
715
716 GST_END_TEST;
717
718 static Suite *
719 gst_event_suite (void)
720 {
721   Suite *s = suite_create ("GstEvent");
722   TCase *tc_chain = tcase_create ("events");
723
724   tcase_set_timeout (tc_chain, 20);
725
726   suite_add_tcase (s, tc_chain);
727   tcase_add_test (tc_chain, create_events);
728   tcase_add_test (tc_chain, send_custom_events);
729   return s;
730 }
731
732 GST_CHECK_MAIN (gst_event);