1 /* GStreamer
2 *
3 * some unit tests for GstBaseSrc
4 *
5 * Copyright (C) 2006-2017 Tim-Philipp Müller <tim centricular net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <gst/gst.h>
27 #include <gst/check/gstcheck.h>
28 #include <gst/check/gstconsistencychecker.h>
29 #include <gst/base/gstbasesrc.h>
30
31 static GstPadProbeReturn
eos_event_counter(GstObject * pad,GstPadProbeInfo * info,guint * p_num_eos)32 eos_event_counter (GstObject * pad, GstPadProbeInfo * info, guint * p_num_eos)
33 {
34 GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
35
36 fail_unless (event != NULL);
37 fail_unless (GST_IS_EVENT (event));
38
39 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
40 *p_num_eos += 1;
41
42 return GST_PAD_PROBE_OK;
43 }
44
45 /* basesrc_eos_events_push_live_op:
46 * - make sure source does send an EOS event when operating in push
47 * mode and being set to READY explicitly (like one might with
48 * live sources)
49 */
GST_START_TEST(basesrc_eos_events_push_live_op)50 GST_START_TEST (basesrc_eos_events_push_live_op)
51 {
52 GstStateChangeReturn state_ret;
53 GstElement *src, *sink, *pipe;
54 GstMessage *msg;
55 GstBus *bus;
56 GstPad *srcpad;
57 guint probe, num_eos = 0;
58 GstStreamConsistency *consistency;
59 GstEvent *eos_event;
60 guint32 eos_event_seqnum;
61
62 pipe = gst_pipeline_new ("pipeline");
63 sink = gst_element_factory_make ("fakesink", "sink");
64 src = gst_element_factory_make ("fakesrc", "src");
65
66 g_assert (pipe != NULL);
67 g_assert (sink != NULL);
68 g_assert (src != NULL);
69
70 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
71 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
72
73 fail_unless (gst_element_link (src, sink) == TRUE);
74
75 g_object_set (sink, "can-activate-push", TRUE, NULL);
76 g_object_set (sink, "can-activate-pull", FALSE, NULL);
77
78 g_object_set (src, "can-activate-push", TRUE, NULL);
79 g_object_set (src, "can-activate-pull", FALSE, NULL);
80
81 /* set up event probe to count EOS events */
82 srcpad = gst_element_get_static_pad (src, "src");
83 fail_unless (srcpad != NULL);
84
85 consistency = gst_consistency_checker_new (srcpad);
86
87 probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
88 (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
89
90 bus = gst_element_get_bus (pipe);
91
92 gst_element_set_state (pipe, GST_STATE_PLAYING);
93 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
94 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
95
96 /* wait a second, then do controlled shutdown */
97 g_usleep (GST_USECOND * 1);
98
99 /* shut down pipeline (should send EOS message) ... */
100 eos_event = gst_event_new_eos ();
101 eos_event_seqnum = gst_event_get_seqnum (eos_event);
102 gst_element_send_event (pipe, eos_event);
103
104 /* ... and wait for the EOS message from the sink */
105 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
106 fail_unless (msg != NULL);
107 fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR);
108 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
109
110 /* should be exactly one EOS event */
111 fail_unless (num_eos == 1);
112 fail_unless (gst_message_get_seqnum (msg) == eos_event_seqnum);
113
114 gst_element_set_state (pipe, GST_STATE_NULL);
115 gst_element_get_state (pipe, NULL, NULL, -1);
116
117 /* make sure source hasn't sent a second one when going PAUSED => READY */
118 fail_unless (num_eos == 1);
119
120 gst_consistency_checker_free (consistency);
121
122 gst_pad_remove_probe (srcpad, probe);
123 gst_object_unref (srcpad);
124 gst_message_unref (msg);
125 gst_object_unref (bus);
126 gst_object_unref (pipe);
127 }
128
129 GST_END_TEST;
130
131
132
133 /* basesrc_eos_events_push:
134 * - make sure source only sends one EOS when operating in push-mode,
135 * reaching the max number of buffers, and is then shut down.
136 */
GST_START_TEST(basesrc_eos_events_push)137 GST_START_TEST (basesrc_eos_events_push)
138 {
139 GstStateChangeReturn state_ret;
140 GstElement *src, *sink, *pipe;
141 GstMessage *msg;
142 GstBus *bus;
143 GstPad *srcpad;
144 guint probe, num_eos = 0;
145 GstStreamConsistency *consistency;
146
147 pipe = gst_pipeline_new ("pipeline");
148 sink = gst_element_factory_make ("fakesink", "sink");
149 src = gst_element_factory_make ("fakesrc", "src");
150
151 g_assert (pipe != NULL);
152 g_assert (sink != NULL);
153 g_assert (src != NULL);
154
155 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
156 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
157
158 fail_unless (gst_element_link (src, sink) == TRUE);
159
160 g_object_set (sink, "can-activate-push", TRUE, NULL);
161 g_object_set (sink, "can-activate-pull", FALSE, NULL);
162
163 g_object_set (src, "can-activate-push", TRUE, NULL);
164 g_object_set (src, "can-activate-pull", FALSE, NULL);
165 g_object_set (src, "num-buffers", 8, NULL);
166
167 /* set up event probe to count EOS events */
168 srcpad = gst_element_get_static_pad (src, "src");
169 fail_unless (srcpad != NULL);
170
171 consistency = gst_consistency_checker_new (srcpad);
172
173 probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
174 (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
175
176 bus = gst_element_get_bus (pipe);
177
178 gst_element_set_state (pipe, GST_STATE_PLAYING);
179 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
180 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
181
182 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
183 fail_unless (msg != NULL);
184 fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR);
185 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
186
187 /* should be exactly one EOS event */
188 fail_unless (num_eos == 1);
189
190 gst_element_set_state (pipe, GST_STATE_NULL);
191 gst_element_get_state (pipe, NULL, NULL, -1);
192
193 /* make sure source hasn't sent a second one when going PAUSED => READY */
194 fail_unless (num_eos == 1);
195
196 gst_consistency_checker_free (consistency);
197
198 gst_pad_remove_probe (srcpad, probe);
199 gst_object_unref (srcpad);
200 gst_message_unref (msg);
201 gst_object_unref (bus);
202 gst_object_unref (pipe);
203 }
204
205 GST_END_TEST;
206
207 /* basesrc_eos_events_pull_live_op:
208 * - make sure source doesn't send an EOS event when operating in
209 * pull mode and being set to READY explicitly (like one might with
210 * live sources)
211 */
GST_START_TEST(basesrc_eos_events_pull_live_op)212 GST_START_TEST (basesrc_eos_events_pull_live_op)
213 {
214 GstStateChangeReturn state_ret;
215 GstElement *src, *sink, *pipe;
216 GstPad *srcpad;
217 guint probe, num_eos = 0;
218
219 pipe = gst_pipeline_new ("pipeline");
220 sink = gst_element_factory_make ("fakesink", "sink");
221 src = gst_element_factory_make ("fakesrc", "src");
222
223 g_assert (pipe != NULL);
224 g_assert (sink != NULL);
225 g_assert (src != NULL);
226
227 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
228 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
229
230 fail_unless (gst_element_link (src, sink) == TRUE);
231
232 g_object_set (sink, "can-activate-push", FALSE, NULL);
233 g_object_set (sink, "can-activate-pull", TRUE, NULL);
234
235 g_object_set (src, "can-activate-push", FALSE, NULL);
236 g_object_set (src, "can-activate-pull", TRUE, NULL);
237
238 /* set up event probe to count EOS events */
239 srcpad = gst_element_get_static_pad (src, "src");
240 fail_unless (srcpad != NULL);
241
242 probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
243 (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
244
245 gst_element_set_state (pipe, GST_STATE_PLAYING);
246 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
247 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
248
249 /* wait a second, then do controlled shutdown */
250 g_usleep (GST_USECOND * 1);
251
252 /* shut down source only ... */
253 gst_element_set_state (src, GST_STATE_NULL);
254 state_ret = gst_element_get_state (src, NULL, NULL, -1);
255 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
256
257 fail_unless (gst_element_set_locked_state (src, TRUE) == TRUE);
258
259 /* source shouldn't have sent any EOS event in pull mode */
260 fail_unless (num_eos == 0);
261
262 gst_element_set_state (pipe, GST_STATE_NULL);
263 gst_element_get_state (pipe, NULL, NULL, -1);
264
265 /* make sure source hasn't sent an EOS when going PAUSED => READY either */
266 fail_unless (num_eos == 0);
267
268 gst_pad_remove_probe (srcpad, probe);
269 gst_object_unref (srcpad);
270 gst_object_unref (pipe);
271 }
272
273 GST_END_TEST;
274
275 /* basesrc_eos_events_pull:
276 * - makes sure source doesn't send EOS event when reaching the max.
277 * number of buffers configured in pull-mode
278 * - make sure source doesn't send EOS event either when being shut down
279 * (PAUSED => READY state change) after EOSing in pull mode
280 */
GST_START_TEST(basesrc_eos_events_pull)281 GST_START_TEST (basesrc_eos_events_pull)
282 {
283 GstStateChangeReturn state_ret;
284 GstElement *src, *sink, *pipe;
285 GstMessage *msg;
286 GstBus *bus;
287 GstPad *srcpad;
288 guint probe, num_eos = 0;
289
290 pipe = gst_pipeline_new ("pipeline");
291 sink = gst_element_factory_make ("fakesink", "sink");
292 src = gst_element_factory_make ("fakesrc", "src");
293
294 g_assert (pipe != NULL);
295 g_assert (sink != NULL);
296 g_assert (src != NULL);
297
298 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
299 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
300
301 fail_unless (gst_element_link (src, sink) == TRUE);
302
303 g_object_set (sink, "can-activate-push", FALSE, NULL);
304 g_object_set (sink, "can-activate-pull", TRUE, NULL);
305
306 g_object_set (src, "can-activate-push", FALSE, NULL);
307 g_object_set (src, "can-activate-pull", TRUE, NULL);
308 g_object_set (src, "num-buffers", 8, NULL);
309
310 /* set up event probe to count EOS events */
311 srcpad = gst_element_get_static_pad (src, "src");
312 fail_unless (srcpad != NULL);
313
314 probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
315 (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
316
317 bus = gst_element_get_bus (pipe);
318
319 gst_element_set_state (pipe, GST_STATE_PLAYING);
320 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
321 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
322
323 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
324 fail_unless (msg != NULL);
325 fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR);
326 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
327
328 /* source shouldn't have sent any EOS event in pull mode */
329 fail_unless (num_eos == 0);
330
331 gst_element_set_state (pipe, GST_STATE_NULL);
332 gst_element_get_state (pipe, NULL, NULL, -1);
333
334 /* make sure source hasn't sent an EOS when going PAUSED => READY either */
335 fail_unless (num_eos == 0);
336
337 gst_pad_remove_probe (srcpad, probe);
338 gst_object_unref (srcpad);
339 gst_message_unref (msg);
340 gst_object_unref (bus);
341 gst_object_unref (pipe);
342 }
343
344 GST_END_TEST;
345
346
347 /* basesrc_eos_events_push_live_eos:
348 * - make sure the source stops and emits EOS when we send an EOS event to the
349 * pipeline.
350 */
GST_START_TEST(basesrc_eos_events_push_live_eos)351 GST_START_TEST (basesrc_eos_events_push_live_eos)
352 {
353 GstStateChangeReturn state_ret;
354 GstElement *src, *sink, *pipe;
355 GstMessage *msg;
356 GstBus *bus;
357 GstPad *srcpad;
358 guint probe, num_eos = 0;
359 gboolean res;
360
361 pipe = gst_pipeline_new ("pipeline");
362 sink = gst_element_factory_make ("fakesink", "sink");
363 src = gst_element_factory_make ("fakesrc", "src");
364
365 g_assert (pipe != NULL);
366 g_assert (sink != NULL);
367 g_assert (src != NULL);
368
369 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
370 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
371
372 fail_unless (gst_element_link (src, sink) == TRUE);
373
374 g_object_set (sink, "can-activate-push", TRUE, NULL);
375 g_object_set (sink, "can-activate-pull", FALSE, NULL);
376
377 g_object_set (src, "can-activate-push", TRUE, NULL);
378 g_object_set (src, "can-activate-pull", FALSE, NULL);
379
380 /* set up event probe to count EOS events */
381 srcpad = gst_element_get_static_pad (src, "src");
382 fail_unless (srcpad != NULL);
383
384 probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
385 (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
386
387 bus = gst_element_get_bus (pipe);
388
389 gst_element_set_state (pipe, GST_STATE_PLAYING);
390 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
391 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
392
393 /* wait a second, then emit the EOS */
394 g_usleep (GST_USECOND * 1);
395
396 /* shut down source only (should send EOS event) ... */
397 res = gst_element_send_event (pipe, gst_event_new_eos ());
398 fail_unless (res == TRUE);
399
400 /* ... and wait for the EOS message from the sink */
401 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
402 fail_unless (msg != NULL);
403 fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR);
404 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
405
406 /* should be exactly one EOS event */
407 fail_unless (num_eos == 1);
408
409 gst_element_set_state (pipe, GST_STATE_NULL);
410 gst_element_get_state (pipe, NULL, NULL, -1);
411
412 /* make sure source hasn't sent a second one when going PAUSED => READY */
413 fail_unless (num_eos == 1);
414
415 gst_pad_remove_probe (srcpad, probe);
416 gst_object_unref (srcpad);
417 gst_message_unref (msg);
418 gst_object_unref (bus);
419 gst_object_unref (pipe);
420 }
421
422 GST_END_TEST;
423
424 /* basesrc_eos_events_pull_live_eos:
425 * - make sure the source stops and emits EOS when we send an EOS event to the
426 * pipeline.
427 */
GST_START_TEST(basesrc_eos_events_pull_live_eos)428 GST_START_TEST (basesrc_eos_events_pull_live_eos)
429 {
430 GstStateChangeReturn state_ret;
431 GstElement *src, *sink, *pipe;
432 GstMessage *msg;
433 GstBus *bus;
434 GstPad *srcpad;
435 guint probe, num_eos = 0;
436 gboolean res;
437
438 pipe = gst_pipeline_new ("pipeline");
439 sink = gst_element_factory_make ("fakesink", "sink");
440 src = gst_element_factory_make ("fakesrc", "src");
441
442 g_assert (pipe != NULL);
443 g_assert (sink != NULL);
444 g_assert (src != NULL);
445
446 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
447 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
448
449 fail_unless (gst_element_link (src, sink) == TRUE);
450
451 g_object_set (sink, "can-activate-push", FALSE, NULL);
452 g_object_set (sink, "can-activate-pull", TRUE, NULL);
453
454 g_object_set (src, "can-activate-push", FALSE, NULL);
455 g_object_set (src, "can-activate-pull", TRUE, NULL);
456
457 /* set up event probe to count EOS events */
458 srcpad = gst_element_get_static_pad (src, "src");
459 fail_unless (srcpad != NULL);
460
461 probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
462 (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
463
464 bus = gst_element_get_bus (pipe);
465
466 gst_element_set_state (pipe, GST_STATE_PLAYING);
467 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
468 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
469
470 /* wait a second, then emit the EOS */
471 g_usleep (GST_USECOND * 1);
472
473 /* shut down source only (should send EOS event) ... */
474 res = gst_element_send_event (pipe, gst_event_new_eos ());
475 fail_unless (res == TRUE);
476
477 /* ... and wait for the EOS message from the sink */
478 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
479 fail_unless (msg != NULL);
480 fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR);
481 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
482
483 /* no EOS in pull mode */
484 fail_unless (num_eos == 0);
485
486 gst_element_set_state (pipe, GST_STATE_NULL);
487 gst_element_get_state (pipe, NULL, NULL, -1);
488
489 /* make sure source hasn't sent a second one when going PAUSED => READY */
490 fail_unless (num_eos == 0);
491
492 gst_pad_remove_probe (srcpad, probe);
493 gst_object_unref (srcpad);
494 gst_message_unref (msg);
495 gst_object_unref (bus);
496 gst_object_unref (pipe);
497 }
498
499 GST_END_TEST;
500
501
502 static GstPadProbeReturn
segment_event_catcher(GstObject * pad,GstPadProbeInfo * info,gpointer * user_data)503 segment_event_catcher (GstObject * pad, GstPadProbeInfo * info,
504 gpointer * user_data)
505 {
506 GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
507 GstEvent **last_event = (GstEvent **) user_data;
508 fail_unless (event != NULL);
509 fail_unless (GST_IS_EVENT (event));
510 fail_unless (user_data != NULL);
511
512 if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
513 g_mutex_lock (&check_mutex);
514 fail_unless (*last_event == NULL);
515 *last_event = gst_event_copy (event);
516 g_cond_signal (&check_cond);
517 g_mutex_unlock (&check_mutex);
518 }
519
520 return GST_PAD_PROBE_OK;
521 }
522
523 /* basesrc_seek_events_rate_update:
524 * - make sure we get expected segment after sending a seek event
525 */
GST_START_TEST(basesrc_seek_events_rate_update)526 GST_START_TEST (basesrc_seek_events_rate_update)
527 {
528 GstStateChangeReturn state_ret;
529 GstElement *src, *sink, *pipe;
530 GstMessage *msg;
531 GstBus *bus;
532 GstPad *probe_pad;
533 guint probe;
534 GstEvent *seg_event = NULL;
535 GstEvent *rate_seek;
536 gboolean event_ret;
537 const GstSegment *segment;
538
539 pipe = gst_pipeline_new ("pipeline");
540 sink = gst_element_factory_make ("fakesink", "sink");
541 src = gst_element_factory_make ("fakesrc", "src");
542
543 g_assert (pipe != NULL);
544 g_assert (sink != NULL);
545 g_assert (src != NULL);
546
547 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
548 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
549
550 fail_unless (gst_element_link (src, sink) == TRUE);
551
552 bus = gst_element_get_bus (pipe);
553
554 /* set up event probe to catch new segment event */
555 probe_pad = gst_element_get_static_pad (sink, "sink");
556 fail_unless (probe_pad != NULL);
557
558 probe = gst_pad_add_probe (probe_pad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
559 (GstPadProbeCallback) segment_event_catcher, &seg_event, NULL);
560
561 /* prepare the seek */
562 rate_seek = gst_event_new_seek (0.5, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
563 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
564 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
565
566 GST_INFO ("going to playing");
567
568 /* play */
569 gst_element_set_state (pipe, GST_STATE_PLAYING);
570 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
571 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
572
573 /* wait for the first segment to be posted, and flush it ... */
574 g_mutex_lock (&check_mutex);
575 while (seg_event == NULL)
576 g_cond_wait (&check_cond, &check_mutex);
577 gst_event_unref (seg_event);
578 seg_event = NULL;
579 g_mutex_unlock (&check_mutex);
580
581 GST_INFO ("seeking");
582
583 /* seek */
584 event_ret = gst_element_send_event (pipe, rate_seek);
585 fail_unless (event_ret == TRUE);
586
587 /* wait for the updated segment to be posted, posting EOS make the loop
588 * thread exit before the updated segment is posted ... */
589 g_mutex_lock (&check_mutex);
590 while (seg_event == NULL)
591 g_cond_wait (&check_cond, &check_mutex);
592 g_mutex_unlock (&check_mutex);
593
594 /* shut down pipeline only (should send EOS message) ... */
595 gst_element_send_event (pipe, gst_event_new_eos ());
596
597 /* ... and wait for the EOS message from the sink */
598 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
599 fail_unless (msg != NULL);
600 fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR);
601 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
602
603 gst_element_set_state (pipe, GST_STATE_NULL);
604 gst_element_get_state (pipe, NULL, NULL, -1);
605
606 GST_INFO ("stopped");
607
608 /* check that we have go the event */
609 fail_unless (seg_event != NULL);
610
611 gst_event_parse_segment (seg_event, &segment);
612 fail_unless (segment->rate == 0.5);
613
614 gst_pad_remove_probe (probe_pad, probe);
615 gst_object_unref (probe_pad);
616 gst_message_unref (msg);
617 gst_event_unref (seg_event);
618 gst_object_unref (bus);
619 gst_object_unref (pipe);
620 }
621
622 GST_END_TEST;
623
624
625 typedef struct
626 {
627 gboolean seeked;
628 gint buffer_count;
629 GList *events;
630 } LastBufferSeekData;
631
632 static GstPadProbeReturn
seek_on_buffer(GstObject * pad,GstPadProbeInfo * info,gpointer * user_data)633 seek_on_buffer (GstObject * pad, GstPadProbeInfo * info, gpointer * user_data)
634 {
635 LastBufferSeekData *data = (LastBufferSeekData *) user_data;
636
637 fail_unless (user_data != NULL);
638
639 if (info->type & GST_PAD_PROBE_TYPE_BUFFER) {
640 data->buffer_count++;
641
642 if (!data->seeked) {
643 fail_unless (gst_pad_push_event (GST_PAD (pad),
644 gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
645 GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 1)));
646 data->seeked = TRUE;
647 }
648 } else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) {
649 data->events = g_list_append (data->events, gst_event_ref (info->data));
650 } else {
651 fail ("Should not be reached");
652 }
653 return GST_PAD_PROBE_OK;
654 }
655
656 /* basesrc_seek_on_last_buffer:
657 * - make sure basesrc doesn't go eos if a seek is sent
658 * after the last buffer push
659 *
660 * This is just a test and is a controlled environment.
661 * For testing purposes sending the seek from the streaming
662 * thread is ok but doing this in an application might not
663 * be a good idea.
664 */
GST_START_TEST(basesrc_seek_on_last_buffer)665 GST_START_TEST (basesrc_seek_on_last_buffer)
666 {
667 GstStateChangeReturn state_ret;
668 GstElement *src, *sink, *pipe;
669 GstMessage *msg;
670 GstBus *bus;
671 GstPad *probe_pad;
672 guint probe;
673 GstEvent *seek;
674 LastBufferSeekData seek_data;
675
676 pipe = gst_pipeline_new ("pipeline");
677 sink = gst_element_factory_make ("fakesink", "sink");
678 src = gst_element_factory_make ("fakesrc", "src");
679
680 g_assert (pipe != NULL);
681 g_assert (sink != NULL);
682 g_assert (src != NULL);
683
684 /* use 'sizemax' buffers to avoid receiving empty buffers */
685 g_object_set (src, "sizetype", 2, NULL);
686
687 fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE);
688 fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE);
689
690 fail_unless (gst_element_link (src, sink) == TRUE);
691
692 bus = gst_element_get_bus (pipe);
693
694 /* set up probe to catch the last buffer and send a seek event */
695 probe_pad = gst_element_get_static_pad (sink, "sink");
696 fail_unless (probe_pad != NULL);
697
698 seek_data.buffer_count = 0;
699 seek_data.seeked = FALSE;
700 seek_data.events = NULL;
701
702 probe =
703 gst_pad_add_probe (probe_pad,
704 GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
705 (GstPadProbeCallback) seek_on_buffer, &seek_data, NULL);
706
707 /* prepare the segment so that it has only one buffer */
708 seek = gst_event_new_seek (1, GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
709 GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 1);
710
711 gst_element_set_state (pipe, GST_STATE_READY);
712 fail_unless (gst_element_send_event (src, seek));
713
714 GST_INFO ("going to playing");
715
716 /* play */
717 gst_element_set_state (pipe, GST_STATE_PLAYING);
718 state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
719 fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
720
721 /* ... and wait for the EOS message from the sink */
722 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
723 fail_unless (msg != NULL);
724 fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR);
725 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
726
727 gst_element_set_state (pipe, GST_STATE_NULL);
728 gst_element_get_state (pipe, NULL, NULL, -1);
729
730 GST_INFO ("stopped");
731
732 /* check that we have go the event */
733 fail_unless (seek_data.buffer_count == 2);
734 fail_unless (seek_data.seeked);
735
736 /* events: stream-start -> segment -> segment -> eos */
737 fail_unless (g_list_length (seek_data.events) == 4);
738 {
739 GstEvent *event;
740
741 event = seek_data.events->data;
742 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
743 gst_event_unref (event);
744 seek_data.events = g_list_delete_link (seek_data.events, seek_data.events);
745
746 event = seek_data.events->data;
747 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
748 gst_event_unref (event);
749 seek_data.events = g_list_delete_link (seek_data.events, seek_data.events);
750
751 event = seek_data.events->data;
752 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
753 gst_event_unref (event);
754 seek_data.events = g_list_delete_link (seek_data.events, seek_data.events);
755
756 event = seek_data.events->data;
757 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
758 gst_event_unref (event);
759 seek_data.events = g_list_delete_link (seek_data.events, seek_data.events);
760 }
761
762 gst_pad_remove_probe (probe_pad, probe);
763 gst_object_unref (probe_pad);
764 gst_message_unref (msg);
765 gst_object_unref (bus);
766 gst_object_unref (pipe);
767 }
768
769 GST_END_TEST;
770
771 typedef GstBaseSrc TestSrc;
772 typedef GstBaseSrcClass TestSrcClass;
773
774 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
775 GST_PAD_SRC,
776 GST_PAD_ALWAYS,
777 GST_STATIC_CAPS_ANY);
778
779 static GType test_src_get_type (void);
780
781 G_DEFINE_TYPE (TestSrc, test_src, GST_TYPE_BASE_SRC);
782
783 static void
test_src_init(TestSrc * src)784 test_src_init (TestSrc * src)
785 {
786 }
787
788 static GstFlowReturn
test_src_create(GstBaseSrc * src,guint64 offset,guint size,GstBuffer ** p_buf)789 test_src_create (GstBaseSrc * src, guint64 offset, guint size,
790 GstBuffer ** p_buf)
791 {
792 GstBuffer *buf;
793 static int num = 0;
794
795 fail_if (*p_buf != NULL);
796
797 buf = gst_buffer_new ();
798 GST_BUFFER_OFFSET (buf) = num++;
799
800 if (num == 1 || g_random_boolean ()) {
801 GstBufferList *buflist = gst_buffer_list_new ();
802
803 gst_buffer_list_add (buflist, buf);
804
805 buf = gst_buffer_new ();
806 GST_BUFFER_OFFSET (buf) = num++;
807 gst_buffer_list_add (buflist, buf);
808 gst_base_src_submit_buffer_list (src, buflist);
809 } else {
810 *p_buf = buf;
811 }
812
813 return GST_FLOW_OK;
814 }
815
816 static void
test_src_class_init(TestSrcClass * klass)817 test_src_class_init (TestSrcClass * klass)
818 {
819 GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
820
821 gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass),
822 &src_template);
823
824 gstbasesrc_class->create = test_src_create;
825 }
826
827 static GstPad *mysinkpad;
828
829 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
830 GST_PAD_SINK,
831 GST_PAD_ALWAYS,
832 GST_STATIC_CAPS_ANY);
833
834 #define NUM_BUFFERS 100
835 static gboolean done;
836 static guint expect_offset;
837
838 static GstFlowReturn
chain_____func(GstPad * pad,GstObject * parent,GstBuffer * buf)839 chain_____func (GstPad * pad, GstObject * parent, GstBuffer * buf)
840 {
841 GST_LOG (" buffer # %3u", (guint) GST_BUFFER_OFFSET (buf));
842
843 fail_unless_equals_int (GST_BUFFER_OFFSET (buf), expect_offset);
844 ++expect_offset;
845
846 if (GST_BUFFER_OFFSET (buf) > NUM_BUFFERS) {
847 g_mutex_lock (&check_mutex);
848 done = TRUE;
849 g_cond_signal (&check_cond);
850 g_mutex_unlock (&check_mutex);
851 }
852 gst_buffer_unref (buf);
853
854 return GST_FLOW_OK;
855 }
856
857 static GstFlowReturn
chainlist_func(GstPad * pad,GstObject * parent,GstBufferList * list)858 chainlist_func (GstPad * pad, GstObject * parent, GstBufferList * list)
859 {
860 guint i, len;
861
862 len = gst_buffer_list_length (list);
863
864 GST_DEBUG ("buffer list with %u buffers", len);
865 for (i = 0; i < len; ++i) {
866 GstBuffer *buf = gst_buffer_list_get (list, i);
867 GST_LOG (" buffer # %3u", (guint) GST_BUFFER_OFFSET (buf));
868
869 fail_unless_equals_int (GST_BUFFER_OFFSET (buf), expect_offset);
870 ++expect_offset;
871 }
872
873 gst_buffer_list_unref (list);
874 return GST_FLOW_OK;
875 }
876
GST_START_TEST(basesrc_create_bufferlist)877 GST_START_TEST (basesrc_create_bufferlist)
878 {
879 GstElement *src;
880
881 src = g_object_new (test_src_get_type (), NULL);
882
883 mysinkpad = gst_check_setup_sink_pad (src, &sinktemplate);
884 gst_pad_set_chain_function (mysinkpad, chain_____func);
885 gst_pad_set_chain_list_function (mysinkpad, chainlist_func);
886 gst_pad_set_active (mysinkpad, TRUE);
887
888 done = FALSE;
889 expect_offset = 0;
890
891 gst_element_set_state (src, GST_STATE_PLAYING);
892
893 g_mutex_lock (&check_mutex);
894 while (!done)
895 g_cond_wait (&check_cond, &check_mutex);
896 g_mutex_unlock (&check_mutex);
897
898 gst_element_set_state (src, GST_STATE_NULL);
899
900 gst_check_teardown_sink_pad (src);
901
902 gst_object_unref (src);
903 }
904
905 GST_END_TEST;
906
907 typedef struct
908 {
909 GstBaseSrc parent;
910 GstSegment *segment;
911 gboolean n_output_buffers;
912 gsize num_times_negotiate_called;
913 gboolean do_renegotiate;
914 } TimeSrc;
915
916 typedef GstBaseSrcClass TimeSrcClass;
917
918 static GType time_src_get_type (void);
919
920 G_DEFINE_TYPE (TimeSrc, time_src, GST_TYPE_BASE_SRC);
921
922 static void
time_src_init(TimeSrc * src)923 time_src_init (TimeSrc * src)
924 {
925 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
926 gst_base_src_set_automatic_eos (GST_BASE_SRC (src), FALSE);
927 src->n_output_buffers = 0;
928 src->num_times_negotiate_called = 0;
929 src->do_renegotiate = FALSE;
930 }
931
932 /* This test src outputs a compressed format, with a single GOP
933 * starting at PTS 0.
934 *
935 * This means that in reverse playback, we may want to output
936 * buffers outside the segment bounds, and decide when to EOS
937 * from the create function.
938 */
939 static GstFlowReturn
time_src_create(GstBaseSrc * bsrc,guint64 offset,guint size,GstBuffer ** p_buf)940 time_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
941 GstBuffer ** p_buf)
942 {
943 TimeSrc *src = (TimeSrc *) bsrc;
944
945 if (src->segment->position >= src->segment->stop)
946 return GST_FLOW_EOS;
947
948 if (src->do_renegotiate) {
949 gst_base_src_negotiate (bsrc);
950 src->do_renegotiate = FALSE;
951 }
952
953 *p_buf = gst_buffer_new ();
954 GST_BUFFER_PTS (*p_buf) = src->segment->position;
955 GST_BUFFER_DURATION (*p_buf) = GST_SECOND;
956 src->segment->position += GST_SECOND;
957
958 src->n_output_buffers++;
959
960 return GST_FLOW_OK;
961 }
962
963 static gboolean
time_src_do_seek(GstBaseSrc * bsrc,GstSegment * segment)964 time_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
965 {
966 TimeSrc *src = (TimeSrc *) bsrc;
967 fail_unless (segment->format == GST_FORMAT_TIME);
968
969 if (src->segment)
970 gst_segment_free (src->segment);
971
972 src->segment = gst_segment_copy (segment);
973
974 ((TimeSrc *) bsrc)->segment->position = 0;
975
976 return TRUE;
977 }
978
979 static gboolean
time_src_is_seekable(GstBaseSrc * bsrc)980 time_src_is_seekable (GstBaseSrc * bsrc)
981 {
982 return TRUE;
983 }
984
985 static gboolean
time_src_negotiate(GstBaseSrc * bsrc)986 time_src_negotiate (GstBaseSrc * bsrc)
987 {
988 TimeSrc *src = (TimeSrc *) bsrc;
989 src->num_times_negotiate_called++;
990 return GST_BASE_SRC_CLASS (time_src_parent_class)->negotiate (bsrc);
991 }
992
993 static void
time_src_class_init(TimeSrcClass * klass)994 time_src_class_init (TimeSrcClass * klass)
995 {
996 GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
997
998 gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass),
999 &src_template);
1000
1001 gstbasesrc_class->create = time_src_create;
1002 gstbasesrc_class->do_seek = time_src_do_seek;
1003 gstbasesrc_class->is_seekable = time_src_is_seekable;
1004 gstbasesrc_class->negotiate = time_src_negotiate;
1005 }
1006
GST_START_TEST(basesrc_time_automatic_eos)1007 GST_START_TEST (basesrc_time_automatic_eos)
1008 {
1009 GstElement *src, *sink;
1010 GstElement *pipe;
1011 GstBus *bus;
1012
1013 src = g_object_new (time_src_get_type (), NULL);
1014 sink = gst_element_factory_make ("fakesink", NULL);
1015
1016 pipe = gst_pipeline_new (NULL);
1017
1018 gst_bin_add (GST_BIN (pipe), src);
1019 gst_bin_add (GST_BIN (pipe), sink);
1020
1021 gst_element_link (src, sink);
1022
1023 gst_element_set_state (pipe, GST_STATE_PAUSED);
1024 gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
1025
1026 gst_element_seek (pipe, -1.0, GST_FORMAT_TIME,
1027 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET,
1028 GST_SECOND, GST_SEEK_TYPE_SET, 2 * GST_SECOND);
1029
1030 gst_element_set_state (pipe, GST_STATE_PLAYING);
1031
1032 bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
1033
1034 gst_message_unref (gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
1035 GST_MESSAGE_EOS));
1036
1037 gst_element_set_state (pipe, GST_STATE_NULL);
1038
1039 /* - One preroll buffer
1040 * - One (1-second) buffer outside the segment, our "keyframe"
1041 * - One buffer inside the segment
1042 */
1043 fail_unless_equals_int (((TimeSrc *) src)->n_output_buffers, 3);
1044
1045 if (((TimeSrc *) src)->segment)
1046 gst_segment_free (((TimeSrc *) src)->segment);
1047
1048 gst_object_unref (bus);
1049 gst_object_unref (pipe);
1050 }
1051
1052 GST_END_TEST;
1053
GST_START_TEST(basesrc_negotiate)1054 GST_START_TEST (basesrc_negotiate)
1055 {
1056 GstElement *src, *sink;
1057 GstElement *pipe;
1058 GstSegment seg;
1059
1060 src = g_object_new (time_src_get_type (), NULL);
1061 sink = gst_element_factory_make ("fakesink", NULL);
1062
1063 pipe = gst_pipeline_new (NULL);
1064
1065 gst_bin_add (GST_BIN (pipe), src);
1066 gst_bin_add (GST_BIN (pipe), sink);
1067
1068 gst_element_link (src, sink);
1069
1070 /* Use some default segment to get the stream going. */
1071 gst_segment_init (&seg, GST_FORMAT_TIME);
1072 ((TimeSrc *) src)->segment = gst_segment_copy (&seg);
1073
1074 /* Check that gst_base_src_negotiate () actually ends up calling
1075 * the negotiate () vmethod by first running the test pipeline
1076 * normally, and then running it with a gst_base_src_negotiate ()
1077 * call, and checking how many times negotiate () was called in
1078 * both cases. */
1079
1080 /* Run pipeline, keep do_renegotiate at FALSE, so
1081 * gst_base_src_negotiate () won't be called. negotiate () still
1082 * will be called once, as part of the regular caps negotiation
1083 * sequence. */
1084 fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 0);
1085 gst_element_set_state (pipe, GST_STATE_PLAYING);
1086 gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
1087 fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 1);
1088 gst_element_set_state (pipe, GST_STATE_NULL);
1089
1090 ((TimeSrc *) src)->num_times_negotiate_called = 0;
1091
1092 /* Run pipeline, set do_renegotiate to TRUE. This will cause
1093 * negotiate () to be called twice: Once during caps negotiation,
1094 * and once by the gst_base_src_negotiate () call in the
1095 * time_src_create () function. */
1096 ((TimeSrc *) src)->do_renegotiate = TRUE;
1097 fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 0);
1098 gst_element_set_state (pipe, GST_STATE_PLAYING);
1099 gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
1100 fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 2);
1101 gst_element_set_state (pipe, GST_STATE_NULL);
1102
1103 if (((TimeSrc *) src)->segment)
1104 gst_segment_free (((TimeSrc *) src)->segment);
1105
1106 gst_object_unref (pipe);
1107 }
1108
1109 GST_END_TEST;
1110
1111 static Suite *
gst_basesrc_suite(void)1112 gst_basesrc_suite (void)
1113 {
1114 Suite *s = suite_create ("GstBaseSrc");
1115 TCase *tc = tcase_create ("general");
1116
1117 suite_add_tcase (s, tc);
1118 tcase_add_test (tc, basesrc_eos_events_pull);
1119 tcase_add_test (tc, basesrc_eos_events_push);
1120 tcase_add_test (tc, basesrc_eos_events_push_live_op);
1121 tcase_add_test (tc, basesrc_eos_events_pull_live_op);
1122 tcase_add_test (tc, basesrc_eos_events_push_live_eos);
1123 tcase_add_test (tc, basesrc_eos_events_pull_live_eos);
1124 tcase_add_test (tc, basesrc_seek_events_rate_update);
1125 tcase_add_test (tc, basesrc_seek_on_last_buffer);
1126 tcase_add_test (tc, basesrc_create_bufferlist);
1127 tcase_add_test (tc, basesrc_time_automatic_eos);
1128 tcase_add_test (tc, basesrc_negotiate);
1129
1130 return s;
1131 }
1132
1133 GST_CHECK_MAIN (gst_basesrc);
1134