52efb2f9ec523d8593c34e7c19dbe7273fa31ec7
[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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22
23 #include <gst/check/gstcheck.h>
24
25 GST_START_TEST (create_events)
26 {
27   GstEvent *event, *event2;
28   GstStructure *structure;
29
30   /* FLUSH_START */
31   {
32     event = gst_event_new_flush_start ();
33     fail_if (event == NULL);
34     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START);
35     fail_unless (GST_EVENT_IS_UPSTREAM (event));
36     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
37     fail_if (GST_EVENT_IS_SERIALIZED (event));
38     gst_event_unref (event);
39   }
40   /* FLUSH_STOP */
41   {
42     event = gst_event_new_flush_stop ();
43     fail_if (event == NULL);
44     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP);
45     fail_unless (GST_EVENT_IS_UPSTREAM (event));
46     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
47     fail_unless (GST_EVENT_IS_SERIALIZED (event));
48     gst_event_unref (event);
49   }
50   /* EOS */
51   {
52     event = gst_event_new_eos ();
53     fail_if (event == NULL);
54     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
55     fail_if (GST_EVENT_IS_UPSTREAM (event));
56     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
57     fail_unless (GST_EVENT_IS_SERIALIZED (event));
58     gst_event_unref (event);
59   }
60   /* NEWSEGMENT */
61   {
62     gdouble rate, applied_rate;
63     GstFormat format;
64     gint64 start, end, base;
65     gboolean update;
66
67     event =
68         gst_event_new_new_segment (FALSE, 0.5, 1.0, GST_FORMAT_TIME, 1,
69         G_MAXINT64, 0xdeadbeef);
70     fail_if (event == NULL);
71     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
72     fail_if (GST_EVENT_IS_UPSTREAM (event));
73     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
74     fail_unless (GST_EVENT_IS_SERIALIZED (event));
75
76     gst_event_parse_new_segment (event, &update, &rate, &applied_rate, &format,
77         &start, &end, &base);
78     fail_unless (update == FALSE);
79     fail_unless (rate == 0.5);
80     fail_unless (applied_rate == 1.0);
81     fail_unless (format == GST_FORMAT_TIME);
82     fail_unless (start == 1);
83     fail_unless (end == G_MAXINT64);
84     fail_unless (base == 0xdeadbeef);
85
86     /* Check that the new segment was created with applied_rate of 1.0 */
87     gst_event_parse_new_segment (event, &update, &rate, &applied_rate,
88         &format, &start, &end, &base);
89
90     fail_unless (update == FALSE);
91     fail_unless (rate == 0.5);
92     fail_unless (applied_rate == 1.0);
93     fail_unless (format == GST_FORMAT_TIME);
94     fail_unless (start == 1);
95     fail_unless (end == G_MAXINT64);
96
97     gst_event_unref (event);
98
99     event =
100         gst_event_new_new_segment (TRUE, 0.75, 0.5, GST_FORMAT_BYTES, 0,
101         G_MAXINT64 - 1, 0xdeadbeef);
102
103     fail_if (event == NULL);
104     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
105     fail_if (GST_EVENT_IS_UPSTREAM (event));
106     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
107     fail_unless (GST_EVENT_IS_SERIALIZED (event));
108
109     gst_event_parse_new_segment (event, &update, &rate, &applied_rate,
110         &format, &start, &end, &base);
111
112     fail_unless (update == TRUE);
113     fail_unless (rate == 0.75);
114     fail_unless (applied_rate == 0.5);
115     fail_unless (format == GST_FORMAT_BYTES);
116     fail_unless (start == 0);
117     fail_unless (end == (G_MAXINT64 - 1));
118
119     gst_event_unref (event);
120   }
121
122   /* TAGS */
123   {
124     GstTagList *taglist = gst_tag_list_new ();
125     GstTagList *tl2 = NULL;
126
127     event = gst_event_new_tag (taglist);
128     fail_if (taglist == NULL);
129     fail_if (event == NULL);
130     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
131     fail_if (GST_EVENT_IS_UPSTREAM (event));
132     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
133     fail_unless (GST_EVENT_IS_SERIALIZED (event));
134
135     gst_event_parse_tag (event, &tl2);
136     fail_unless (taglist == tl2);
137     gst_event_unref (event);
138   }
139
140   /* QOS */
141   {
142     GstQOSType t1 = GST_QOS_TYPE_THROTTLE, t2;
143     gdouble p1 = 1.0, p2;
144     GstClockTimeDiff ctd1 = G_GINT64_CONSTANT (10), ctd2;
145     GstClockTime ct1 = G_GUINT64_CONSTANT (20), ct2;
146
147     event = gst_event_new_qos (t1, p1, ctd1, ct1);
148     fail_if (event == NULL);
149     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
150     fail_unless (GST_EVENT_IS_UPSTREAM (event));
151     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
152     fail_if (GST_EVENT_IS_SERIALIZED (event));
153
154     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
155     fail_unless (p1 == p2);
156     fail_unless (ctd1 == ctd2);
157     fail_unless (ct1 == ct2);
158     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
159     fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
160     fail_unless (p1 == p2);
161     fail_unless (ctd1 == ctd2);
162     fail_unless (ct1 == ct2);
163     gst_event_unref (event);
164
165     ctd1 = G_GINT64_CONSTANT (-10);
166     event = gst_event_new_qos (t1, p1, ctd1, ct1);
167     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
168     fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
169     gst_event_unref (event);
170
171     event = gst_event_new_qos (t1, p1, ctd1, ct1);
172     gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
173     fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
174     fail_unless (p1 == p2);
175     fail_unless (ctd1 == ctd2);
176     fail_unless (ct1 == ct2);
177     gst_event_unref (event);
178   }
179
180   /* SEEK */
181   {
182     gdouble rate;
183     GstFormat format;
184     GstSeekFlags flags;
185     GstSeekType cur_type, stop_type;
186     gint64 cur, stop;
187
188     event = gst_event_new_seek (0.5, GST_FORMAT_BYTES,
189         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
190         GST_SEEK_TYPE_SET, 1, GST_SEEK_TYPE_NONE, 0xdeadbeef);
191
192     fail_if (event == NULL);
193     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
194     fail_unless (GST_EVENT_IS_UPSTREAM (event));
195     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
196     fail_if (GST_EVENT_IS_SERIALIZED (event));
197
198     gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
199         &stop_type, &stop);
200     fail_unless (rate == 0.5);
201     fail_unless (format == GST_FORMAT_BYTES);
202     fail_unless (flags == (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE));
203     fail_unless (cur_type == GST_SEEK_TYPE_SET);
204     fail_unless (cur == 1);
205     fail_unless (stop_type == GST_SEEK_TYPE_NONE);
206     fail_unless (stop == 0xdeadbeef);
207
208     gst_event_unref (event);
209   }
210
211   /* NAVIGATION */
212   {
213     structure = gst_structure_new ("application/x-gst-navigation", "event",
214         G_TYPE_STRING, "key-press", "key", G_TYPE_STRING, "mon", NULL);
215     fail_if (structure == NULL);
216     event = gst_event_new_navigation (structure);
217     fail_if (event == NULL);
218     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NAVIGATION);
219     fail_unless (GST_EVENT_IS_UPSTREAM (event));
220     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
221     fail_if (GST_EVENT_IS_SERIALIZED (event));
222
223     fail_unless (gst_event_get_structure (event) == structure);
224     gst_event_unref (event);
225   }
226
227   /* Custom event types */
228   {
229     structure = gst_structure_empty_new ("application/x-custom");
230     fail_if (structure == NULL);
231     event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
232     fail_if (event == NULL);
233     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM);
234     fail_unless (GST_EVENT_IS_UPSTREAM (event));
235     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
236     fail_if (GST_EVENT_IS_SERIALIZED (event));
237     fail_unless (gst_event_get_structure (event) == structure);
238     fail_unless (gst_event_has_name (event, "application/x-custom"));
239     gst_event_unref (event);
240
241     /* Decided not to test the other custom enum types, as they
242      * only differ by the value of the enum passed to gst_event_new_custom
243      */
244   }
245
246   /* Event copying */
247   {
248     structure = gst_structure_empty_new ("application/x-custom");
249     fail_if (structure == NULL);
250     event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
251
252     fail_if (event == NULL);
253     event2 = gst_event_copy (event);
254     fail_if (event2 == NULL);
255     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TYPE (event2));
256     fail_unless (gst_event_has_name (event, "application/x-custom"));
257
258     /* The structure should have been duplicated */
259     fail_if (gst_event_get_structure (event) ==
260         gst_event_get_structure (event2));
261
262     gst_event_unref (event);
263     gst_event_unref (event2);
264   }
265
266   /* Make events writable */
267   {
268     structure = gst_structure_empty_new ("application/x-custom");
269     fail_if (structure == NULL);
270     event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
271     /* ref the event so that it becomes non-writable */
272     gst_event_ref (event);
273     gst_event_ref (event);
274     /* this should fail if the structure isn't writable */
275     ASSERT_CRITICAL (gst_structure_remove_all_fields ((GstStructure *)
276             gst_event_get_structure (event)));
277     fail_unless (gst_event_has_name (event, "application/x-custom"));
278
279     /* now make writable */
280     event2 =
281         GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event)));
282     fail_unless (event != event2);
283     /* this fail if the structure isn't writable */
284     gst_structure_remove_all_fields ((GstStructure *)
285         gst_event_get_structure (event2));
286     fail_unless (gst_event_has_name (event2, "application/x-custom"));
287
288     gst_event_unref (event);
289     gst_event_unref (event);
290     gst_event_unref (event2);
291   }
292 }
293
294 GST_END_TEST;
295
296 static GTimeVal sent_event_time;
297 static GstEvent *got_event_before_q, *got_event_after_q;
298 static GTimeVal got_event_time;
299
300 static gboolean
301 event_probe (GstPad * pad, GstMiniObject ** data, gpointer user_data)
302 {
303   gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data);
304
305   fail_unless (GST_IS_EVENT (data));
306
307   GST_DEBUG ("event probe called");
308
309   if (before_q) {
310     switch (GST_EVENT_TYPE (GST_EVENT (data))) {
311       case GST_EVENT_CUSTOM_UPSTREAM:
312       case GST_EVENT_CUSTOM_BOTH:
313       case GST_EVENT_CUSTOM_BOTH_OOB:
314         if (got_event_before_q != NULL)
315           break;
316         gst_event_ref ((GstEvent *) data);
317         g_get_current_time (&got_event_time);
318         got_event_before_q = GST_EVENT (data);
319         break;
320       default:
321         break;
322     }
323   } else {
324     switch (GST_EVENT_TYPE (GST_EVENT (data))) {
325       case GST_EVENT_CUSTOM_DOWNSTREAM:
326       case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
327       case GST_EVENT_CUSTOM_BOTH:
328       case GST_EVENT_CUSTOM_BOTH_OOB:
329         if (got_event_after_q != NULL)
330           break;
331         gst_event_ref ((GstEvent *) data);
332         g_get_current_time (&got_event_time);
333         got_event_after_q = GST_EVENT (data);
334         break;
335       default:
336         break;
337     }
338   }
339
340   return TRUE;
341 }
342
343 static void test_event
344     (GstBin * pipeline, GstEventType type, GstPad * pad,
345     gboolean expect_before_q, GstPad * fake_srcpad)
346 {
347   GstEvent *event;
348   GstPad *peer;
349   gint i;
350
351   got_event_before_q = got_event_after_q = NULL;
352
353   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
354   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
355       GST_CLOCK_TIME_NONE);
356
357   GST_DEBUG ("test event called");
358
359   event = gst_event_new_custom (type,
360       gst_structure_empty_new ("application/x-custom"));
361   g_get_current_time (&sent_event_time);
362   got_event_time.tv_sec = 0;
363   got_event_time.tv_usec = 0;
364
365   /* We block the pad so the stream lock is released and we can send the event */
366   fail_unless (gst_pad_set_blocked (fake_srcpad, TRUE) == TRUE);
367
368   /* We send on the peer pad, since the pad is blocked */
369   fail_unless ((peer = gst_pad_get_peer (pad)) != NULL);
370   gst_pad_send_event (peer, event);
371   gst_object_unref (peer);
372
373   fail_unless (gst_pad_set_blocked (fake_srcpad, FALSE) == TRUE);
374
375   if (expect_before_q) {
376     /* Wait up to 5 seconds for the event to appear */
377     for (i = 0; i < 500; i++) {
378       g_usleep (G_USEC_PER_SEC / 100);
379       if (got_event_before_q != NULL)
380         break;
381     }
382     fail_if (got_event_before_q == NULL,
383         "Expected event failed to appear upstream of the queue "
384         "within 5 seconds");
385     fail_unless (GST_EVENT_TYPE (got_event_before_q) == type);
386   } else {
387     /* Wait up to 10 seconds for the event to appear */
388     for (i = 0; i < 1000; i++) {
389       g_usleep (G_USEC_PER_SEC / 100);
390       if (got_event_after_q != NULL)
391         break;
392     }
393     fail_if (got_event_after_q == NULL,
394         "Expected event failed to appear after the queue within 10 seconds");
395     fail_unless (GST_EVENT_TYPE (got_event_after_q) == type);
396   }
397
398   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
399   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
400       GST_CLOCK_TIME_NONE);
401
402   if (got_event_before_q)
403     gst_event_unref (got_event_before_q);
404   if (got_event_after_q)
405     gst_event_unref (got_event_after_q);
406
407   got_event_before_q = got_event_after_q = NULL;
408 }
409
410 static gint64
411 timediff (GTimeVal * end, GTimeVal * start)
412 {
413   return (end->tv_sec - start->tv_sec) * G_USEC_PER_SEC +
414       (end->tv_usec - start->tv_usec);
415 }
416
417 GST_START_TEST (send_custom_events)
418 {
419   /* Run some tests on custom events. Checking for serialisation and whatnot.
420    * pipeline is fakesrc ! queue ! fakesink */
421   GstBin *pipeline;
422   GstElement *fakesrc, *fakesink, *queue;
423   GstPad *srcpad, *sinkpad;
424
425   fail_if ((pipeline = (GstBin *) gst_pipeline_new ("testpipe")) == NULL);
426   fail_if ((fakesrc = gst_element_factory_make ("fakesrc", NULL)) == NULL);
427   fail_if ((fakesink = gst_element_factory_make ("fakesink", NULL)) == NULL);
428   fail_if ((queue = gst_element_factory_make ("queue", NULL)) == NULL);
429
430   gst_bin_add_many (pipeline, fakesrc, queue, fakesink, NULL);
431   fail_unless (gst_element_link_many (fakesrc, queue, fakesink, NULL));
432
433   g_object_set (G_OBJECT (fakesink), "sync", FALSE, NULL);
434
435   /* Send 100 buffers per sec */
436   g_object_set (G_OBJECT (fakesrc), "silent", TRUE, "datarate", 100,
437       "sizemax", 1, "sizetype", 2, NULL);
438   g_object_set (G_OBJECT (queue), "max-size-buffers", 0, "max-size-time",
439       (guint64) GST_SECOND, "max-size-bytes", 0, NULL);
440   g_object_set (G_OBJECT (fakesink), "silent", TRUE, "sync", TRUE, NULL);
441
442   /* add pad-probes to faksrc.src and fakesink.sink */
443   fail_if ((srcpad = gst_element_get_static_pad (fakesrc, "src")) == NULL);
444   gst_pad_add_event_probe (srcpad, (GCallback) event_probe,
445       GINT_TO_POINTER (TRUE));
446
447   fail_if ((sinkpad = gst_element_get_static_pad (fakesink, "sink")) == NULL);
448   gst_pad_add_event_probe (sinkpad, (GCallback) event_probe,
449       GINT_TO_POINTER (FALSE));
450
451   /* Upstream events */
452   test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad);
453   fail_unless (timediff (&got_event_time,
454           &sent_event_time) < G_USEC_PER_SEC / 2,
455       "GST_EVENT_CUSTOM_UP took too long to reach source: %"
456       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
457
458   test_event (pipeline, GST_EVENT_CUSTOM_BOTH, sinkpad, TRUE, srcpad);
459   fail_unless (timediff (&got_event_time,
460           &sent_event_time) < G_USEC_PER_SEC / 2,
461       "GST_EVENT_CUSTOM_BOTH took too long to reach source: %"
462       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
463
464   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, sinkpad, TRUE, srcpad);
465   fail_unless (timediff (&got_event_time,
466           &sent_event_time) < G_USEC_PER_SEC / 2,
467       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
468       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
469
470   /* Out of band downstream events */
471   test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM_OOB, srcpad, FALSE, srcpad);
472   fail_unless (timediff (&got_event_time,
473           &sent_event_time) < G_USEC_PER_SEC / 2,
474       "GST_EVENT_CUSTOM_DS_OOB took too long to reach source: %"
475       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
476
477   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, srcpad, FALSE, srcpad);
478   fail_unless (timediff (&got_event_time,
479           &sent_event_time) < G_USEC_PER_SEC / 2,
480       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
481       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
482
483   /* In-band downstream events are expected to take at least 1 second
484    * to traverse the the queue */
485   test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM, srcpad, FALSE, srcpad);
486   fail_unless (timediff (&got_event_time,
487           &sent_event_time) >= G_USEC_PER_SEC / 2,
488       "GST_EVENT_CUSTOM_DS arrived too quickly for an in-band event: %"
489       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
490
491   test_event (pipeline, GST_EVENT_CUSTOM_BOTH, srcpad, FALSE, srcpad);
492   fail_unless (timediff (&got_event_time,
493           &sent_event_time) >= G_USEC_PER_SEC / 2,
494       "GST_EVENT_CUSTOM_BOTH arrived too quickly for an in-band event: %"
495       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
496
497   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
498   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
499       GST_CLOCK_TIME_NONE);
500
501   gst_object_unref (pipeline);
502 }
503
504 GST_END_TEST;
505
506 static Suite *
507 gst_event_suite (void)
508 {
509   Suite *s = suite_create ("GstEvent");
510   TCase *tc_chain = tcase_create ("events");
511
512   tcase_set_timeout (tc_chain, 20);
513
514   suite_add_tcase (s, tc_chain);
515   tcase_add_test (tc_chain, create_events);
516   tcase_add_test (tc_chain, send_custom_events);
517   return s;
518 }
519
520 GST_CHECK_MAIN (gst_event);