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