• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
3  * Copyright (C) 2020 Sebastian Dröge <sebastian@centricular.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include <string.h>
22 
23 #include <gst/check/gstcheck.h>
24 #include <gst/check/gstharness.h>
25 #include <gst/video/video.h>
26 
27 static gboolean
bus_handler(GstBus * bus,GstMessage * message,gpointer data)28 bus_handler (GstBus * bus, GstMessage * message, gpointer data)
29 {
30   GMainLoop *loop = (GMainLoop *) data;
31 
32   switch (message->type) {
33     case GST_MESSAGE_EOS:
34       g_main_loop_quit (loop);
35       break;
36     case GST_MESSAGE_WARNING:
37     case GST_MESSAGE_ERROR:{
38       GError *gerror;
39       gchar *debug;
40 
41       if (message->type == GST_MESSAGE_WARNING)
42         gst_message_parse_warning (message, &gerror, &debug);
43       else
44         gst_message_parse_error (message, &gerror, &debug);
45       g_error ("error from %s: %s (%s)\n",
46           GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)), gerror->message,
47           GST_STR_NULL (debug));
48       g_error_free (gerror);
49       g_free (debug);
50       g_main_loop_quit (loop);
51       break;
52     }
53     default:
54       break;
55   }
56 
57   return TRUE;
58 }
59 
60 static GstElement *
setup_imagefreeze(const GstCaps * caps1,const GstCaps * caps2,GCallback sink_handoff,gpointer sink_handoff_data)61 setup_imagefreeze (const GstCaps * caps1, const GstCaps * caps2,
62     GCallback sink_handoff, gpointer sink_handoff_data)
63 {
64   GstElement *pipeline;
65   GstElement *videotestsrc, *capsfilter1, *imagefreeze, *capsfilter2, *fakesink;
66 
67   pipeline = gst_pipeline_new ("pipeline");
68   fail_unless (pipeline != NULL);
69 
70   videotestsrc = gst_element_factory_make ("videotestsrc", "src");
71   fail_unless (videotestsrc != NULL);
72   g_object_set (videotestsrc, "num-buffers", 1, NULL);
73 
74   capsfilter1 = gst_element_factory_make ("capsfilter", "filter1");
75   fail_unless (capsfilter1 != NULL);
76   g_object_set (capsfilter1, "caps", caps1, NULL);
77 
78   imagefreeze = gst_element_factory_make ("imagefreeze", "freeze");
79   fail_unless (imagefreeze != NULL);
80 
81   capsfilter2 = gst_element_factory_make ("capsfilter", "filter2");
82   fail_unless (capsfilter2 != NULL);
83   g_object_set (capsfilter2, "caps", caps2, NULL);
84 
85   fakesink = gst_element_factory_make ("fakesink", "sink");
86   fail_unless (fakesink != NULL);
87   g_object_set (fakesink, "signal-handoffs", TRUE, "async", FALSE, NULL);
88 
89   if (sink_handoff)
90     g_signal_connect (fakesink, "handoff", sink_handoff, sink_handoff_data);
91 
92   gst_bin_add_many (GST_BIN (pipeline), videotestsrc, capsfilter1, imagefreeze,
93       capsfilter2, fakesink, NULL);
94 
95   fail_unless (gst_element_link_pads (videotestsrc, "src", capsfilter1,
96           "sink"));
97   fail_unless (gst_element_link_pads (capsfilter1, "src", imagefreeze, "sink"));
98   fail_unless (gst_element_link_pads (imagefreeze, "src", capsfilter2, "sink"));
99   fail_unless (gst_element_link_pads (capsfilter2, "src", fakesink, "sink"));
100 
101   return pipeline;
102 }
103 
104 static void
sink_handoff_cb_0_1(GstElement * object,GstBuffer * buffer,GstPad * pad,gpointer user_data)105 sink_handoff_cb_0_1 (GstElement * object, GstBuffer * buffer, GstPad * pad,
106     gpointer user_data)
107 {
108   guint *n_buffers = (guint *) user_data;
109 
110   if (*n_buffers == G_MAXUINT)
111     return;
112 
113   fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer), 0);
114   fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), GST_CLOCK_TIME_NONE);
115   fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buffer), 0);
116   fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (buffer), 1);
117 
118   *n_buffers = *n_buffers + 1;
119 }
120 
GST_START_TEST(test_imagefreeze_0_1)121 GST_START_TEST (test_imagefreeze_0_1)
122 {
123   GstElement *pipeline;
124   GstCaps *caps1, *caps2;
125   GstBus *bus;
126   GMainLoop *loop;
127   guint n_buffers = G_MAXUINT;
128   guint bus_watch = 0;
129   GstVideoInfo i1, i2;
130 
131   gst_video_info_init (&i1);
132   gst_video_info_set_format (&i1, GST_VIDEO_FORMAT_xRGB, 640, 480);
133   i1.fps_n = 25;
134   i1.fps_d = 1;
135   caps1 = gst_video_info_to_caps (&i1);
136 
137   gst_video_info_init (&i2);
138   gst_video_info_set_format (&i2, GST_VIDEO_FORMAT_xRGB, 640, 480);
139   caps2 = gst_video_info_to_caps (&i2);
140 
141   pipeline =
142       setup_imagefreeze (caps1, caps2, G_CALLBACK (sink_handoff_cb_0_1),
143       &n_buffers);
144 
145   loop = g_main_loop_new (NULL, TRUE);
146   fail_unless (loop != NULL);
147 
148   bus = gst_element_get_bus (pipeline);
149   fail_unless (bus != NULL);
150   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
151   gst_object_unref (bus);
152 
153   n_buffers = 0;
154   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
155       GST_STATE_CHANGE_SUCCESS);
156 
157   g_main_loop_run (loop);
158 
159   fail_unless_equals_int (n_buffers, 1);
160 
161   gst_element_set_state (pipeline, GST_STATE_NULL);
162 
163   gst_object_unref (pipeline);
164   g_main_loop_unref (loop);
165   gst_caps_unref (caps1);
166   gst_caps_unref (caps2);
167   g_source_remove (bus_watch);
168 }
169 
170 GST_END_TEST;
171 
172 static void
sink_handoff_cb_25_1_0ms_400ms(GstElement * object,GstBuffer * buffer,GstPad * pad,gpointer user_data)173 sink_handoff_cb_25_1_0ms_400ms (GstElement * object, GstBuffer * buffer,
174     GstPad * pad, gpointer user_data)
175 {
176   guint *n_buffers = (guint *) user_data;
177 
178   if (*n_buffers == G_MAXUINT)
179     return;
180 
181   fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
182       *n_buffers * 40 * GST_MSECOND);
183   fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), 40 * GST_MSECOND);
184   fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buffer), *n_buffers);
185   fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (buffer), *n_buffers + 1);
186 
187   *n_buffers = *n_buffers + 1;
188 }
189 
GST_START_TEST(test_imagefreeze_25_1_0ms_400ms)190 GST_START_TEST (test_imagefreeze_25_1_0ms_400ms)
191 {
192   GstElement *pipeline;
193   GstCaps *caps1, *caps2;
194   GstBus *bus;
195   GMainLoop *loop;
196   guint n_buffers = G_MAXUINT;
197   guint bus_watch = 0;
198   GstVideoInfo i1, i2;
199 
200   gst_video_info_init (&i1);
201   gst_video_info_set_format (&i1, GST_VIDEO_FORMAT_xRGB, 640, 480);
202   i1.fps_n = 25;
203   i1.fps_d = 1;
204   caps1 = gst_video_info_to_caps (&i1);
205 
206   gst_video_info_init (&i2);
207   gst_video_info_set_format (&i2, GST_VIDEO_FORMAT_xRGB, 640, 480);
208   i2.fps_n = 25;
209   i2.fps_d = 1;
210   caps2 = gst_video_info_to_caps (&i2);
211 
212   pipeline =
213       setup_imagefreeze (caps1, caps2,
214       G_CALLBACK (sink_handoff_cb_25_1_0ms_400ms), &n_buffers);
215 
216   loop = g_main_loop_new (NULL, TRUE);
217   fail_unless (loop != NULL);
218 
219   bus = gst_element_get_bus (pipeline);
220   fail_unless (bus != NULL);
221   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
222   gst_object_unref (bus);
223 
224   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
225       GST_STATE_CHANGE_SUCCESS);
226 
227   fail_unless (gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME,
228           GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET,
229           400 * GST_MSECOND));
230 
231   n_buffers = 0;
232 
233   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
234       GST_STATE_CHANGE_SUCCESS);
235 
236   g_main_loop_run (loop);
237 
238   fail_unless_equals_int (n_buffers, 10);
239 
240   gst_element_set_state (pipeline, GST_STATE_NULL);
241 
242   gst_object_unref (pipeline);
243   g_main_loop_unref (loop);
244   gst_caps_unref (caps1);
245   gst_caps_unref (caps2);
246   g_source_remove (bus_watch);
247 }
248 
249 GST_END_TEST;
250 
251 static void
sink_handoff_cb_25_1_200ms_400ms(GstElement * object,GstBuffer * buffer,GstPad * pad,gpointer user_data)252 sink_handoff_cb_25_1_200ms_400ms (GstElement * object, GstBuffer * buffer,
253     GstPad * pad, gpointer user_data)
254 {
255   guint *n_buffers = (guint *) user_data;
256 
257   if (*n_buffers == G_MAXUINT)
258     return;
259 
260   fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
261       200 * GST_MSECOND + *n_buffers * 40 * GST_MSECOND);
262   fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), 40 * GST_MSECOND);
263   fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buffer), 5 + *n_buffers);
264   fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (buffer),
265       5 + *n_buffers + 1);
266 
267   *n_buffers = *n_buffers + 1;
268 }
269 
GST_START_TEST(test_imagefreeze_25_1_200ms_400ms)270 GST_START_TEST (test_imagefreeze_25_1_200ms_400ms)
271 {
272   GstElement *pipeline;
273   GstCaps *caps1, *caps2;
274   GstBus *bus;
275   GMainLoop *loop;
276   guint n_buffers = G_MAXUINT;
277   guint bus_watch = 0;
278   GstVideoInfo i1, i2;
279 
280   gst_video_info_init (&i1);
281   gst_video_info_set_format (&i1, GST_VIDEO_FORMAT_xRGB, 640, 480);
282   i1.fps_n = 25;
283   i1.fps_d = 1;
284   caps1 = gst_video_info_to_caps (&i1);
285 
286   gst_video_info_init (&i2);
287   gst_video_info_set_format (&i2, GST_VIDEO_FORMAT_xRGB, 640, 480);
288   i2.fps_n = 25;
289   i2.fps_d = 1;
290   caps2 = gst_video_info_to_caps (&i2);
291 
292   pipeline =
293       setup_imagefreeze (caps1, caps2,
294       G_CALLBACK (sink_handoff_cb_25_1_200ms_400ms), &n_buffers);
295 
296   loop = g_main_loop_new (NULL, TRUE);
297   fail_unless (loop != NULL);
298 
299   bus = gst_element_get_bus (pipeline);
300   fail_unless (bus != NULL);
301   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
302   gst_object_unref (bus);
303 
304   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
305       GST_STATE_CHANGE_SUCCESS);
306 
307   fail_unless (gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME,
308           GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 200 * GST_MSECOND,
309           GST_SEEK_TYPE_SET, 400 * GST_MSECOND));
310 
311   n_buffers = 0;
312 
313   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
314       GST_STATE_CHANGE_SUCCESS);
315 
316   g_main_loop_run (loop);
317 
318   fail_unless_equals_int (n_buffers, 5);
319 
320   gst_element_set_state (pipeline, GST_STATE_NULL);
321 
322   gst_object_unref (pipeline);
323   g_main_loop_unref (loop);
324   gst_caps_unref (caps1);
325   gst_caps_unref (caps2);
326   g_source_remove (bus_watch);
327 }
328 
329 GST_END_TEST;
330 
331 static void
sink_handoff_cb_25_1_400ms_0ms(GstElement * object,GstBuffer * buffer,GstPad * pad,gpointer user_data)332 sink_handoff_cb_25_1_400ms_0ms (GstElement * object, GstBuffer * buffer,
333     GstPad * pad, gpointer user_data)
334 {
335   guint *n_buffers = (guint *) user_data;
336 
337   if (*n_buffers == G_MAXUINT)
338     return;
339 
340   fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
341       400 * GST_MSECOND - (*n_buffers + 1) * 40 * GST_MSECOND);
342   fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), 40 * GST_MSECOND);
343   fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buffer), 10 - (*n_buffers + 1));
344   fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (buffer),
345       10 - (*n_buffers + 1) + 1);
346 
347   *n_buffers = *n_buffers + 1;
348 }
349 
GST_START_TEST(test_imagefreeze_25_1_400ms_0ms)350 GST_START_TEST (test_imagefreeze_25_1_400ms_0ms)
351 {
352   GstElement *pipeline;
353   GstCaps *caps1, *caps2;
354   GstBus *bus;
355   GMainLoop *loop;
356   guint n_buffers = G_MAXUINT;
357   guint bus_watch = 0;
358   GstVideoInfo i1, i2;
359 
360   gst_video_info_init (&i1);
361   gst_video_info_set_format (&i1, GST_VIDEO_FORMAT_xRGB, 640, 480);
362   i1.fps_n = 25;
363   i1.fps_d = 1;
364   caps1 = gst_video_info_to_caps (&i1);
365 
366   gst_video_info_init (&i2);
367   gst_video_info_set_format (&i2, GST_VIDEO_FORMAT_xRGB, 640, 480);
368   i2.fps_n = 25;
369   i2.fps_d = 1;
370   caps2 = gst_video_info_to_caps (&i2);
371 
372   pipeline =
373       setup_imagefreeze (caps1, caps2,
374       G_CALLBACK (sink_handoff_cb_25_1_400ms_0ms), &n_buffers);
375 
376   loop = g_main_loop_new (NULL, TRUE);
377   fail_unless (loop != NULL);
378 
379   bus = gst_element_get_bus (pipeline);
380   fail_unless (bus != NULL);
381   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
382   gst_object_unref (bus);
383 
384   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
385       GST_STATE_CHANGE_SUCCESS);
386 
387   fail_unless (gst_element_seek (pipeline, -1.0, GST_FORMAT_TIME,
388           GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET,
389           400 * GST_MSECOND));
390 
391   n_buffers = 0;
392 
393   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
394       GST_STATE_CHANGE_SUCCESS);
395 
396   g_main_loop_run (loop);
397 
398   fail_unless_equals_int (n_buffers, 10);
399 
400   gst_element_set_state (pipeline, GST_STATE_NULL);
401 
402   gst_object_unref (pipeline);
403   g_main_loop_unref (loop);
404   gst_caps_unref (caps1);
405   gst_caps_unref (caps2);
406   g_source_remove (bus_watch);
407 }
408 
409 GST_END_TEST;
410 
411 static void
sink_handoff_cb_25_1_220ms_380ms(GstElement * object,GstBuffer * buffer,GstPad * pad,gpointer user_data)412 sink_handoff_cb_25_1_220ms_380ms (GstElement * object, GstBuffer * buffer,
413     GstPad * pad, gpointer user_data)
414 {
415   guint *n_buffers = (guint *) user_data;
416 
417   if (*n_buffers == G_MAXUINT)
418     return;
419 
420   if (*n_buffers == 0) {
421     fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
422         220 * GST_MSECOND);
423     fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), 20 * GST_MSECOND);
424   } else if (*n_buffers == 4) {
425     fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
426         360 * GST_MSECOND);
427     fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), 20 * GST_MSECOND);
428   } else {
429     fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
430         200 * GST_MSECOND + *n_buffers * 40 * GST_MSECOND);
431     fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), 40 * GST_MSECOND);
432   }
433 
434   fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buffer), 5 + *n_buffers);
435   fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (buffer),
436       5 + *n_buffers + 1);
437 
438   *n_buffers = *n_buffers + 1;
439 }
440 
GST_START_TEST(test_imagefreeze_25_1_220ms_380ms)441 GST_START_TEST (test_imagefreeze_25_1_220ms_380ms)
442 {
443   GstElement *pipeline;
444   GstCaps *caps1, *caps2;
445   GstBus *bus;
446   GMainLoop *loop;
447   guint n_buffers = G_MAXUINT;
448   guint bus_watch = 0;
449   GstVideoInfo i1, i2;
450 
451   gst_video_info_init (&i1);
452   gst_video_info_set_format (&i1, GST_VIDEO_FORMAT_xRGB, 640, 480);
453   i1.fps_n = 25;
454   i1.fps_d = 1;
455   caps1 = gst_video_info_to_caps (&i1);
456 
457   gst_video_info_init (&i2);
458   gst_video_info_set_format (&i2, GST_VIDEO_FORMAT_xRGB, 640, 480);
459   i2.fps_n = 25;
460   i2.fps_d = 1;
461   caps2 = gst_video_info_to_caps (&i2);
462 
463   pipeline =
464       setup_imagefreeze (caps1, caps2,
465       G_CALLBACK (sink_handoff_cb_25_1_220ms_380ms), &n_buffers);
466 
467   loop = g_main_loop_new (NULL, TRUE);
468   fail_unless (loop != NULL);
469 
470   bus = gst_element_get_bus (pipeline);
471   fail_unless (bus != NULL);
472   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
473   gst_object_unref (bus);
474 
475   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
476       GST_STATE_CHANGE_SUCCESS);
477 
478   fail_unless (gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME,
479           GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 220 * GST_MSECOND,
480           GST_SEEK_TYPE_SET, 380 * GST_MSECOND));
481 
482   n_buffers = 0;
483 
484   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
485       GST_STATE_CHANGE_SUCCESS);
486 
487   g_main_loop_run (loop);
488 
489   fail_unless_equals_int (n_buffers, 5);
490 
491   gst_element_set_state (pipeline, GST_STATE_NULL);
492 
493   gst_object_unref (pipeline);
494   g_main_loop_unref (loop);
495   gst_caps_unref (caps1);
496   gst_caps_unref (caps2);
497   g_source_remove (bus_watch);
498 }
499 
500 GST_END_TEST;
501 
502 static void
sink_handoff_cb_count_buffers(GstElement * object,GstBuffer * buffer,GstPad * pad,gpointer user_data)503 sink_handoff_cb_count_buffers (GstElement * object, GstBuffer * buffer,
504     GstPad * pad, gpointer user_data)
505 {
506   guint *n_buffers = (guint *) user_data;
507 
508   if (*n_buffers == G_MAXUINT)
509     return;
510 
511   *n_buffers = *n_buffers + 1;
512 }
513 
GST_START_TEST(test_imagefreeze_num_buffers)514 GST_START_TEST (test_imagefreeze_num_buffers)
515 {
516   GstElement *pipeline;
517   GstElement *imagefreeze;
518   GstCaps *caps1, *caps2;
519   GstBus *bus;
520   GMainLoop *loop;
521   guint n_buffers = G_MAXUINT;
522   guint bus_watch = 0;
523   GstVideoInfo i1, i2;
524 
525   gst_video_info_init (&i1);
526   gst_video_info_set_format (&i1, GST_VIDEO_FORMAT_xRGB, 640, 480);
527   i1.fps_n = 25;
528   i1.fps_d = 1;
529   caps1 = gst_video_info_to_caps (&i1);
530 
531   gst_video_info_init (&i2);
532   gst_video_info_set_format (&i2, GST_VIDEO_FORMAT_xRGB, 640, 480);
533   i2.fps_n = 25;
534   i2.fps_d = 1;
535   caps2 = gst_video_info_to_caps (&i2);
536 
537   pipeline =
538       setup_imagefreeze (caps1, caps2,
539       G_CALLBACK (sink_handoff_cb_count_buffers), &n_buffers);
540 
541   imagefreeze = gst_bin_get_by_name (GST_BIN (pipeline), "freeze");
542   fail_unless (imagefreeze != NULL);
543 
544   loop = g_main_loop_new (NULL, TRUE);
545   fail_unless (loop != NULL);
546 
547   bus = gst_element_get_bus (pipeline);
548   fail_unless (bus != NULL);
549   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
550   gst_object_unref (bus);
551 
552   /* Check that 0 buffers have been pushed */
553   g_object_set (imagefreeze, "num-buffers", 0, NULL);
554   n_buffers = 0;
555 
556   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
557       GST_STATE_CHANGE_SUCCESS);
558 
559   g_main_loop_run (loop);
560 
561   fail_unless_equals_int (n_buffers, 0);
562 
563   gst_element_set_state (pipeline, GST_STATE_NULL);
564 
565   /* Check that the exact number of buffers have been pushed */
566   g_object_set (imagefreeze, "num-buffers", 100, NULL);
567   n_buffers = 0;
568 
569   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
570       GST_STATE_CHANGE_SUCCESS);
571 
572   g_main_loop_run (loop);
573 
574   fail_unless_equals_int (n_buffers, 100);
575 
576   gst_element_set_state (pipeline, GST_STATE_NULL);
577 
578   gst_object_unref (imagefreeze);
579   gst_object_unref (pipeline);
580   g_main_loop_unref (loop);
581   gst_caps_unref (caps1);
582   gst_caps_unref (caps2);
583   g_source_remove (bus_watch);
584 }
585 
586 GST_END_TEST;
587 
GST_START_TEST(test_imagefreeze_eos)588 GST_START_TEST (test_imagefreeze_eos)
589 {
590   GstElement *pipeline;
591   GstElement *src;
592   GstCaps *caps1, *caps2;
593   GstBus *bus;
594   GMainLoop *loop;
595   GstFormat fmt = GST_FORMAT_TIME;
596   gint64 position;
597   guint bus_watch = 0;
598   GstVideoInfo i1, i2;
599 
600   gst_video_info_init (&i1);
601   gst_video_info_set_format (&i1, GST_VIDEO_FORMAT_xRGB, 640, 480);
602   i1.fps_n = 25;
603   i1.fps_d = 1;
604   caps1 = gst_video_info_to_caps (&i1);
605 
606   gst_video_info_init (&i2);
607   gst_video_info_set_format (&i2, GST_VIDEO_FORMAT_xRGB, 640, 480);
608   i2.fps_n = 25;
609   i2.fps_d = 1;
610   caps2 = gst_video_info_to_caps (&i2);
611 
612   pipeline = setup_imagefreeze (caps1, caps2, NULL, NULL);
613 
614   src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
615   fail_unless (src != NULL);
616   g_object_set (src, "num-buffers", 100, NULL);
617 
618   loop = g_main_loop_new (NULL, TRUE);
619   fail_unless (loop != NULL);
620 
621   bus = gst_element_get_bus (pipeline);
622   fail_unless (bus != NULL);
623   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
624   gst_object_unref (bus);
625 
626   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
627       GST_STATE_CHANGE_SUCCESS);
628 
629   fail_unless (gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME,
630           GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET,
631           400 * GST_MSECOND));
632 
633   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
634       GST_STATE_CHANGE_SUCCESS);
635 
636   g_main_loop_run (loop);
637 
638   fail_unless (gst_element_query_position (src, fmt, &position));
639   fail_unless_equals_uint64 (position, 40 * GST_MSECOND);
640 
641   gst_element_set_state (pipeline, GST_STATE_NULL);
642 
643   gst_object_unref (src);
644   gst_object_unref (pipeline);
645   g_main_loop_unref (loop);
646   gst_caps_unref (caps1);
647   gst_caps_unref (caps2);
648   g_source_remove (bus_watch);
649 }
650 
651 GST_END_TEST;
652 
GST_START_TEST(test_imagefreeze_25_1_live)653 GST_START_TEST (test_imagefreeze_25_1_live)
654 {
655   GstBuffer *buffer;
656   GstHarness *h = gst_harness_new_parse ("imagefreeze is-live=true");
657   guint i;
658 
659   gst_harness_use_testclock (h);
660   gst_harness_play (h);
661 
662   gst_harness_set_src_caps_str (h,
663       "video/x-raw, format=xRGB, width=640, height=480, framerate=0/1");
664   gst_harness_set_sink_caps_str (h,
665       "video/x-raw, format=xRGB, width=640, height=480, framerate=25/1");
666 
667   /* Fill the buffer */
668   buffer = gst_buffer_new ();
669   fail_unless_equals_int (gst_harness_push (h, buffer), GST_FLOW_EOS);
670   fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
671 
672   /* Check if we can get 10 buffers under normal circumstances out */
673   for (i = 0; i < 10; i++) {
674     fail_unless (gst_harness_crank_single_clock_wait (h));
675     buffer = gst_harness_pull (h);
676     fail_unless (buffer != NULL);
677     fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), i * 40 * GST_MSECOND);
678     gst_buffer_unref (buffer);
679   }
680 
681   /* Skip ahead, now the next buffer would be too late so imagefreeze should
682    * skip ahead too and continue from there */
683   fail_unless (gst_harness_wait_for_clock_id_waits (h, 1, 5));
684   gst_harness_set_time (h, 1 * GST_SECOND);
685 
686   /* FIXME: Consume one more buffer that went through because of a testclock
687    * bug. See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/581
688    */
689   fail_unless (gst_harness_crank_single_clock_wait (h));
690   buffer = gst_harness_pull (h);
691   fail_unless (buffer != NULL);
692   fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), i * 40 * GST_MSECOND);
693   gst_buffer_unref (buffer);
694 
695   /* Check if we can get 10 more buffers after the 1s gap */
696   for (i = 0; i < 10; i++) {
697     fail_unless (gst_harness_crank_single_clock_wait (h));
698     buffer = gst_harness_pull (h);
699     fail_unless (buffer != NULL);
700     fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer),
701         GST_SECOND + i * 40 * GST_MSECOND);
702     gst_buffer_unref (buffer);
703   }
704 
705   gst_harness_teardown (h);
706 }
707 
708 GST_END_TEST;
709 
710 static Suite *
imagefreeze_suite(void)711 imagefreeze_suite (void)
712 {
713   Suite *s = suite_create ("imagefreeze");
714   TCase *tc_chain = tcase_create ("linear");
715 
716   /* time out after 120s, not the default 3 */
717   tcase_set_timeout (tc_chain, 120);
718 
719   suite_add_tcase (s, tc_chain);
720   tcase_add_test (tc_chain, test_imagefreeze_0_1);
721   tcase_add_test (tc_chain, test_imagefreeze_25_1_0ms_400ms);
722   tcase_add_test (tc_chain, test_imagefreeze_25_1_200ms_400ms);
723   tcase_add_test (tc_chain, test_imagefreeze_25_1_400ms_0ms);
724   tcase_add_test (tc_chain, test_imagefreeze_25_1_220ms_380ms);
725 
726   tcase_add_test (tc_chain, test_imagefreeze_num_buffers);
727   tcase_add_test (tc_chain, test_imagefreeze_eos);
728 
729   tcase_add_test (tc_chain, test_imagefreeze_25_1_live);
730 
731   return s;
732 }
733 
734 GST_CHECK_MAIN (imagefreeze);
735