1 /* GStreamer
2 *
3 * unit test for compositor
4 *
5 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6 * Copyright (C) <2013> Thibault Saunier <thibault.saunier@collabora.com>
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 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., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #ifdef HAVE_VALGRIND
29 # include <valgrind/valgrind.h>
30 #endif
31
32 #include <gst/check/gstcheck.h>
33 #include <gst/check/gstconsistencychecker.h>
34 #include <gst/video/gstvideometa.h>
35 #include <gst/base/gstbasesrc.h>
36
37 #define VIDEO_CAPS_STRING \
38 "video/x-raw, " \
39 "width = (int) 320, " \
40 "height = (int) 240, " \
41 "framerate = (fraction) 25/1 , " \
42 "format = (string) I420"
43
44 static GMainLoop *main_loop;
45
46 static GstCaps *
_compositor_get_all_supported_caps(void)47 _compositor_get_all_supported_caps (void)
48 {
49 return gst_caps_from_string (GST_VIDEO_CAPS_MAKE
50 (" { AYUV, BGRA, ARGB, RGBA, ABGR, Y444, Y42B, YUY2, UYVY, "
51 " YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, "
52 " RGBx, BGRx } "));
53 }
54
55 static GstCaps *
_compositor_get_non_alpha_supported_caps(void)56 _compositor_get_non_alpha_supported_caps (void)
57 {
58 return gst_caps_from_string (GST_VIDEO_CAPS_MAKE
59 (" { Y444, Y42B, YUY2, UYVY, "
60 " YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, "
61 " RGBx, BGRx } "));
62 }
63
64 /* make sure downstream gets a CAPS event before buffers are sent */
GST_START_TEST(test_caps)65 GST_START_TEST (test_caps)
66 {
67 GstElement *pipeline, *src, *compositor, *sink;
68 GstStateChangeReturn state_res;
69 GstCaps *caps;
70 GstPad *pad;
71
72 /* build pipeline */
73 pipeline = gst_pipeline_new ("pipeline");
74
75 src = gst_element_factory_make ("videotestsrc", "src1");
76 compositor = gst_element_factory_make ("compositor", "compositor");
77 sink = gst_element_factory_make ("fakesink", "sink");
78 gst_bin_add_many (GST_BIN (pipeline), src, compositor, sink, NULL);
79
80 fail_unless (gst_element_link_many (src, compositor, sink, NULL));
81
82 /* prepare playing */
83 state_res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
84 fail_unless_equals_int (state_res, GST_STATE_CHANGE_ASYNC);
85
86 /* wait for preroll */
87 state_res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
88 fail_unless_equals_int (state_res, GST_STATE_CHANGE_SUCCESS);
89
90 /* check caps on fakesink */
91 pad = gst_element_get_static_pad (sink, "sink");
92 caps = gst_pad_get_current_caps (pad);
93 fail_unless (caps != NULL);
94 gst_caps_unref (caps);
95 gst_object_unref (pad);
96
97 gst_element_set_state (pipeline, GST_STATE_NULL);
98 gst_object_unref (pipeline);
99 }
100
101 GST_END_TEST;
102
103 static void
message_received(GstBus * bus,GstMessage * message,GstPipeline * bin)104 message_received (GstBus * bus, GstMessage * message, GstPipeline * bin)
105 {
106 GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
107 GST_MESSAGE_SRC (message), message);
108
109 switch (message->type) {
110 case GST_MESSAGE_EOS:
111 g_main_loop_quit (main_loop);
112 break;
113 case GST_MESSAGE_WARNING:{
114 GError *gerror;
115 gchar *debug;
116
117 gst_message_parse_warning (message, &gerror, &debug);
118 gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
119 g_error_free (gerror);
120 g_free (debug);
121 break;
122 }
123 case GST_MESSAGE_ERROR:{
124 GError *gerror;
125 gchar *debug;
126
127 gst_message_parse_error (message, &gerror, &debug);
128 gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
129 g_error_free (gerror);
130 g_free (debug);
131 g_main_loop_quit (main_loop);
132 break;
133 }
134 default:
135 break;
136 }
137 }
138
139
140 static GstFormat format = GST_FORMAT_UNDEFINED;
141 static gint64 position = -1;
142
143 static void
test_event_message_received(GstBus * bus,GstMessage * message,GstPipeline * bin)144 test_event_message_received (GstBus * bus, GstMessage * message,
145 GstPipeline * bin)
146 {
147 GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
148 GST_MESSAGE_SRC (message), message);
149
150 switch (message->type) {
151 case GST_MESSAGE_SEGMENT_DONE:
152 gst_message_parse_segment_done (message, &format, &position);
153 GST_INFO ("received segment_done : %" G_GINT64_FORMAT, position);
154 g_main_loop_quit (main_loop);
155 break;
156 default:
157 g_assert_not_reached ();
158 break;
159 }
160 }
161
162
GST_START_TEST(test_event)163 GST_START_TEST (test_event)
164 {
165 GstElement *bin, *src1, *src2, *compositor, *sink;
166 GstBus *bus;
167 GstEvent *seek_event;
168 GstStateChangeReturn state_res;
169 gboolean res;
170 GstPad *srcpad, *sinkpad;
171 GstStreamConsistency *chk_1, *chk_2, *chk_3;
172
173 GST_INFO ("preparing test");
174
175 /* build pipeline */
176 bin = gst_pipeline_new ("pipeline");
177 bus = gst_element_get_bus (bin);
178 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
179
180 src1 = gst_element_factory_make ("videotestsrc", "src1");
181 src2 = gst_element_factory_make ("videotestsrc", "src2");
182 compositor = gst_element_factory_make ("compositor", "compositor");
183 sink = gst_element_factory_make ("fakesink", "sink");
184 gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
185
186 res = gst_element_link (src1, compositor);
187 fail_unless (res == TRUE, NULL);
188 res = gst_element_link (src2, compositor);
189 fail_unless (res == TRUE, NULL);
190 res = gst_element_link (compositor, sink);
191 fail_unless (res == TRUE, NULL);
192
193 srcpad = gst_element_get_static_pad (compositor, "src");
194 chk_3 = gst_consistency_checker_new (srcpad);
195 gst_object_unref (srcpad);
196
197 /* create consistency checkers for the pads */
198 srcpad = gst_element_get_static_pad (src1, "src");
199 chk_1 = gst_consistency_checker_new (srcpad);
200 sinkpad = gst_pad_get_peer (srcpad);
201 gst_consistency_checker_add_pad (chk_3, sinkpad);
202 gst_object_unref (sinkpad);
203 gst_object_unref (srcpad);
204
205 srcpad = gst_element_get_static_pad (src2, "src");
206 chk_2 = gst_consistency_checker_new (srcpad);
207 sinkpad = gst_pad_get_peer (srcpad);
208 gst_consistency_checker_add_pad (chk_3, sinkpad);
209 gst_object_unref (sinkpad);
210 gst_object_unref (srcpad);
211
212 seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
213 GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
214 GST_SEEK_TYPE_SET, (GstClockTime) 0,
215 GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
216
217 format = GST_FORMAT_UNDEFINED;
218 position = -1;
219
220 main_loop = g_main_loop_new (NULL, FALSE);
221 g_signal_connect (bus, "message::segment-done",
222 (GCallback) test_event_message_received, bin);
223 g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
224 g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
225 g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
226
227 GST_INFO ("starting test");
228
229 /* prepare playing */
230 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
231 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
232
233 /* wait for completion */
234 state_res = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
235 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
236
237 res = gst_element_send_event (bin, seek_event);
238 fail_unless (res == TRUE, NULL);
239
240 /* run pipeline */
241 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
242 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
243
244 GST_INFO ("running main loop");
245 g_main_loop_run (main_loop);
246
247 state_res = gst_element_set_state (bin, GST_STATE_NULL);
248 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
249
250 ck_assert_int_eq (position, 2 * GST_SECOND);
251
252 /* cleanup */
253 g_main_loop_unref (main_loop);
254 gst_consistency_checker_free (chk_1);
255 gst_consistency_checker_free (chk_2);
256 gst_consistency_checker_free (chk_3);
257 gst_bus_remove_signal_watch (bus);
258 gst_object_unref (bus);
259 gst_object_unref (bin);
260 }
261
262 GST_END_TEST;
263
264 static GstBuffer *
create_video_buffer(GstCaps * caps,gint ts_in_seconds)265 create_video_buffer (GstCaps * caps, gint ts_in_seconds)
266 {
267 GstVideoInfo info;
268 guint size;
269 GstBuffer *buf;
270 GstMapInfo mapinfo;
271
272 fail_unless (gst_video_info_from_caps (&info, caps));
273
274 size = GST_VIDEO_INFO_WIDTH (&info) * GST_VIDEO_INFO_HEIGHT (&info);
275
276 switch (GST_VIDEO_INFO_FORMAT (&info)) {
277 case GST_VIDEO_FORMAT_RGB:
278 size *= 3;
279 break;
280 case GST_VIDEO_FORMAT_RGBA:
281 case GST_VIDEO_FORMAT_ARGB:
282 size *= 4;
283 break;
284 case GST_VIDEO_FORMAT_I420:
285 size *= 2;
286 break;
287 default:
288 fail ("Unsupported test format");
289 }
290
291 buf = gst_buffer_new_and_alloc (size);
292 /* write something to avoid uninitialized error issues (valgrind) */
293 gst_buffer_map (buf, &mapinfo, GST_MAP_WRITE);
294 memset (mapinfo.data, 0, mapinfo.size);
295 gst_buffer_unmap (buf, &mapinfo);
296
297 GST_BUFFER_PTS (buf) = ts_in_seconds * GST_SECOND;
298 GST_BUFFER_DURATION (buf) = GST_SECOND;
299 return buf;
300 }
301
302
GST_START_TEST(test_caps_query)303 GST_START_TEST (test_caps_query)
304 {
305 GstElement *compositor, *capsfilter, *sink;
306 GstElement *pipeline;
307 gboolean res;
308 GstStateChangeReturn state_res;
309 GstPad *sinkpad;
310 GstCaps *caps, *restriction_caps;
311 GstCaps *all_caps, *non_alpha_caps;
312
313 /* initial setup */
314 all_caps = _compositor_get_all_supported_caps ();
315 non_alpha_caps = _compositor_get_non_alpha_supported_caps ();
316
317 compositor = gst_element_factory_make ("compositor", "compositor");
318 capsfilter = gst_element_factory_make ("capsfilter", "out-cf");
319 sink = gst_element_factory_make ("fakesink", "sink");
320 pipeline = gst_pipeline_new ("test-pipeline");
321
322 gst_bin_add_many (GST_BIN (pipeline), compositor, capsfilter, sink, NULL);
323 res = gst_element_link (compositor, capsfilter);
324 fail_unless (res == TRUE, NULL);
325 res = gst_element_link (capsfilter, sink);
326 fail_unless (res == TRUE, NULL);
327
328 sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
329
330 state_res = gst_element_set_state (pipeline, GST_STATE_PLAYING);
331 fail_if (state_res == GST_STATE_CHANGE_FAILURE);
332
333 /* try an unrestricted caps query, should return all formats */
334 caps = gst_pad_query_caps (sinkpad, NULL);
335 fail_unless (gst_caps_is_equal (caps, all_caps));
336 gst_caps_unref (caps);
337
338 /* now restrict downstream to a single alpha format, it should still
339 * be able to convert anything else to it */
340 restriction_caps = gst_caps_from_string ("video/x-raw, format=(string)AYUV");
341 g_object_set (capsfilter, "caps", restriction_caps, NULL);
342 caps = gst_pad_query_caps (sinkpad, NULL);
343 fail_unless (gst_caps_is_equal (caps, all_caps));
344 gst_caps_unref (caps);
345 gst_caps_unref (restriction_caps);
346
347 /* now restrict downstream to a non-alpha format, it should
348 * be able to accept non-alpha formats */
349 restriction_caps = gst_caps_from_string ("video/x-raw, format=(string)I420");
350 g_object_set (capsfilter, "caps", restriction_caps, NULL);
351 caps = gst_pad_query_caps (sinkpad, NULL);
352 fail_unless (gst_caps_is_equal (caps, non_alpha_caps));
353 gst_caps_unref (caps);
354 gst_caps_unref (restriction_caps);
355
356 /* check that compositor proxies downstream interlace-mode */
357 restriction_caps =
358 gst_caps_from_string ("video/x-raw, interlace-mode=(string)interleaved");
359 g_object_set (capsfilter, "caps", restriction_caps, NULL);
360 caps = gst_pad_query_caps (sinkpad, NULL);
361 fail_unless (gst_caps_is_subset (caps, restriction_caps));
362 gst_caps_unref (caps);
363 gst_caps_unref (restriction_caps);
364
365 gst_element_set_state (pipeline, GST_STATE_NULL);
366 gst_element_release_request_pad (compositor, sinkpad);
367 gst_object_unref (sinkpad);
368 gst_object_unref (pipeline);
369 gst_caps_unref (all_caps);
370 gst_caps_unref (non_alpha_caps);
371 }
372
373 GST_END_TEST;
374
375
GST_START_TEST(test_caps_query_interlaced)376 GST_START_TEST (test_caps_query_interlaced)
377 {
378 GstElement *compositor, *sink;
379 GstElement *pipeline;
380 gboolean res;
381 GstStateChangeReturn state_res;
382 GstPad *sinkpad;
383 GstCaps *caps;
384 GstCaps *caps_mixed, *caps_progressive, *caps_interleaved;
385 GstEvent *caps_event;
386 GstQuery *drain;
387
388 caps_interleaved =
389 gst_caps_from_string ("video/x-raw, interlace-mode=interleaved");
390 caps_mixed = gst_caps_from_string ("video/x-raw, interlace-mode=mixed");
391 caps_progressive =
392 gst_caps_from_string ("video/x-raw, interlace-mode=progressive");
393
394 /* initial setup */
395 compositor = gst_element_factory_make ("compositor", "compositor");
396 sink = gst_element_factory_make ("fakesink", "sink");
397 pipeline = gst_pipeline_new ("test-pipeline");
398
399 gst_bin_add_many (GST_BIN (pipeline), compositor, sink, NULL);
400 res = gst_element_link (compositor, sink);
401 fail_unless (res == TRUE, NULL);
402 sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
403
404 state_res = gst_element_set_state (pipeline, GST_STATE_PLAYING);
405 fail_if (state_res == GST_STATE_CHANGE_FAILURE);
406
407 /* try an unrestricted caps query, should be compatible with all formats */
408 caps = gst_pad_query_caps (sinkpad, NULL);
409 fail_unless (gst_caps_can_intersect (caps, caps_interleaved));
410 fail_unless (gst_caps_can_intersect (caps, caps_progressive));
411 fail_unless (gst_caps_can_intersect (caps, caps_mixed));
412 gst_caps_unref (caps);
413
414 /* now set caps on the pad, it should restrict the interlace-mode for
415 * future caps */
416 caps = gst_caps_from_string ("video/x-raw, width=100, height=100, "
417 "format=RGB, framerate=1/1, interlace-mode=progressive");
418 caps_event = gst_event_new_caps (caps);
419 gst_caps_unref (caps);
420 fail_unless (gst_pad_send_event (sinkpad, caps_event));
421
422 /* Send drain query to make sure this is processed */
423 drain = gst_query_new_drain ();
424 gst_pad_query (sinkpad, drain);
425 gst_query_unref (drain);
426
427 /* now recheck the interlace-mode */
428 gst_object_unref (sinkpad);
429 sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
430 caps = gst_pad_query_caps (sinkpad, NULL);
431 fail_if (gst_caps_can_intersect (caps, caps_interleaved));
432 fail_unless (gst_caps_can_intersect (caps, caps_progressive));
433 fail_if (gst_caps_can_intersect (caps, caps_mixed));
434 gst_object_unref (sinkpad);
435 gst_caps_unref (caps);
436
437 gst_element_set_state (pipeline, GST_STATE_NULL);
438 gst_object_unref (pipeline);
439 gst_caps_unref (caps_interleaved);
440 gst_caps_unref (caps_mixed);
441 gst_caps_unref (caps_progressive);
442 }
443
444 GST_END_TEST;
445
446 static void
add_interlaced_mode_to_caps(GstCaps * caps,const gchar * mode)447 add_interlaced_mode_to_caps (GstCaps * caps, const gchar * mode)
448 {
449 GstStructure *s;
450 gint i;
451
452 for (i = 0; i < gst_caps_get_size (caps); i++) {
453 s = gst_caps_get_structure (caps, i);
454 gst_structure_set (s, "interlace-mode", G_TYPE_STRING, mode, NULL);
455 }
456 }
457
458 #define MODE_ALL 1
459 #define MODE_NON_ALPHA 2
460
461 static void
run_late_caps_query_test(GstCaps * input_caps,GstCaps * output_allowed_caps,gint expected_caps_mode)462 run_late_caps_query_test (GstCaps * input_caps, GstCaps * output_allowed_caps,
463 gint expected_caps_mode)
464 {
465 GstElement *compositor, *capsfilter, *sink;
466 GstElement *pipeline;
467 gboolean res;
468 GstStateChangeReturn state_res;
469 GstPad *srcpad1, *srcpad2;
470 GstPad *sinkpad1, *sinkpad2;
471 GstSegment segment;
472 GstCaps *caps, *all_caps, *non_alpha_caps;
473
474 all_caps = _compositor_get_all_supported_caps ();
475 non_alpha_caps = _compositor_get_non_alpha_supported_caps ();
476
477 /* add progressive mode as it is what is used in the test, otherwise
478 * is_equal checks would fail */
479 add_interlaced_mode_to_caps (all_caps, "progressive");
480 add_interlaced_mode_to_caps (non_alpha_caps, "progressive");
481
482 compositor = gst_element_factory_make ("compositor", "compositor");
483 capsfilter = gst_element_factory_make ("capsfilter", "out-cf");
484 sink = gst_element_factory_make ("fakesink", "sink");
485 pipeline = gst_pipeline_new ("test-pipeline");
486
487 gst_bin_add_many (GST_BIN (pipeline), compositor, capsfilter, sink, NULL);
488 res = gst_element_link (compositor, capsfilter);
489 fail_unless (res == TRUE, NULL);
490 res = gst_element_link (capsfilter, sink);
491 fail_unless (res == TRUE, NULL);
492
493 sinkpad1 = gst_element_get_request_pad (compositor, "sink_%u");
494 srcpad1 = gst_pad_new ("src1", GST_PAD_SRC);
495 fail_unless (gst_pad_link (srcpad1, sinkpad1) == GST_PAD_LINK_OK);
496 gst_pad_set_active (srcpad1, TRUE);
497
498 state_res = gst_element_set_state (pipeline, GST_STATE_PLAYING);
499 fail_if (state_res == GST_STATE_CHANGE_FAILURE);
500
501 if (output_allowed_caps)
502 g_object_set (capsfilter, "caps", output_allowed_caps, NULL);
503
504 gst_segment_init (&segment, GST_FORMAT_TIME);
505 fail_unless (gst_pad_push_event (srcpad1,
506 gst_event_new_stream_start ("test-1")));
507 fail_unless (gst_pad_push_event (srcpad1, gst_event_new_caps (input_caps)));
508 fail_unless (gst_pad_push_event (srcpad1, gst_event_new_segment (&segment)));
509 fail_unless (gst_pad_push (srcpad1,
510 create_video_buffer (input_caps, 0)) == GST_FLOW_OK);
511 fail_unless (gst_pad_push (srcpad1,
512 create_video_buffer (input_caps, 1)) == GST_FLOW_OK);
513
514 /* now comes the second pad */
515 sinkpad2 = gst_element_get_request_pad (compositor, "sink_%u");
516 srcpad2 = gst_pad_new ("src2", GST_PAD_SRC);
517 fail_unless (gst_pad_link (srcpad2, sinkpad2) == GST_PAD_LINK_OK);
518 gst_pad_set_active (srcpad2, TRUE);
519 fail_unless (gst_pad_push_event (srcpad2,
520 gst_event_new_stream_start ("test-2")));
521
522 caps = gst_pad_peer_query_caps (srcpad2, NULL);
523 fail_unless (gst_caps_is_equal (caps,
524 expected_caps_mode == MODE_ALL ? all_caps : non_alpha_caps));
525 gst_caps_unref (caps);
526
527 gst_pad_set_active (srcpad1, FALSE);
528 gst_pad_set_active (srcpad2, FALSE);
529 gst_element_set_state (pipeline, GST_STATE_NULL);
530 gst_element_release_request_pad (compositor, sinkpad1);
531 gst_element_release_request_pad (compositor, sinkpad2);
532 gst_object_unref (sinkpad1);
533 gst_object_unref (sinkpad2);
534 gst_object_unref (pipeline);
535 gst_object_unref (srcpad1);
536 gst_object_unref (srcpad2);
537 gst_caps_unref (all_caps);
538 gst_caps_unref (non_alpha_caps);
539 }
540
GST_START_TEST(test_late_caps_query)541 GST_START_TEST (test_late_caps_query)
542 {
543 GstCaps *rgb_caps;
544 GstCaps *non_alpha_caps;
545
546 rgb_caps = gst_caps_from_string ("video/x-raw, format=(string)RGB, "
547 "width=(int)100, height=(int)100, framerate=(fraction)1/1");
548 non_alpha_caps = gst_caps_from_string ("video/x-raw, format=(string)RGB");
549
550 /* check that a 2nd pad that is added late to compositor will be able to
551 * negotiate to formats that depend only on downstream caps and not on what
552 * the other pads have already negotiated */
553 run_late_caps_query_test (rgb_caps, NULL, MODE_ALL);
554 run_late_caps_query_test (rgb_caps, non_alpha_caps, MODE_NON_ALPHA);
555
556 gst_caps_unref (non_alpha_caps);
557 gst_caps_unref (rgb_caps);
558 }
559
560 GST_END_TEST;
561
562 static void
run_late_caps_set_test(GstCaps * first_caps,GstCaps * expected_query_caps,GstCaps * second_caps,gboolean accept_caps)563 run_late_caps_set_test (GstCaps * first_caps, GstCaps * expected_query_caps,
564 GstCaps * second_caps, gboolean accept_caps)
565 {
566 GstElement *capsfilter_1;
567 GstElement *compositor;
568 GstElement *pipeline;
569 GstStateChangeReturn state_res;
570 GstPad *sinkpad_2;
571 GstCaps *caps;
572 GstBus *bus;
573 GstMessage *msg;
574
575 pipeline =
576 gst_parse_launch ("videotestsrc num-buffers=10 ! capsfilter name=cf1 !"
577 " compositor name=c ! fakesink sync=true", NULL);
578 fail_unless (pipeline != NULL);
579
580 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
581
582 compositor = gst_bin_get_by_name (GST_BIN (pipeline), "c");
583 capsfilter_1 = gst_bin_get_by_name (GST_BIN (pipeline), "cf1");
584
585 g_object_set (capsfilter_1, "caps", first_caps, NULL);
586
587 state_res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
588 fail_if (state_res == GST_STATE_CHANGE_FAILURE);
589
590 /* wait for pipeline to get to paused */
591 msg =
592 gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
593 GST_MESSAGE_ASYNC_DONE);
594 fail_unless (msg != NULL);
595 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE);
596 gst_message_unref (msg);
597
598 /* try to set the second caps */
599 sinkpad_2 = gst_element_get_request_pad (compositor, "sink_%u");
600 caps = gst_pad_query_caps (sinkpad_2, NULL);
601 fail_unless (gst_caps_is_subset (expected_query_caps, caps));
602 gst_caps_unref (caps);
603 caps = gst_pad_query_caps (sinkpad_2, second_caps);
604 fail_unless (gst_caps_is_empty (caps) != accept_caps);
605 gst_caps_unref (caps);
606 gst_object_unref (sinkpad_2);
607
608 gst_object_unref (bus);
609 gst_object_unref (compositor);
610 gst_object_unref (capsfilter_1);
611 gst_element_set_state (pipeline, GST_STATE_NULL);
612 gst_object_unref (pipeline);
613 }
614
GST_START_TEST(test_late_caps_different_interlaced)615 GST_START_TEST (test_late_caps_different_interlaced)
616 {
617 GstCaps *non_interlaced_caps;
618 GstCaps *interlaced_caps;
619
620 non_interlaced_caps =
621 gst_caps_from_string ("video/x-raw, interlace-mode=progressive, "
622 "format=RGB, width=100, height=100, framerate=1/1");
623 interlaced_caps =
624 gst_caps_from_string ("video/x-raw, interlace-mode=interleaved, "
625 "format=RGB, width=100, height=100, framerate=1/1");
626
627 run_late_caps_set_test (non_interlaced_caps, non_interlaced_caps,
628 interlaced_caps, FALSE);
629
630 gst_caps_unref (non_interlaced_caps);
631 gst_caps_unref (interlaced_caps);
632 }
633
634 GST_END_TEST;
635
636 static guint play_count = 0;
637 static GstEvent *play_seek_event = NULL;
638
639 static void
test_play_twice_message_received(GstBus * bus,GstMessage * message,GstPipeline * bin)640 test_play_twice_message_received (GstBus * bus, GstMessage * message,
641 GstPipeline * bin)
642 {
643 gboolean res;
644 GstStateChangeReturn state_res;
645
646 GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
647 GST_MESSAGE_SRC (message), message);
648
649 switch (message->type) {
650 case GST_MESSAGE_SEGMENT_DONE:
651 play_count++;
652 if (play_count == 1) {
653 state_res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
654 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
655
656 /* prepare playing again */
657 state_res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
658 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
659
660 /* wait for completion */
661 state_res =
662 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
663 GST_CLOCK_TIME_NONE);
664 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
665
666 res = gst_element_send_event (GST_ELEMENT (bin),
667 gst_event_ref (play_seek_event));
668 fail_unless (res == TRUE, NULL);
669
670 state_res =
671 gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
672 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
673 } else {
674 g_main_loop_quit (main_loop);
675 }
676 break;
677 default:
678 g_assert_not_reached ();
679 break;
680 }
681 }
682
683
GST_START_TEST(test_play_twice)684 GST_START_TEST (test_play_twice)
685 {
686 GstElement *bin, *src1, *src2, *compositor, *sink;
687 GstBus *bus;
688 gboolean res;
689 GstStateChangeReturn state_res;
690 GstPad *srcpad;
691 GstStreamConsistency *consist;
692
693 GST_INFO ("preparing test");
694
695 /* build pipeline */
696 bin = gst_pipeline_new ("pipeline");
697 bus = gst_element_get_bus (bin);
698 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
699
700 src1 = gst_element_factory_make ("videotestsrc", "src1");
701 src2 = gst_element_factory_make ("videotestsrc", "src2");
702 compositor = gst_element_factory_make ("compositor", "compositor");
703 sink = gst_element_factory_make ("fakesink", "sink");
704 gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
705
706 res = gst_element_link (src1, compositor);
707 fail_unless (res == TRUE, NULL);
708 res = gst_element_link (src2, compositor);
709 fail_unless (res == TRUE, NULL);
710 res = gst_element_link (compositor, sink);
711 fail_unless (res == TRUE, NULL);
712
713 srcpad = gst_element_get_static_pad (compositor, "src");
714 consist = gst_consistency_checker_new (srcpad);
715 gst_object_unref (srcpad);
716
717 play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
718 GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
719 GST_SEEK_TYPE_SET, (GstClockTime) 0,
720 GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
721
722 play_count = 0;
723
724 main_loop = g_main_loop_new (NULL, FALSE);
725 g_signal_connect (bus, "message::segment-done",
726 (GCallback) test_play_twice_message_received, bin);
727 g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
728 g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
729 g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
730
731 GST_INFO ("starting test");
732
733 /* prepare playing */
734 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
735 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
736
737 /* wait for completion */
738 state_res =
739 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
740 GST_CLOCK_TIME_NONE);
741 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
742
743 res = gst_element_send_event (bin, gst_event_ref (play_seek_event));
744 fail_unless (res == TRUE, NULL);
745
746 GST_INFO ("seeked");
747
748 /* run pipeline */
749 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
750 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
751
752 g_main_loop_run (main_loop);
753
754 state_res = gst_element_set_state (bin, GST_STATE_NULL);
755 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
756
757 ck_assert_int_eq (play_count, 2);
758
759 /* cleanup */
760 g_main_loop_unref (main_loop);
761 gst_consistency_checker_free (consist);
762 gst_event_unref (play_seek_event);
763 gst_bus_remove_signal_watch (bus);
764 gst_object_unref (bus);
765 gst_object_unref (bin);
766 }
767
768 GST_END_TEST;
769
GST_START_TEST(test_play_twice_then_add_and_play_again)770 GST_START_TEST (test_play_twice_then_add_and_play_again)
771 {
772 GstElement *bin, *src1, *src2, *src3, *compositor, *sink;
773 GstBus *bus;
774 gboolean res;
775 GstStateChangeReturn state_res;
776 gint i;
777 GstPad *srcpad;
778 GstStreamConsistency *consist;
779
780 GST_INFO ("preparing test");
781
782 /* build pipeline */
783 bin = gst_pipeline_new ("pipeline");
784 bus = gst_element_get_bus (bin);
785 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
786
787 src1 = gst_element_factory_make ("videotestsrc", "src1");
788 src2 = gst_element_factory_make ("videotestsrc", "src2");
789 compositor = gst_element_factory_make ("compositor", "compositor");
790 sink = gst_element_factory_make ("fakesink", "sink");
791 gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
792
793 srcpad = gst_element_get_static_pad (compositor, "src");
794 consist = gst_consistency_checker_new (srcpad);
795 gst_object_unref (srcpad);
796
797 res = gst_element_link (src1, compositor);
798 fail_unless (res == TRUE, NULL);
799 res = gst_element_link (src2, compositor);
800 fail_unless (res == TRUE, NULL);
801 res = gst_element_link (compositor, sink);
802 fail_unless (res == TRUE, NULL);
803
804 play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
805 GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
806 GST_SEEK_TYPE_SET, (GstClockTime) 0,
807 GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
808
809 main_loop = g_main_loop_new (NULL, FALSE);
810 g_signal_connect (bus, "message::segment-done",
811 (GCallback) test_play_twice_message_received, bin);
812 g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
813 g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
814 g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
815
816 /* run it twice */
817 for (i = 0; i < 2; i++) {
818 play_count = 0;
819
820 GST_INFO ("starting test-loop %d", i);
821
822 /* prepare playing */
823 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
824 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
825
826 /* wait for completion */
827 state_res =
828 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
829 GST_CLOCK_TIME_NONE);
830 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
831
832 res = gst_element_send_event (bin, gst_event_ref (play_seek_event));
833 fail_unless (res == TRUE, NULL);
834
835 GST_INFO ("seeked");
836
837 /* run pipeline */
838 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
839 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
840
841 g_main_loop_run (main_loop);
842
843 state_res = gst_element_set_state (bin, GST_STATE_READY);
844 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
845
846 ck_assert_int_eq (play_count, 2);
847
848 /* plug another source */
849 if (i == 0) {
850 src3 = gst_element_factory_make ("videotestsrc", "src3");
851 gst_bin_add (GST_BIN (bin), src3);
852
853 res = gst_element_link (src3, compositor);
854 fail_unless (res == TRUE, NULL);
855 }
856
857 gst_consistency_checker_reset (consist);
858 }
859
860 state_res = gst_element_set_state (bin, GST_STATE_NULL);
861 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
862
863 /* cleanup */
864 g_main_loop_unref (main_loop);
865 gst_event_unref (play_seek_event);
866 gst_consistency_checker_free (consist);
867 gst_bus_remove_signal_watch (bus);
868 gst_object_unref (bus);
869 gst_object_unref (bin);
870 }
871
872 GST_END_TEST;
873
874 /* check if adding pads work as expected */
GST_START_TEST(test_add_pad)875 GST_START_TEST (test_add_pad)
876 {
877 GstElement *bin, *src1, *src2, *compositor, *sink;
878 GstBus *bus;
879 GstPad *srcpad;
880 gboolean res;
881 GstStateChangeReturn state_res;
882
883 GST_INFO ("preparing test");
884
885 /* build pipeline */
886 bin = gst_pipeline_new ("pipeline");
887 bus = gst_element_get_bus (bin);
888 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
889
890 src1 = gst_element_factory_make ("videotestsrc", "src1");
891 g_object_set (src1, "num-buffers", 4, NULL);
892 src2 = gst_element_factory_make ("videotestsrc", "src2");
893 /* one buffer less, we connect with 1 buffer of delay */
894 g_object_set (src2, "num-buffers", 3, NULL);
895 compositor = gst_element_factory_make ("compositor", "compositor");
896 sink = gst_element_factory_make ("fakesink", "sink");
897 gst_bin_add_many (GST_BIN (bin), src1, compositor, sink, NULL);
898
899 res = gst_element_link (src1, compositor);
900 fail_unless (res == TRUE, NULL);
901 res = gst_element_link (compositor, sink);
902 fail_unless (res == TRUE, NULL);
903
904 srcpad = gst_element_get_static_pad (compositor, "src");
905 gst_object_unref (srcpad);
906
907 main_loop = g_main_loop_new (NULL, FALSE);
908 g_signal_connect (bus, "message::segment-done", (GCallback) message_received,
909 bin);
910 g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
911 g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
912 g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
913
914 GST_INFO ("starting test");
915
916 /* prepare playing */
917 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
918 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
919
920 /* wait for completion */
921 state_res =
922 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
923 GST_CLOCK_TIME_NONE);
924 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
925
926 /* add other element */
927 gst_bin_add_many (GST_BIN (bin), src2, NULL);
928
929 /* now link the second element */
930 res = gst_element_link (src2, compositor);
931 fail_unless (res == TRUE, NULL);
932
933 /* set to PAUSED as well */
934 state_res = gst_element_set_state (src2, GST_STATE_PAUSED);
935 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
936
937 /* now play all */
938 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
939 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
940
941 g_main_loop_run (main_loop);
942
943 state_res = gst_element_set_state (bin, GST_STATE_NULL);
944 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
945
946 /* cleanup */
947 g_main_loop_unref (main_loop);
948 gst_bus_remove_signal_watch (bus);
949 gst_object_unref (bus);
950 gst_object_unref (bin);
951 }
952
953 GST_END_TEST;
954
955 /* check if removing pads work as expected */
GST_START_TEST(test_remove_pad)956 GST_START_TEST (test_remove_pad)
957 {
958 GstElement *bin, *src, *compositor, *sink;
959 GstBus *bus;
960 GstPad *pad, *srcpad;
961 gboolean res;
962 GstStateChangeReturn state_res;
963
964 GST_INFO ("preparing test");
965
966 /* build pipeline */
967 bin = gst_pipeline_new ("pipeline");
968 bus = gst_element_get_bus (bin);
969 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
970
971 src = gst_element_factory_make ("videotestsrc", "src");
972 g_object_set (src, "num-buffers", 4, NULL);
973 compositor = gst_element_factory_make ("compositor", "compositor");
974 sink = gst_element_factory_make ("fakesink", "sink");
975 gst_bin_add_many (GST_BIN (bin), src, compositor, sink, NULL);
976
977 res = gst_element_link (src, compositor);
978 fail_unless (res == TRUE, NULL);
979 res = gst_element_link (compositor, sink);
980 fail_unless (res == TRUE, NULL);
981
982 /* create an unconnected sinkpad in compositor */
983 pad = gst_element_get_request_pad (compositor, "sink_%u");
984 fail_if (pad == NULL, NULL);
985
986 srcpad = gst_element_get_static_pad (compositor, "src");
987 gst_object_unref (srcpad);
988
989 main_loop = g_main_loop_new (NULL, FALSE);
990 g_signal_connect (bus, "message::segment-done", (GCallback) message_received,
991 bin);
992 g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
993 g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
994 g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
995
996 GST_INFO ("starting test");
997
998 /* prepare playing, this will not preroll as compositor is waiting
999 * on the unconnected sinkpad. */
1000 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
1001 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1002
1003 /* wait for completion for one second, will return ASYNC */
1004 state_res = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_SECOND);
1005 ck_assert_int_eq (state_res, GST_STATE_CHANGE_ASYNC);
1006
1007 /* get rid of the pad now, compositor should stop waiting on it and
1008 * continue the preroll */
1009 gst_element_release_request_pad (compositor, pad);
1010 gst_object_unref (pad);
1011
1012 /* wait for completion, should work now */
1013 state_res =
1014 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
1015 GST_CLOCK_TIME_NONE);
1016 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1017
1018 /* now play all */
1019 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1020 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1021
1022 g_main_loop_run (main_loop);
1023
1024 state_res = gst_element_set_state (bin, GST_STATE_NULL);
1025 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1026
1027 /* cleanup */
1028 g_main_loop_unref (main_loop);
1029 gst_bus_remove_signal_watch (bus);
1030 gst_object_unref (G_OBJECT (bus));
1031 gst_object_unref (G_OBJECT (bin));
1032 }
1033
1034 GST_END_TEST;
1035
1036
1037 static GstBuffer *handoff_buffer = NULL;
1038
1039 static gboolean
_quit(GMainLoop * ml)1040 _quit (GMainLoop * ml)
1041 {
1042 g_main_loop_quit (ml);
1043
1044 return G_SOURCE_REMOVE;
1045 }
1046
1047 static void
handoff_buffer_cb(GstElement * fakesink,GstBuffer * buffer,GstPad * pad,gpointer user_data)1048 handoff_buffer_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
1049 gpointer user_data)
1050 {
1051 GST_DEBUG ("got buffer %p", buffer);
1052 gst_buffer_replace (&handoff_buffer, buffer);
1053
1054 if (main_loop)
1055 g_idle_add ((GSourceFunc) _quit, main_loop);
1056 }
1057
1058 /* check if clipping works as expected */
GST_START_TEST(test_clip)1059 GST_START_TEST (test_clip)
1060 {
1061 GstSegment segment;
1062 GstElement *bin, *compositor, *sink;
1063 GstBus *bus;
1064 GstPad *sinkpad;
1065 gboolean res;
1066 GstStateChangeReturn state_res;
1067 GstFlowReturn ret;
1068 GstEvent *event;
1069 GstBuffer *buffer;
1070 GstCaps *caps;
1071 GMainLoop *local_mainloop;
1072
1073 GST_INFO ("preparing test");
1074
1075 local_mainloop = g_main_loop_new (NULL, FALSE);
1076 main_loop = NULL;
1077
1078 /* build pipeline */
1079 bin = gst_pipeline_new ("pipeline");
1080 bus = gst_element_get_bus (bin);
1081 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
1082
1083 g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
1084 g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
1085 g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
1086
1087 /* just an compositor and a fakesink */
1088 compositor = gst_element_factory_make ("compositor", "compositor");
1089 sink = gst_element_factory_make ("fakesink", "sink");
1090 g_object_set (sink, "signal-handoffs", TRUE, NULL);
1091 g_signal_connect (sink, "handoff", (GCallback) handoff_buffer_cb, NULL);
1092 gst_bin_add_many (GST_BIN (bin), compositor, sink, NULL);
1093
1094 res = gst_element_link (compositor, sink);
1095 fail_unless (res == TRUE, NULL);
1096
1097 /* set to playing */
1098 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1099 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1100
1101 /* create an unconnected sinkpad in compositor, should also automatically activate
1102 * the pad */
1103 sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
1104 fail_if (sinkpad == NULL, NULL);
1105
1106 gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
1107
1108 caps = gst_caps_from_string (VIDEO_CAPS_STRING);
1109
1110 gst_pad_set_caps (sinkpad, caps);
1111 gst_caps_unref (caps);
1112
1113 /* send segment to compositor */
1114 gst_segment_init (&segment, GST_FORMAT_TIME);
1115 segment.start = GST_SECOND;
1116 segment.stop = 2 * GST_SECOND;
1117 segment.time = 0;
1118 event = gst_event_new_segment (&segment);
1119 gst_pad_send_event (sinkpad, event);
1120
1121 /* should be clipped and ok */
1122 buffer = gst_buffer_new_and_alloc (115200);
1123 GST_BUFFER_TIMESTAMP (buffer) = 0;
1124 GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
1125 GST_DEBUG ("pushing buffer %p", buffer);
1126 ret = gst_pad_chain (sinkpad, buffer);
1127 ck_assert_int_eq (ret, GST_FLOW_OK);
1128 fail_unless (handoff_buffer == NULL);
1129
1130 /* should be partially clipped */
1131 buffer = gst_buffer_new_and_alloc (115200);
1132 GST_BUFFER_TIMESTAMP (buffer) = 900 * GST_MSECOND;
1133 GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
1134 GST_DEBUG ("pushing buffer %p", buffer);
1135
1136 main_loop = local_mainloop;
1137 ret = gst_pad_chain (sinkpad, buffer);
1138 ck_assert_int_eq (ret, GST_FLOW_OK);
1139 g_main_loop_run (main_loop);
1140 gst_buffer_replace (&handoff_buffer, NULL);
1141
1142 /* should not be clipped */
1143 buffer = gst_buffer_new_and_alloc (115200);
1144 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
1145 GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
1146 GST_DEBUG ("pushing buffer %p", buffer);
1147 ret = gst_pad_chain (sinkpad, buffer);
1148 g_main_loop_run (main_loop);
1149 main_loop = NULL;
1150 ck_assert_int_eq (ret, GST_FLOW_OK);
1151 fail_unless (handoff_buffer != NULL);
1152 gst_buffer_replace (&handoff_buffer, NULL);
1153
1154 /* should be clipped and ok */
1155 buffer = gst_buffer_new_and_alloc (115200);
1156 GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
1157 GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
1158 GST_DEBUG ("pushing buffer %p", buffer);
1159 ret = gst_pad_chain (sinkpad, buffer);
1160 ck_assert_int_eq (ret, GST_FLOW_OK);
1161 fail_unless (handoff_buffer == NULL);
1162
1163 gst_object_unref (sinkpad);
1164 gst_element_set_state (bin, GST_STATE_NULL);
1165 g_main_loop_unref (local_mainloop);
1166 gst_bus_remove_signal_watch (bus);
1167 gst_object_unref (bus);
1168 gst_object_unref (bin);
1169 }
1170
1171 GST_END_TEST;
1172
GST_START_TEST(test_duration_is_max)1173 GST_START_TEST (test_duration_is_max)
1174 {
1175 GstElement *bin, *src[3], *compositor, *sink;
1176 GstStateChangeReturn state_res;
1177 GstFormat format = GST_FORMAT_TIME;
1178 gboolean res;
1179 gint64 duration;
1180
1181 GST_INFO ("preparing test");
1182
1183 /* build pipeline */
1184 bin = gst_pipeline_new ("pipeline");
1185
1186 /* 3 sources, an compositor and a fakesink */
1187 src[0] = gst_element_factory_make ("videotestsrc", NULL);
1188 src[1] = gst_element_factory_make ("videotestsrc", NULL);
1189 src[2] = gst_element_factory_make ("videotestsrc", NULL);
1190 compositor = gst_element_factory_make ("compositor", "compositor");
1191 sink = gst_element_factory_make ("fakesink", "sink");
1192 gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], compositor, sink,
1193 NULL);
1194
1195 gst_element_link (src[0], compositor);
1196 gst_element_link (src[1], compositor);
1197 gst_element_link (src[2], compositor);
1198 gst_element_link (compositor, sink);
1199
1200 /* irks, duration is reset on basesrc */
1201 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
1202 fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1203
1204 /* set durations on src */
1205 GST_BASE_SRC (src[0])->segment.duration = 1000;
1206 GST_BASE_SRC (src[1])->segment.duration = 3000;
1207 GST_BASE_SRC (src[2])->segment.duration = 2000;
1208
1209 /* set to playing */
1210 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1211 fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1212
1213 /* wait for completion */
1214 state_res =
1215 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
1216 GST_CLOCK_TIME_NONE);
1217 fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1218
1219 res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration);
1220 fail_unless (res, NULL);
1221
1222 ck_assert_int_eq (duration, 3000);
1223
1224 gst_element_set_state (bin, GST_STATE_NULL);
1225 gst_object_unref (bin);
1226 }
1227
1228 GST_END_TEST;
1229
GST_START_TEST(test_duration_unknown_overrides)1230 GST_START_TEST (test_duration_unknown_overrides)
1231 {
1232 GstElement *bin, *src[3], *compositor, *sink;
1233 GstStateChangeReturn state_res;
1234 GstFormat format = GST_FORMAT_TIME;
1235 gboolean res;
1236 gint64 duration;
1237
1238 GST_INFO ("preparing test");
1239
1240 /* build pipeline */
1241 bin = gst_pipeline_new ("pipeline");
1242
1243 /* 3 sources, an compositor and a fakesink */
1244 src[0] = gst_element_factory_make ("videotestsrc", NULL);
1245 src[1] = gst_element_factory_make ("videotestsrc", NULL);
1246 src[2] = gst_element_factory_make ("videotestsrc", NULL);
1247 compositor = gst_element_factory_make ("compositor", "compositor");
1248 sink = gst_element_factory_make ("fakesink", "sink");
1249 gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], compositor, sink,
1250 NULL);
1251
1252 gst_element_link (src[0], compositor);
1253 gst_element_link (src[1], compositor);
1254 gst_element_link (src[2], compositor);
1255 gst_element_link (compositor, sink);
1256
1257 /* irks, duration is reset on basesrc */
1258 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
1259 fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1260
1261 /* set durations on src */
1262 GST_BASE_SRC (src[0])->segment.duration = GST_CLOCK_TIME_NONE;
1263 GST_BASE_SRC (src[1])->segment.duration = 3000;
1264 GST_BASE_SRC (src[2])->segment.duration = 2000;
1265
1266 /* set to playing */
1267 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1268 fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1269
1270 /* wait for completion */
1271 state_res =
1272 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
1273 GST_CLOCK_TIME_NONE);
1274 fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1275
1276 res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration);
1277 fail_unless (res, NULL);
1278
1279 ck_assert_int_eq (duration, GST_CLOCK_TIME_NONE);
1280
1281 gst_element_set_state (bin, GST_STATE_NULL);
1282 gst_object_unref (bin);
1283 }
1284
1285 GST_END_TEST;
1286
1287
1288 static gboolean looped = FALSE;
1289
1290 static void
loop_segment_done(GstBus * bus,GstMessage * message,GstElement * bin)1291 loop_segment_done (GstBus * bus, GstMessage * message, GstElement * bin)
1292 {
1293 GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
1294 GST_MESSAGE_SRC (message), message);
1295
1296 if (looped) {
1297 g_main_loop_quit (main_loop);
1298 } else {
1299 GstEvent *seek_event;
1300 gboolean res;
1301
1302 seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
1303 GST_SEEK_FLAG_SEGMENT,
1304 GST_SEEK_TYPE_SET, (GstClockTime) 0,
1305 GST_SEEK_TYPE_SET, (GstClockTime) 1 * GST_SECOND);
1306
1307 res = gst_element_send_event (bin, seek_event);
1308 fail_unless (res == TRUE, NULL);
1309 looped = TRUE;
1310 }
1311 }
1312
GST_START_TEST(test_loop)1313 GST_START_TEST (test_loop)
1314 {
1315 GstElement *bin, *src1, *src2, *compositor, *sink;
1316 GstBus *bus;
1317 GstEvent *seek_event;
1318 GstStateChangeReturn state_res;
1319 gboolean res;
1320
1321 GST_INFO ("preparing test");
1322
1323 /* build pipeline */
1324 bin = gst_pipeline_new ("pipeline");
1325 bus = gst_element_get_bus (bin);
1326 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
1327
1328 src1 = gst_element_factory_make ("videotestsrc", "src1");
1329 src2 = gst_element_factory_make ("videotestsrc", "src2");
1330 compositor = gst_element_factory_make ("compositor", "compositor");
1331 sink = gst_element_factory_make ("fakesink", "sink");
1332 gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
1333
1334 res = gst_element_link (src1, compositor);
1335 fail_unless (res == TRUE, NULL);
1336 res = gst_element_link (src2, compositor);
1337 fail_unless (res == TRUE, NULL);
1338 res = gst_element_link (compositor, sink);
1339 fail_unless (res == TRUE, NULL);
1340
1341 seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
1342 GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
1343 GST_SEEK_TYPE_SET, (GstClockTime) 0, GST_SEEK_TYPE_SET,
1344 (GstClockTime) 2 * GST_SECOND);
1345
1346 main_loop = g_main_loop_new (NULL, FALSE);
1347 g_signal_connect (bus, "message::segment-done",
1348 (GCallback) loop_segment_done, bin);
1349 g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
1350 g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
1351 g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
1352
1353 GST_INFO ("starting test");
1354
1355 /* prepare playing */
1356 state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
1357 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1358
1359 /* wait for completion */
1360 state_res =
1361 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
1362 GST_CLOCK_TIME_NONE);
1363 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1364
1365 res = gst_element_send_event (bin, seek_event);
1366 fail_unless (res == TRUE, NULL);
1367
1368 /* run pipeline */
1369 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1370 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1371
1372 GST_INFO ("running main loop");
1373 g_main_loop_run (main_loop);
1374
1375 state_res = gst_element_set_state (bin, GST_STATE_NULL);
1376
1377 /* cleanup */
1378 g_main_loop_unref (main_loop);
1379 gst_bus_remove_signal_watch (bus);
1380 gst_object_unref (bus);
1381 gst_object_unref (bin);
1382 }
1383
1384 GST_END_TEST;
1385
GST_START_TEST(test_flush_start_flush_stop)1386 GST_START_TEST (test_flush_start_flush_stop)
1387 {
1388 GstPadTemplate *sink_template;
1389 GstPad *sinkpad1, *sinkpad2, *compositor_src;
1390 GstElement *compositor;
1391
1392 GST_INFO ("preparing test");
1393
1394 /* build pipeline */
1395 compositor = gst_element_factory_make ("compositor", "compositor");
1396
1397 sink_template =
1398 gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (compositor),
1399 "sink_%u");
1400 fail_unless (GST_IS_PAD_TEMPLATE (sink_template));
1401 sinkpad1 = gst_element_request_pad (compositor, sink_template, NULL, NULL);
1402 sinkpad2 = gst_element_request_pad (compositor, sink_template, NULL, NULL);
1403 gst_object_unref (sinkpad2);
1404
1405 gst_element_set_state (compositor, GST_STATE_PLAYING);
1406 fail_unless (gst_element_get_state (compositor, NULL, NULL,
1407 GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_SUCCESS);
1408
1409 compositor_src = gst_element_get_static_pad (compositor, "src");
1410 fail_if (GST_PAD_IS_FLUSHING (compositor_src));
1411 gst_pad_send_event (sinkpad1, gst_event_new_flush_start ());
1412 fail_if (GST_PAD_IS_FLUSHING (compositor_src));
1413 fail_unless (GST_PAD_IS_FLUSHING (sinkpad1));
1414 gst_pad_send_event (sinkpad1, gst_event_new_flush_stop (TRUE));
1415 fail_if (GST_PAD_IS_FLUSHING (compositor_src));
1416 fail_if (GST_PAD_IS_FLUSHING (sinkpad1));
1417 gst_object_unref (compositor_src);
1418
1419 /* cleanup */
1420 gst_element_set_state (compositor, GST_STATE_NULL);
1421 gst_object_unref (sinkpad1);
1422 gst_object_unref (compositor);
1423 }
1424
1425 GST_END_TEST;
1426
GST_START_TEST(test_segment_base_handling)1427 GST_START_TEST (test_segment_base_handling)
1428 {
1429 GstElement *pipeline, *sink, *mix, *src1, *src2;
1430 GstPad *srcpad, *sinkpad;
1431 GstClockTime end_time;
1432 GstSample *last_sample = NULL;
1433 GstSample *sample;
1434 GstBuffer *buf;
1435 GstCaps *caps;
1436
1437 caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, 16,
1438 "height", G_TYPE_INT, 16, "framerate", GST_TYPE_FRACTION, 30, 1, NULL);
1439
1440 /* each source generates 5 seconds of data, src2 shifted by 5 seconds */
1441 pipeline = gst_pipeline_new ("pipeline");
1442 mix = gst_element_factory_make ("compositor", "compositor");
1443 sink = gst_element_factory_make ("appsink", "sink");
1444 g_object_set (sink, "caps", caps, "sync", FALSE, NULL);
1445 gst_caps_unref (caps);
1446 src1 = gst_element_factory_make ("videotestsrc", "src1");
1447 g_object_set (src1, "num-buffers", 30 * 5, "pattern", 2, NULL);
1448 src2 = gst_element_factory_make ("videotestsrc", "src2");
1449 g_object_set (src2, "num-buffers", 30 * 5, "pattern", 2, NULL);
1450 gst_bin_add_many (GST_BIN (pipeline), src1, src2, mix, sink, NULL);
1451 fail_unless (gst_element_link (mix, sink));
1452
1453 srcpad = gst_element_get_static_pad (src1, "src");
1454 sinkpad = gst_element_get_request_pad (mix, "sink_1");
1455 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
1456 gst_object_unref (sinkpad);
1457 gst_object_unref (srcpad);
1458
1459 srcpad = gst_element_get_static_pad (src2, "src");
1460 sinkpad = gst_element_get_request_pad (mix, "sink_2");
1461 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
1462 gst_pad_set_offset (sinkpad, 5 * GST_SECOND);
1463 gst_object_unref (sinkpad);
1464 gst_object_unref (srcpad);
1465
1466 gst_element_set_state (pipeline, GST_STATE_PLAYING);
1467
1468 do {
1469 g_signal_emit_by_name (sink, "pull-sample", &sample);
1470 if (sample == NULL)
1471 break;
1472 if (last_sample)
1473 gst_sample_unref (last_sample);
1474 last_sample = sample;
1475 } while (TRUE);
1476
1477 buf = gst_sample_get_buffer (last_sample);
1478 end_time = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
1479 fail_unless_equals_int64 (end_time, 10 * GST_SECOND);
1480 gst_sample_unref (last_sample);
1481
1482 gst_element_set_state (pipeline, GST_STATE_NULL);
1483 gst_object_unref (pipeline);
1484 }
1485
1486 GST_END_TEST;
1487
1488 static gboolean buffer_mapped;
1489 static gboolean (*default_map) (GstVideoMeta * meta, guint plane,
1490 GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags);
1491
1492 static gboolean
test_obscured_new_videometa_map(GstVideoMeta * meta,guint plane,GstMapInfo * info,gpointer * data,gint * stride,GstMapFlags flags)1493 test_obscured_new_videometa_map (GstVideoMeta * meta, guint plane,
1494 GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
1495 {
1496 buffer_mapped = TRUE;
1497 return default_map (meta, plane, info, data, stride, flags);
1498 }
1499
1500 static GstPadProbeReturn
test_obscured_pad_probe_cb(GstPad * srcpad,GstPadProbeInfo * info,gpointer user_data)1501 test_obscured_pad_probe_cb (GstPad * srcpad, GstPadProbeInfo * info,
1502 gpointer user_data)
1503 {
1504 GstBuffer *obuf, *nbuf;
1505 GstVideoMeta *meta;
1506
1507 GST_DEBUG ("pad probe called");
1508 /* We need to deep-copy the buffer here because videotestsrc reuses buffers
1509 * and hence the GstVideoMap associated with the buffers, and that causes a
1510 * segfault inside videotestsrc when it tries to reuse the buffer */
1511 obuf = GST_PAD_PROBE_INFO_BUFFER (info);
1512 nbuf = gst_buffer_new ();
1513 gst_buffer_copy_into (nbuf, obuf, GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP,
1514 0, -1);
1515 meta = gst_buffer_get_video_meta (nbuf);
1516 /* Override the default map() function to set also buffer_mapped */
1517 default_map = meta->map;
1518 meta->map = test_obscured_new_videometa_map;
1519 /* Replace the buffer that's going downstream */
1520 GST_PAD_PROBE_INFO_DATA (info) = nbuf;
1521 gst_buffer_unref (obuf);
1522
1523 return GST_PAD_PROBE_PASS;
1524 }
1525
1526 static void
_test_obscured(const gchar * caps_str,gint xpos0,gint ypos0,gint width0,gint height0,gdouble alpha0,gint xpos1,gint ypos1,gint width1,gint height1,gdouble alpha1,gint out_width,gint out_height)1527 _test_obscured (const gchar * caps_str, gint xpos0, gint ypos0, gint width0,
1528 gint height0, gdouble alpha0, gint xpos1, gint ypos1, gint width1,
1529 gint height1, gdouble alpha1, gint out_width, gint out_height)
1530 {
1531 GstElement *pipeline, *sink, *mix, *src0, *cfilter0, *src1, *cfilter1;
1532 GstElement *out_cfilter;
1533 GstPad *srcpad, *sinkpad;
1534 GstSample *last_sample = NULL;
1535 GstSample *sample;
1536 GstCaps *caps;
1537
1538 GST_INFO ("preparing test");
1539
1540 pipeline = gst_pipeline_new ("pipeline");
1541 src0 = gst_element_factory_make ("videotestsrc", "src0");
1542 g_object_set (src0, "num-buffers", 5, NULL);
1543 cfilter0 = gst_element_factory_make ("capsfilter", "capsfilter0");
1544 caps = gst_caps_from_string (caps_str);
1545 g_object_set (cfilter0, "caps", caps, NULL);
1546 gst_caps_unref (caps);
1547
1548 src1 = gst_element_factory_make ("videotestsrc", "src1");
1549 g_object_set (src1, "num-buffers", 5, NULL);
1550 cfilter1 = gst_element_factory_make ("capsfilter", "capsfilter1");
1551 caps = gst_caps_from_string (caps_str);
1552 g_object_set (cfilter1, "caps", caps, NULL);
1553 gst_caps_unref (caps);
1554
1555 mix = gst_element_factory_make ("compositor", "compositor");
1556 out_cfilter = gst_element_factory_make ("capsfilter", "out_capsfilter");
1557 caps = gst_caps_from_string (caps_str);
1558 if (out_width > 0)
1559 gst_caps_set_simple (caps, "width", G_TYPE_INT, out_width, NULL);
1560 if (out_height > 0)
1561 gst_caps_set_simple (caps, "height", G_TYPE_INT, out_height, NULL);
1562 g_object_set (out_cfilter, "caps", caps, NULL);
1563 gst_caps_unref (caps);
1564 sink = gst_element_factory_make ("appsink", "sink");
1565
1566 gst_bin_add_many (GST_BIN (pipeline), src0, cfilter0, src1, cfilter1, mix,
1567 out_cfilter, sink, NULL);
1568 fail_unless (gst_element_link (src0, cfilter0));
1569 fail_unless (gst_element_link (src1, cfilter1));
1570 fail_unless (gst_element_link (mix, out_cfilter));
1571 fail_unless (gst_element_link (out_cfilter, sink));
1572
1573 srcpad = gst_element_get_static_pad (cfilter0, "src");
1574 sinkpad = gst_element_get_request_pad (mix, "sink_0");
1575 g_object_set (sinkpad, "xpos", xpos0, "ypos", ypos0, "width", width0,
1576 "height", height0, "alpha", alpha0, NULL);
1577 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
1578 gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BUFFER,
1579 test_obscured_pad_probe_cb, NULL, NULL);
1580 gst_object_unref (sinkpad);
1581 gst_object_unref (srcpad);
1582
1583 srcpad = gst_element_get_static_pad (cfilter1, "src");
1584 sinkpad = gst_element_get_request_pad (mix, "sink_1");
1585 g_object_set (sinkpad, "xpos", xpos1, "ypos", ypos1, "width", width1,
1586 "height", height1, "alpha", alpha1, NULL);
1587 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
1588 gst_object_unref (sinkpad);
1589 gst_object_unref (srcpad);
1590
1591 GST_INFO ("sample prepared");
1592 gst_element_set_state (pipeline, GST_STATE_PLAYING);
1593
1594 do {
1595 GST_DEBUG ("sample pulling");
1596 g_signal_emit_by_name (sink, "pull-sample", &sample);
1597 if (sample == NULL)
1598 break;
1599 if (last_sample)
1600 gst_sample_unref (last_sample);
1601 last_sample = sample;
1602 GST_DEBUG ("sample pulled");
1603 } while (TRUE);
1604 gst_sample_unref (last_sample);
1605
1606 gst_element_set_state (pipeline, GST_STATE_NULL);
1607 gst_object_unref (pipeline);
1608 }
1609
GST_START_TEST(test_obscured_skipped)1610 GST_START_TEST (test_obscured_skipped)
1611 {
1612 gint xpos0, xpos1;
1613 gint ypos0, ypos1;
1614 gint width0, width1;
1615 gint height0, height1;
1616 gint out_width, out_height;
1617 gdouble alpha0, alpha1;
1618 const gchar *caps_str;
1619
1620 caps_str = "video/x-raw";
1621 buffer_mapped = FALSE;
1622 /* Set else to compositor defaults */
1623 alpha0 = alpha1 = 1.0;
1624 xpos0 = xpos1 = ypos0 = ypos1 = 0;
1625 width0 = width1 = height0 = height1 = 0;
1626 out_width = out_height = 0;
1627
1628 GST_INFO ("testing defaults");
1629 /* With everything at defaults, sink_1 will obscure sink_0, so buffers from
1630 * sink_0 will never get mapped by compositor. To verify, run with
1631 * GST_DEBUG=compositor:6 and look for "Obscured by" messages */
1632 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1633 width1, height1, alpha1, out_width, out_height);
1634 fail_unless (buffer_mapped == FALSE);
1635 buffer_mapped = FALSE;
1636
1637 caps_str = "video/x-raw,format=ARGB";
1638 GST_INFO ("testing video with alpha channel");
1639 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1640 width1, height1, alpha1, out_width, out_height);
1641 fail_unless (buffer_mapped == TRUE);
1642 caps_str = "video/x-raw";
1643 buffer_mapped = FALSE;
1644
1645 alpha1 = 0.0;
1646 GST_INFO ("testing alpha1 = %.2g", alpha1);
1647 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1648 width1, height1, alpha1, out_width, out_height);
1649 fail_unless (buffer_mapped == TRUE);
1650 alpha1 = 1.0;
1651 buffer_mapped = FALSE;
1652
1653 /* Test 0.1, ..., 0.9 */
1654 for (alpha1 = 1; alpha1 < 10; alpha1 += 1) {
1655 GST_INFO ("testing alpha1 = %.2g", alpha1 / 10);
1656 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1,
1657 ypos1, width1, height1, alpha1 / 10, out_width, out_height);
1658 fail_unless (buffer_mapped == TRUE);
1659 }
1660 alpha1 = 1.0;
1661 buffer_mapped = FALSE;
1662
1663 width1 = height1 = 10;
1664 GST_INFO ("testing smaller sink_1");
1665 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1666 width1, height1, alpha1, out_width, out_height);
1667 fail_unless (buffer_mapped == TRUE);
1668 width1 = height1 = 0;
1669 buffer_mapped = FALSE;
1670
1671 width0 = height0 = width1 = height1 = 10;
1672 GST_INFO ("testing smaller sink_1 and sink0 (same sizes)");
1673 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1674 width1, height1, alpha1, out_width, out_height);
1675 fail_unless (buffer_mapped == FALSE);
1676 width0 = height0 = width1 = height1 = 0;
1677 buffer_mapped = FALSE;
1678
1679 width0 = height0 = 20;
1680 width1 = height1 = 10;
1681 GST_INFO ("testing smaller sink_1 and sink0 (sink_0 > sink_1)");
1682 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1683 width1, height1, alpha1, out_width, out_height);
1684 fail_unless (buffer_mapped == TRUE);
1685 width0 = height0 = width1 = height1 = 0;
1686 buffer_mapped = FALSE;
1687
1688 width0 = height0 = 10;
1689 width1 = height1 = 20;
1690 GST_INFO ("testing smaller sink_1 and sink0 (sink_0 < sink_1)");
1691 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1692 width1, height1, alpha1, out_width, out_height);
1693 fail_unless (buffer_mapped == FALSE);
1694 width0 = height0 = width1 = height1 = 0;
1695 buffer_mapped = FALSE;
1696
1697 xpos0 = ypos0 = 10;
1698 xpos1 = ypos1 = 20;
1699 GST_INFO ("testing offset");
1700 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1701 width1, height1, alpha1, out_width, out_height);
1702 fail_unless (buffer_mapped == TRUE);
1703 xpos0 = ypos0 = xpos1 = ypos1 = 0;
1704 buffer_mapped = FALSE;
1705
1706 xpos1 = ypos1 = 0;
1707 xpos0 = ypos0 = width0 = height0 = width1 = height1 = 10;
1708 out_width = out_height = 20;
1709 GST_INFO ("testing bug 754107");
1710 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1711 width1, height1, alpha1, out_width, out_height);
1712 fail_unless (buffer_mapped == TRUE);
1713 xpos0 = ypos0 = xpos1 = ypos1 = width0 = height0 = width1 = height1 = 0;
1714 out_width = out_height = 0;
1715 buffer_mapped = FALSE;
1716
1717 xpos1 = -1;
1718 xpos0 = ypos0 = width0 = height0 = width1 = height1 = 10;
1719 out_width = out_height = 20;
1720 GST_INFO ("testing bug 754576");
1721 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1722 width1, height1, alpha1, out_width, out_height);
1723 fail_unless (buffer_mapped == TRUE);
1724 xpos0 = xpos1 = ypos1 = width0 = height0 = width1 = height1 = 0;
1725 out_width = out_height = 0;
1726 buffer_mapped = FALSE;
1727
1728 xpos0 = ypos0 = 10000;
1729 out_width = 320;
1730 out_height = 240;
1731 GST_INFO ("testing sink_0 outside the frame");
1732 _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
1733 width1, height1, alpha1, out_width, out_height);
1734 fail_unless (buffer_mapped == FALSE);
1735 xpos0 = ypos0 = out_width = out_height = 0;
1736 buffer_mapped = FALSE;
1737 }
1738
1739 GST_END_TEST;
1740
1741 static void
_pipeline_eos(GstBus * bus,GstMessage * message,GstPipeline * bin)1742 _pipeline_eos (GstBus * bus, GstMessage * message, GstPipeline * bin)
1743 {
1744 GST_INFO ("pipeline EOS");
1745 g_main_loop_quit (main_loop);
1746 }
1747
1748 static GstFlowReturn
_buffer_recvd(GstElement * appsink,gint * buffers_recvd)1749 _buffer_recvd (GstElement * appsink, gint * buffers_recvd)
1750 {
1751 GstSample *sample;
1752
1753 g_signal_emit_by_name (appsink, "pull-sample", &sample);
1754 ck_assert_msg (sample != NULL, "NULL sample received!");
1755
1756 (*buffers_recvd)++;
1757 GST_INFO ("buffer recvd");
1758 gst_sample_unref (sample);
1759
1760 if (*buffers_recvd > 5)
1761 g_main_loop_quit (main_loop);
1762
1763 return GST_FLOW_OK;
1764 }
1765
GST_START_TEST(test_repeat_after_eos)1766 GST_START_TEST (test_repeat_after_eos)
1767 {
1768 gboolean res;
1769 gint buffers_recvd;
1770 GstPadLinkReturn link_res;
1771 GstStateChangeReturn state_res;
1772 GstElement *bin, *src, *compositor, *appsink;
1773 GstPad *srcpad, *sinkpad;
1774 GstBus *bus;
1775
1776 GST_INFO ("preparing test");
1777
1778 /* build pipeline */
1779 bin = gst_pipeline_new ("pipeline");
1780 bus = gst_element_get_bus (bin);
1781 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
1782
1783 src = gst_element_factory_make ("videotestsrc", NULL);
1784 g_object_set (src, "num-buffers", 5, NULL);
1785 compositor = gst_element_factory_make ("compositor", NULL);
1786 appsink = gst_element_factory_make ("appsink", NULL);
1787 g_object_set (appsink, "emit-signals", TRUE, NULL);
1788 gst_bin_add_many (GST_BIN (bin), src, compositor, appsink, NULL);
1789
1790 res = gst_element_link (compositor, appsink);
1791 ck_assert_msg (res == TRUE, "Could not link compositor with appsink");
1792 srcpad = gst_element_get_static_pad (src, "src");
1793 sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
1794 /* When "repeat-after-eos" is set, compositor will keep sending the last buffer even
1795 * after EOS, so we will receive more buffers than we sent. */
1796 g_object_set (sinkpad, "repeat-after-eos", TRUE, NULL);
1797 link_res = gst_pad_link (srcpad, sinkpad);
1798 ck_assert_msg (GST_PAD_LINK_SUCCESSFUL (link_res), "videotestsrc -> "
1799 "compositor pad link failed: %i", link_res);
1800 gst_object_unref (sinkpad);
1801 gst_object_unref (srcpad);
1802
1803 GST_INFO ("pipeline built, connecting signals");
1804
1805 buffers_recvd = 0;
1806 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1807 ck_assert_msg (state_res != GST_STATE_CHANGE_FAILURE, "Pipeline didn't play");
1808
1809 main_loop = g_main_loop_new (NULL, FALSE);
1810 g_signal_connect (bus, "message::error", G_CALLBACK (message_received), bin);
1811 g_signal_connect (bus, "message::warning", G_CALLBACK (message_received),
1812 bin);
1813 g_signal_connect (bus, "message::eos", G_CALLBACK (_pipeline_eos), bin);
1814 g_signal_connect (appsink, "new-sample", G_CALLBACK (_buffer_recvd),
1815 &buffers_recvd);
1816
1817 GST_INFO ("starting test");
1818 g_main_loop_run (main_loop);
1819
1820 state_res = gst_element_set_state (bin, GST_STATE_NULL);
1821 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
1822
1823 ck_assert_msg (buffers_recvd > 5, "Did not receive more buffers"
1824 " than were sent");
1825
1826 /* cleanup */
1827 g_main_loop_unref (main_loop);
1828 gst_bus_remove_signal_watch (bus);
1829 gst_object_unref (bus);
1830 gst_object_unref (bin);
1831 }
1832
1833 GST_END_TEST;
1834
1835 /* Test that the GST_ELEMENT(vagg)->sinkpads GList is always sorted by zorder */
GST_START_TEST(test_pad_z_order)1836 GST_START_TEST (test_pad_z_order)
1837 {
1838 GstElement *compositor;
1839 GstPad *sinkpad1, *sinkpad2, *sinkpad3;
1840 guint zorder1, zorder2;
1841 GList *sinkpads;
1842
1843 GST_INFO ("preparing test");
1844
1845 compositor = gst_element_factory_make ("compositor", NULL);
1846 sinkpad1 = gst_element_get_request_pad (compositor, "sink_%u");
1847 sinkpad2 = gst_element_get_request_pad (compositor, "sink_%u");
1848
1849 /* Pads requested later have a higher z-order than earlier ones by default */
1850 g_object_get (sinkpad1, "zorder", &zorder1, NULL);
1851 g_object_get (sinkpad2, "zorder", &zorder2, NULL);
1852 ck_assert_int_gt (zorder2, zorder1);
1853 sinkpads = GST_ELEMENT (compositor)->sinkpads;
1854 ck_assert_ptr_eq (sinkpads->data, sinkpad1);
1855 ck_assert_ptr_eq (sinkpads->next->data, sinkpad2);
1856
1857 /* Make sinkpad1's zorder the largest, which should re-sort the sinkpads */
1858 g_object_set (sinkpad1, "zorder", zorder2 + 1, NULL);
1859 sinkpads = GST_ELEMENT (compositor)->sinkpads;
1860 ck_assert_ptr_eq (sinkpads->data, sinkpad2);
1861 ck_assert_ptr_eq (sinkpads->next->data, sinkpad1);
1862
1863 /* Get a new pad, which should be the highest pad now */
1864 sinkpad3 = gst_element_get_request_pad (compositor, "sink_%u");
1865 sinkpads = GST_ELEMENT (compositor)->sinkpads;
1866 ck_assert_ptr_eq (sinkpads->data, sinkpad2);
1867 ck_assert_ptr_eq (sinkpads->next->data, sinkpad1);
1868 ck_assert_ptr_eq (sinkpads->next->next->data, sinkpad3);
1869
1870 /* cleanup */
1871 gst_object_unref (compositor);
1872 gst_object_unref (sinkpad1);
1873 gst_object_unref (sinkpad2);
1874 gst_object_unref (sinkpad3);
1875 }
1876
1877 GST_END_TEST;
1878
1879 /*
1880 * Test that the pad numbering assigned by aggregator behaves as follows:
1881 * 1. If a pad number is requested, it must be assigned if it is available
1882 * 2. When numbering automatically, the largest available pad number is used
1883 * 3. Pad names must be unique
1884 */
GST_START_TEST(test_pad_numbering)1885 GST_START_TEST (test_pad_numbering)
1886 {
1887 GstElement *mixer;
1888 GstPad *sinkpad1, *sinkpad2, *sinkpad3, *sinkpad4;
1889
1890 GST_INFO ("preparing test");
1891
1892 mixer = gst_element_factory_make ("compositor", NULL);
1893 sinkpad1 = gst_element_get_request_pad (mixer, "sink_%u");
1894 sinkpad2 = gst_element_get_request_pad (mixer, "sink_7");
1895 sinkpad3 = gst_element_get_request_pad (mixer, "sink_1");
1896 sinkpad4 = gst_element_get_request_pad (mixer, "sink_%u");
1897
1898 ck_assert_str_eq (GST_PAD_NAME (sinkpad1), "sink_0");
1899 ck_assert_str_eq (GST_PAD_NAME (sinkpad2), "sink_7");
1900 ck_assert_str_eq (GST_PAD_NAME (sinkpad3), "sink_1");
1901 ck_assert_str_eq (GST_PAD_NAME (sinkpad4), "sink_8");
1902
1903 /* cleanup */
1904 gst_object_unref (mixer);
1905 gst_object_unref (sinkpad1);
1906 gst_object_unref (sinkpad2);
1907 gst_object_unref (sinkpad3);
1908 gst_object_unref (sinkpad4);
1909 }
1910
1911 GST_END_TEST;
1912
1913 typedef struct
1914 {
1915 gint buffers_sent;
1916 GstClockTime first_pts;
1917 gboolean first;
1918 gboolean drop;
1919 } TestStartTimeSelectionData;
1920
1921 static GstPadProbeReturn
drop_buffer_cb(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)1922 drop_buffer_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
1923 {
1924 TestStartTimeSelectionData *data = user_data;
1925
1926 if (data->drop) {
1927 data->buffers_sent = data->buffers_sent + 1;
1928 if (data->buffers_sent < 4)
1929 return GST_PAD_PROBE_DROP;
1930 }
1931
1932 data->first_pts = GST_BUFFER_PTS (info->data);
1933
1934 return GST_PAD_PROBE_REMOVE;
1935 }
1936
1937 static GstFlowReturn
first_buffer_received_cb(GstElement * appsink,gpointer user_data)1938 first_buffer_received_cb (GstElement * appsink, gpointer user_data)
1939 {
1940 TestStartTimeSelectionData *data = user_data;
1941 GstSample *sample;
1942 GstBuffer *buffer;
1943
1944 g_signal_emit_by_name (appsink, "pull-sample", &sample);
1945 ck_assert_msg (sample != NULL, "NULL sample received!");
1946
1947 buffer = gst_sample_get_buffer (sample);
1948 if (!data->first) {
1949 fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0);
1950 } else {
1951 fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), data->first_pts);
1952 }
1953
1954 gst_sample_unref (sample);
1955
1956 g_main_loop_quit (main_loop);
1957
1958 return GST_FLOW_EOS;
1959 }
1960
1961 static void
run_test_start_time(gboolean first,gboolean drop,gboolean unlinked)1962 run_test_start_time (gboolean first, gboolean drop, gboolean unlinked)
1963 {
1964 gboolean res;
1965 GstPadLinkReturn link_res;
1966 GstStateChangeReturn state_res;
1967 GstElement *bin, *src, *compositor, *appsink;
1968 GstPad *srcpad, *sinkpad;
1969 GstBus *bus;
1970 TestStartTimeSelectionData data = { 0, GST_CLOCK_TIME_NONE, first, drop };
1971
1972 GST_INFO ("preparing test");
1973
1974 /* build pipeline */
1975 bin = gst_pipeline_new ("pipeline");
1976 bus = gst_element_get_bus (bin);
1977 gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
1978
1979 src = gst_element_factory_make ("videotestsrc", NULL);
1980
1981 srcpad = gst_element_get_static_pad (src, "src");
1982 gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BUFFER, drop_buffer_cb, &data,
1983 NULL);
1984 gst_object_unref (srcpad);
1985
1986 g_object_set (src, "is-live", TRUE, NULL);
1987 compositor = gst_element_factory_make ("compositor", NULL);
1988 g_object_set (compositor, "start-time-selection", (first ? 1 : 0), NULL);
1989 appsink = gst_element_factory_make ("appsink", NULL);
1990 g_object_set (appsink, "emit-signals", TRUE, NULL);
1991 gst_bin_add_many (GST_BIN (bin), src, compositor, appsink, NULL);
1992
1993 res = gst_element_link (compositor, appsink);
1994 ck_assert_msg (res == TRUE, "Could not link compositor with appsink");
1995 srcpad = gst_element_get_static_pad (src, "src");
1996 sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
1997 link_res = gst_pad_link (srcpad, sinkpad);
1998 ck_assert_msg (GST_PAD_LINK_SUCCESSFUL (link_res), "videotestsrc -> "
1999 "compositor pad link failed: %i", link_res);
2000 gst_object_unref (sinkpad);
2001 gst_object_unref (srcpad);
2002
2003 if (unlinked) {
2004 sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
2005 gst_object_unref (sinkpad);
2006 }
2007
2008 GST_INFO ("pipeline built, connecting signals");
2009
2010 state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
2011 ck_assert_msg (state_res != GST_STATE_CHANGE_FAILURE, "Pipeline didn't play");
2012
2013 main_loop = g_main_loop_new (NULL, FALSE);
2014 g_signal_connect (bus, "message::error", G_CALLBACK (message_received), bin);
2015 g_signal_connect (bus, "message::warning", G_CALLBACK (message_received),
2016 bin);
2017 g_signal_connect (bus, "message::eos", G_CALLBACK (_pipeline_eos), bin);
2018 g_signal_connect (appsink, "new-sample",
2019 G_CALLBACK (first_buffer_received_cb), &data);
2020
2021 GST_INFO ("starting test");
2022 g_main_loop_run (main_loop);
2023
2024 state_res = gst_element_set_state (bin, GST_STATE_NULL);
2025 ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
2026
2027 /* cleanup */
2028 g_main_loop_unref (main_loop);
2029 gst_bus_remove_signal_watch (bus);
2030 gst_object_unref (bus);
2031 gst_object_unref (bin);
2032 }
2033
GST_START_TEST(test_start_time_zero_live_drop_0)2034 GST_START_TEST (test_start_time_zero_live_drop_0)
2035 {
2036 run_test_start_time (FALSE, FALSE, FALSE);
2037 }
2038
2039 GST_END_TEST;
2040
GST_START_TEST(test_start_time_zero_live_drop_3)2041 GST_START_TEST (test_start_time_zero_live_drop_3)
2042 {
2043 run_test_start_time (FALSE, TRUE, FALSE);
2044 }
2045
2046 GST_END_TEST;
2047
GST_START_TEST(test_start_time_zero_live_drop_3_unlinked_1)2048 GST_START_TEST (test_start_time_zero_live_drop_3_unlinked_1)
2049 {
2050 run_test_start_time (FALSE, TRUE, TRUE);
2051 }
2052
2053 GST_END_TEST;
2054
GST_START_TEST(test_start_time_first_live_drop_0)2055 GST_START_TEST (test_start_time_first_live_drop_0)
2056 {
2057 run_test_start_time (TRUE, FALSE, FALSE);
2058 }
2059
2060 GST_END_TEST;
2061
GST_START_TEST(test_start_time_first_live_drop_3)2062 GST_START_TEST (test_start_time_first_live_drop_3)
2063 {
2064 run_test_start_time (TRUE, TRUE, FALSE);
2065 }
2066
2067 GST_END_TEST;
2068
GST_START_TEST(test_start_time_first_live_drop_3_unlinked_1)2069 GST_START_TEST (test_start_time_first_live_drop_3_unlinked_1)
2070 {
2071 run_test_start_time (TRUE, TRUE, TRUE);
2072 }
2073
2074 GST_END_TEST;
2075
2076 static Suite *
compositor_suite(void)2077 compositor_suite (void)
2078 {
2079 Suite *s = suite_create ("compositor");
2080 TCase *tc_chain = tcase_create ("general");
2081
2082 suite_add_tcase (s, tc_chain);
2083 tcase_add_test (tc_chain, test_caps);
2084 tcase_add_test (tc_chain, test_event);
2085 tcase_add_test (tc_chain, test_caps_query);
2086 tcase_add_test (tc_chain, test_caps_query_interlaced);
2087 tcase_add_test (tc_chain, test_late_caps_query);
2088 tcase_add_test (tc_chain, test_late_caps_different_interlaced);
2089 tcase_add_test (tc_chain, test_play_twice);
2090 tcase_add_test (tc_chain, test_play_twice_then_add_and_play_again);
2091 tcase_add_test (tc_chain, test_add_pad);
2092 tcase_add_test (tc_chain, test_remove_pad);
2093 tcase_add_test (tc_chain, test_clip);
2094 tcase_add_test (tc_chain, test_duration_is_max);
2095 tcase_add_test (tc_chain, test_duration_unknown_overrides);
2096 tcase_add_test (tc_chain, test_loop);
2097 tcase_add_test (tc_chain, test_flush_start_flush_stop);
2098 tcase_add_test (tc_chain, test_segment_base_handling);
2099 tcase_add_test (tc_chain, test_obscured_skipped);
2100 tcase_add_test (tc_chain, test_repeat_after_eos);
2101 tcase_add_test (tc_chain, test_pad_z_order);
2102 tcase_add_test (tc_chain, test_pad_numbering);
2103 tcase_add_test (tc_chain, test_start_time_zero_live_drop_0);
2104 tcase_add_test (tc_chain, test_start_time_zero_live_drop_3);
2105 tcase_add_test (tc_chain, test_start_time_zero_live_drop_3_unlinked_1);
2106 tcase_add_test (tc_chain, test_start_time_first_live_drop_0);
2107 tcase_add_test (tc_chain, test_start_time_first_live_drop_3);
2108 tcase_add_test (tc_chain, test_start_time_first_live_drop_3_unlinked_1);
2109
2110 return s;
2111 }
2112
2113 GST_CHECK_MAIN (compositor);
2114