• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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