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