1 /* GStreamer
2  *
3  * unit test for videotestsrc
4  *
5  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6  * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
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/gstharness.h>
34 
35 /* For ease of programming we use globals to keep refs for our floating
36  * src and sink pads we create; otherwise we always have to do get_pad,
37  * get_peer, and then remove references in every test function */
38 static GstPad *mysinkpad;
39 
40 
41 #define CAPS_TEMPLATE_STRING            \
42     "video/x-raw, "                 \
43     "format = (string) UYVY, "          \
44     "width = (int) [ 1,  MAX ], "       \
45     "height = (int) [ 1,  MAX ], "      \
46     "framerate = (fraction) [ 0/1, MAX ]"
47 
48 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
49     GST_PAD_SINK,
50     GST_PAD_ALWAYS,
51     GST_STATIC_CAPS (CAPS_TEMPLATE_STRING)
52     );
53 
54 static GstElement *
setup_videotestsrc(void)55 setup_videotestsrc (void)
56 {
57   GstElement *videotestsrc;
58 
59   GST_DEBUG ("setup_videotestsrc");
60   videotestsrc = gst_check_setup_element ("videotestsrc");
61   mysinkpad = gst_check_setup_sink_pad (videotestsrc, &sinktemplate);
62   gst_pad_set_active (mysinkpad, TRUE);
63 
64   return videotestsrc;
65 }
66 
67 static void
cleanup_videotestsrc(GstElement * videotestsrc)68 cleanup_videotestsrc (GstElement * videotestsrc)
69 {
70   GST_DEBUG ("cleanup_videotestsrc");
71 
72   gst_check_drop_buffers ();
73 
74   gst_pad_set_active (mysinkpad, FALSE);
75   gst_check_teardown_sink_pad (videotestsrc);
76   gst_check_teardown_element (videotestsrc);
77 }
78 
GST_START_TEST(test_all_patterns)79 GST_START_TEST (test_all_patterns)
80 {
81   GstElement *videotestsrc;
82   GObjectClass *oclass;
83   GParamSpec *property;
84   GEnumValue *values;
85   guint j = 0;
86 
87   videotestsrc = setup_videotestsrc ();
88   oclass = G_OBJECT_GET_CLASS (videotestsrc);
89   property = g_object_class_find_property (oclass, "pattern");
90   fail_unless (G_IS_PARAM_SPEC_ENUM (property));
91   values = G_ENUM_CLASS (g_type_class_ref (property->value_type))->values;
92 
93   while (values[j].value_name) {
94     GST_DEBUG_OBJECT (videotestsrc, "testing pattern %s", values[j].value_name);
95 
96     g_object_set (videotestsrc, "pattern", j, NULL);
97 
98     fail_unless (gst_element_set_state (videotestsrc,
99             GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
100         "could not set to playing");
101 
102     g_mutex_lock (&check_mutex);
103     while (g_list_length (buffers) < 10) {
104       GST_DEBUG_OBJECT (videotestsrc, "Waiting for more buffers");
105       g_cond_wait (&check_cond, &check_mutex);
106     }
107     g_mutex_unlock (&check_mutex);
108 
109     gst_element_set_state (videotestsrc, GST_STATE_READY);
110 
111     gst_check_drop_buffers ();
112     ++j;
113   }
114 
115   /* cleanup */
116   cleanup_videotestsrc (videotestsrc);
117 }
118 
119 GST_END_TEST;
120 
121 static guint32
right_shift_colour(guint32 mask,guint32 pixel)122 right_shift_colour (guint32 mask, guint32 pixel)
123 {
124   if (mask == 0)
125     return 0;
126 
127   pixel = pixel & mask;
128   while ((mask & 0x01) == 0) {
129     mask = mask >> 1;
130     pixel = pixel >> 1;
131   }
132 
133   return pixel;
134 }
135 
136 static guint8
fix_expected_colour(guint32 col_mask,guint8 col_expected)137 fix_expected_colour (guint32 col_mask, guint8 col_expected)
138 {
139   guint32 mask;
140   gint last = g_bit_nth_msf (col_mask, -1);
141   gint first = g_bit_nth_lsf (col_mask, -1);
142 
143   mask = 1 << (last - first + 1);
144   mask -= 1;
145 
146   g_assert (col_expected == 0x00 || col_expected == 0xff);
147 
148   /* this only works because we only check for all-bits-set or no-bits-set */
149   return col_expected & mask;
150 }
151 
152 static void
check_rgb_buf(const guint8 * pixels,guint32 r_mask,guint32 g_mask,guint32 b_mask,guint32 a_mask,guint8 r_expected,guint8 g_expected,guint8 b_expected,guint bpp,guint depth)153 check_rgb_buf (const guint8 * pixels, guint32 r_mask, guint32 g_mask,
154     guint32 b_mask, guint32 a_mask, guint8 r_expected, guint8 g_expected,
155     guint8 b_expected, guint bpp, guint depth)
156 {
157   guint32 pixel, red, green, blue, alpha;
158 
159   switch (bpp) {
160     case 32:
161       pixel = GST_READ_UINT32_BE (pixels);
162       break;
163     case 24:
164       pixel = (GST_READ_UINT8 (pixels) << 16) |
165           (GST_READ_UINT8 (pixels + 1) << 8) |
166           (GST_READ_UINT8 (pixels + 2) << 0);
167       break;
168     case 16:
169       if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
170         pixel = GST_READ_UINT16_LE (pixels);
171       else
172         pixel = GST_READ_UINT16_BE (pixels);
173       break;
174     default:
175       g_return_if_reached ();
176   }
177 
178   red = right_shift_colour (r_mask, pixel);
179   green = right_shift_colour (g_mask, pixel);
180   blue = right_shift_colour (b_mask, pixel);
181   alpha = right_shift_colour (a_mask, pixel);
182 
183   /* can't enable this by default, valgrind will complain about accessing
184    * uninitialised memory for the depth=24,bpp=32 formats ... */
185   /* GST_LOG ("pixels: 0x%02x 0x%02x 0x%02x 0x%02x => pixel = 0x%08x",
186      pixels[0], (guint) pixels[1], pixels[2], pixels[3], pixel); */
187 
188   /* fix up the mask (for rgb15/16) */
189   if (bpp == 16) {
190     r_expected = fix_expected_colour (r_mask, r_expected);
191     g_expected = fix_expected_colour (g_mask, g_expected);
192     b_expected = fix_expected_colour (b_mask, b_expected);
193   }
194 
195   fail_unless (red == r_expected, "RED: expected 0x%02x, found 0x%02x",
196       r_expected, red);
197   fail_unless (green == g_expected, "GREEN: expected 0x%02x, found 0x%02x",
198       g_expected, green);
199   fail_unless (blue == b_expected, "BLUE: expected 0x%02x, found 0x%02x",
200       b_expected, blue);
201 
202   fail_unless (a_mask == 0 || alpha != 0);      /* better than nothing */
203 }
204 
205 static void
got_buf_cb(GstElement * sink,GstBuffer * new_buf,GstPad * pad,GstSample ** p_old_sample)206 got_buf_cb (GstElement * sink, GstBuffer * new_buf, GstPad * pad,
207     GstSample ** p_old_sample)
208 {
209   GstCaps *caps;
210 
211   caps = gst_pad_get_current_caps (pad);
212 
213   if (*p_old_sample)
214     gst_sample_unref (*p_old_sample);
215   *p_old_sample = gst_sample_new (new_buf, caps, NULL, NULL);
216 
217   gst_caps_unref (caps);
218 }
219 
220 /* tests the positioning of pixels within the various RGB pixel layouts */
GST_START_TEST(test_rgb_formats)221 GST_START_TEST (test_rgb_formats)
222 {
223   const struct
224   {
225     const gchar *pattern_name;
226     gint pattern_enum;
227     guint8 r_expected;
228     guint8 g_expected;
229     guint8 b_expected;
230   } test_patterns[] = {
231     {
232     "white", 3, 0xff, 0xff, 0xff}, {
233     "red", 4, 0xff, 0x00, 0x00}, {
234     "green", 5, 0x00, 0xff, 0x00}, {
235     "blue", 6, 0x00, 0x00, 0xff}, {
236     "black", 2, 0x00, 0x00, 0x00}
237   };
238   const struct
239   {
240     const gchar *nick;
241     guint bpp, depth;
242     guint32 red_mask, green_mask, blue_mask, alpha_mask;
243   } rgb_formats[] = {
244     {
245     "RGBA", 32, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff}, {
246     "ARGB", 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, {
247     "BGRA", 32, 32, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff}, {
248     "ABGR", 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}, {
249     "RGBx", 32, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0x00000000}, {
250     "xRGB", 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, {
251     "BGRx", 32, 24, 0x0000ff00, 0x00ff0000, 0xff000000, 0x00000000}, {
252     "xBGR", 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}, {
253     "RGB", 24, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, {
254     "BGR", 24, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}, {
255     "RGB16", 16, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000}, {
256     "RGB15", 16, 15, 0x00007c00, 0x000003e0, 0x0000001f, 0x0000000}
257   };
258   GstElement *pipeline, *src, *filter, *sink;
259   GstCaps *template_caps;
260   GstSample *sample = NULL;
261   GstPad *srcpad;
262   gint p, i, e;
263 
264   /* test check function */
265   fail_unless (right_shift_colour (0x00ff0000, 0x11223344) == 0x22);
266 
267   pipeline = gst_pipeline_new ("pipeline");
268   src = gst_check_setup_element ("videotestsrc");
269   filter = gst_check_setup_element ("capsfilter");
270   sink = gst_check_setup_element ("fakesink");
271 
272   gst_bin_add_many (GST_BIN (pipeline), src, filter, sink, NULL);
273 
274   fail_unless (gst_element_link (src, filter));
275   fail_unless (gst_element_link (filter, sink));
276 
277   srcpad = gst_element_get_static_pad (src, "src");
278   template_caps = gst_pad_get_pad_template_caps (srcpad);
279 
280   g_object_set (sink, "signal-handoffs", TRUE, NULL);
281   g_signal_connect (sink, "preroll-handoff", G_CALLBACK (got_buf_cb), &sample);
282 
283   GST_LOG ("videotestsrc src template caps: %" GST_PTR_FORMAT, template_caps);
284 
285   for (i = 0; i < G_N_ELEMENTS (rgb_formats); ++i) {
286     for (e = 0; e < 2; ++e) {
287       GstCaps *caps;
288 
289       caps = gst_caps_new_simple ("video/x-raw",
290           "format", G_TYPE_STRING, rgb_formats[i].nick,
291           "width", G_TYPE_INT, 16, "height", G_TYPE_INT, 16,
292           "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
293 
294       if (gst_caps_is_subset (caps, template_caps)) {
295         /* caps are supported, let's run some tests then ... */
296         for (p = 0; p < G_N_ELEMENTS (test_patterns); ++p) {
297           GstStateChangeReturn state_ret;
298           GstMapInfo map;
299 
300           g_object_set (src, "pattern", test_patterns[p].pattern_enum, NULL);
301 
302           GST_INFO ("%5s %u/%u %08x %08x %08x %08x, pattern=%s",
303               rgb_formats[i].nick, rgb_formats[i].bpp, rgb_formats[i].depth,
304               rgb_formats[i].red_mask, rgb_formats[i].green_mask,
305               rgb_formats[i].blue_mask, rgb_formats[i].alpha_mask,
306               test_patterns[p].pattern_name);
307 
308           /* now get videotestsrc to produce a buffer with the given caps */
309           g_object_set (filter, "caps", caps, NULL);
310 
311           state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
312           fail_unless (state_ret != GST_STATE_CHANGE_FAILURE,
313               "pipeline _set_state() to PAUSED failed");
314           state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
315           fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS,
316               "pipeline failed going to PAUSED state");
317 
318           state_ret = gst_element_set_state (pipeline, GST_STATE_NULL);
319           fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
320 
321           fail_unless (sample != NULL);
322 
323           /* check buffer caps */
324           {
325             GstBuffer *buf;
326             GstStructure *s;
327             GstCaps *caps;
328             const gchar *format;
329 
330             buf = gst_sample_get_buffer (sample);
331             fail_unless (buf != NULL);
332             caps = gst_sample_get_caps (sample);
333             fail_unless (caps != NULL);
334 
335             s = gst_caps_get_structure (caps, 0);
336             format = gst_structure_get_string (s, "format");
337             fail_unless (g_str_equal (format, rgb_formats[i].nick));
338 
339             /* now check the first pixel */
340             gst_buffer_map (buf, &map, GST_MAP_READ);
341             check_rgb_buf (map.data, rgb_formats[i].red_mask,
342                 rgb_formats[i].green_mask, rgb_formats[i].blue_mask,
343                 rgb_formats[i].alpha_mask, test_patterns[p].r_expected,
344                 test_patterns[p].g_expected, test_patterns[p].b_expected,
345                 rgb_formats[i].bpp, rgb_formats[i].depth);
346             gst_buffer_unmap (buf, &map);
347 
348             gst_sample_unref (sample);
349             sample = NULL;
350           }
351         }
352 
353       } else {
354         GST_INFO ("videotestsrc doesn't support format %" GST_PTR_FORMAT, caps);
355       }
356 
357       gst_caps_unref (caps);
358     }
359   }
360   gst_caps_unref (template_caps);
361   gst_object_unref (srcpad);
362 
363   gst_object_unref (pipeline);
364 }
365 
366 GST_END_TEST;
367 
368 struct BackwardsPlaybackData
369 {
370   GstClockTime last_ts;
371   const gchar *error_msg;
372 };
373 
374 static gboolean
eos_watch(GstBus * bus,GstMessage * message,GMainLoop * loop)375 eos_watch (GstBus * bus, GstMessage * message, GMainLoop * loop)
376 {
377   if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS) {
378     g_main_loop_quit (loop);
379   }
380   return TRUE;
381 }
382 
383 static GstPadProbeReturn
backward_check_probe(GstPad * pad,GstPadProbeInfo * info,gpointer udata)384 backward_check_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata)
385 {
386   if (info->type & GST_PAD_PROBE_TYPE_BUFFER) {
387     GstBuffer *buf = info->data;
388     struct BackwardsPlaybackData *pdata = udata;
389 
390     if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
391       if (GST_CLOCK_TIME_IS_VALID (pdata->last_ts) &&
392           pdata->last_ts < GST_BUFFER_TIMESTAMP (buf)) {
393         pdata->error_msg = "Received buffer with increasing timestamp";
394       }
395       pdata->last_ts = GST_BUFFER_TIMESTAMP (buf);
396     } else {
397       pdata->error_msg = "Received buffer without timestamp";
398     }
399 
400   }
401   return GST_PAD_PROBE_OK;
402 }
403 
GST_START_TEST(test_backward_playback)404 GST_START_TEST (test_backward_playback)
405 {
406   GstBus *bus;
407   GstElement *bin;
408   GError *error = NULL;
409   GMainLoop *loop;
410   guint bus_watch = 0;
411   GstStateChangeReturn ret;
412   GstElement *src;
413   GstPad *pad;
414   gulong pad_probe;
415   struct BackwardsPlaybackData pdata;
416 
417   pdata.last_ts = GST_CLOCK_TIME_NONE;
418   pdata.error_msg = NULL;
419 
420   bin = gst_parse_launch ("videotestsrc name=src ! fakesink name=sink "
421       "sync=true", &error);
422 
423   /* run until we receive EOS */
424   loop = g_main_loop_new (NULL, FALSE);
425   bus = gst_element_get_bus (bin);
426   bus_watch = gst_bus_add_watch (bus, (GstBusFunc) eos_watch, loop);
427   gst_object_unref (bus);
428 
429 
430   ret = gst_element_set_state (bin, GST_STATE_PAUSED);
431 
432   if (ret == GST_STATE_CHANGE_ASYNC) {
433     ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
434     fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline");
435   }
436 
437   src = gst_bin_get_by_name (GST_BIN (bin), "src");
438   pad = gst_element_get_static_pad (src, "src");
439   pad_probe = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
440       (GstPadProbeCallback) backward_check_probe, &pdata, NULL);
441 
442   gst_element_seek (bin, -1.0, GST_FORMAT_TIME,
443       GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
444       0, GST_SEEK_TYPE_SET, 1 * GST_SECOND);
445 
446   ret = gst_element_set_state (bin, GST_STATE_PLAYING);
447   fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not start test pipeline");
448   if (ret == GST_STATE_CHANGE_ASYNC) {
449     ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
450     fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline");
451   }
452   g_main_loop_run (loop);
453 
454   ret = gst_element_set_state (bin, GST_STATE_NULL);
455   fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not stop test pipeline");
456   if (ret == GST_STATE_CHANGE_ASYNC) {
457     ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
458     fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not stop test pipeline");
459   }
460 
461   if (pdata.error_msg)
462     fail ("%s", pdata.error_msg);
463 
464   /* clean up */
465   gst_pad_remove_probe (pad, pad_probe);
466   gst_object_unref (pad);
467   gst_object_unref (src);
468   g_main_loop_unref (loop);
469   g_source_remove (bus_watch);
470   gst_object_unref (bin);
471 }
472 
473 GST_END_TEST;
474 
GST_START_TEST(test_duration_query)475 GST_START_TEST (test_duration_query)
476 {
477   GstElement *bin;
478   GError *error = NULL;
479   GstStateChangeReturn ret;
480   gboolean queryret;
481   gint64 duration = -1;
482 
483   bin =
484       gst_parse_launch ("videotestsrc ! fakesink name=sink sync=true", &error);
485   ret = gst_element_set_state (bin, GST_STATE_PAUSED);
486   if (ret == GST_STATE_CHANGE_ASYNC) {
487     ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
488     fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline");
489   }
490   queryret = gst_element_query_duration (bin, GST_FORMAT_TIME, &duration);
491   /* should have unknown duration */
492   if (queryret && duration != -1) {
493     fail ("Should return false on duration query");
494   }
495   gst_element_set_state (bin, GST_STATE_NULL);
496   gst_object_unref (bin);
497 
498   bin = gst_parse_launch ("videotestsrc num-buffers=100 ! capsfilter "
499       "caps=\"video/x-raw,framerate=(fraction)10/1\" ! "
500       "fakesink name=sink sync=true", &error);
501   ret = gst_element_set_state (bin, GST_STATE_PAUSED);
502   if (ret == GST_STATE_CHANGE_ASYNC) {
503     ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
504     fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline");
505   }
506   queryret = gst_element_query_duration (bin, GST_FORMAT_TIME, &duration);
507   fail_unless (queryret, "Duration should be returned");
508   fail_unless (duration == GST_SECOND * 10, "Expected duration didn't match");
509 
510   /* reverse playback should have no impact on duration */
511   gst_element_seek (bin, -1.0, GST_FORMAT_TIME,
512       GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
513       0, GST_SEEK_TYPE_SET, 1 * GST_SECOND);
514   queryret = gst_element_query_duration (bin, GST_FORMAT_TIME, &duration);
515   fail_unless (queryret, "Duration should be returned");
516   fail_unless (duration == GST_SECOND * 10, "Expected duration didn't match");
517 
518   gst_element_set_state (bin, GST_STATE_NULL);
519   gst_object_unref (bin);
520 }
521 
522 GST_END_TEST;
523 
524 static gchar *
get_buffer_checksum(GstBuffer * buf)525 get_buffer_checksum (GstBuffer * buf)
526 {
527   GstMapInfo map = GST_MAP_INFO_INIT;
528   GChecksum *md5 = g_checksum_new (G_CHECKSUM_MD5);
529   gchar *ret;
530 
531   gst_buffer_map (buf, &map, GST_MAP_READ);
532   g_checksum_update (md5, map.data, map.size);
533   gst_buffer_unmap (buf, &map);
534 
535   ret = g_strdup (g_checksum_get_string (md5));
536   g_checksum_free (md5);
537 
538   return ret;
539 }
540 
GST_START_TEST(test_patterns_are_deterministic)541 GST_START_TEST (test_patterns_are_deterministic)
542 {
543   GType type;
544   GEnumClass *enum_class;
545   gint num_patterns;
546   GstHarness *h[2];
547   const gint num_instances = G_N_ELEMENTS (h);
548   const gint num_frames = 2;
549   gint pattern, i, frame;
550 
551   /* Create an element to register types used below */
552   gst_object_unref (gst_element_factory_make ("videotestsrc", NULL));
553 
554   /* Find number of patterns to check */
555   type = g_type_from_name ("GstVideoTestSrcPattern");
556   fail_unless (type != 0);
557   enum_class = g_type_class_ref (type);
558   num_patterns = enum_class->n_values;
559   fail_unless (num_patterns > 0);
560   g_type_class_unref (enum_class);
561 
562   /* For each pattern, make sure that all instances produce identical
563    * frames */
564   for (pattern = 0; pattern < num_patterns; pattern++) {
565 
566     for (i = 0; i < G_N_ELEMENTS (h); i++) {
567       h[i] = gst_harness_new ("videotestsrc");
568       g_object_set (h[i]->element, "pattern", pattern, NULL);
569       gst_harness_set_blocking_push_mode (h[i]);
570       gst_harness_play (h[i]);
571     }
572 
573     for (frame = 0; frame < num_frames; frame++) {
574       gchar *ref_checksum = NULL;
575 
576       for (i = 0; i < num_instances; i++) {
577         GstBuffer *buffer = gst_harness_pull (h[i]);
578         gchar *checksum = get_buffer_checksum (buffer);
579 
580         if (i == 0)
581           ref_checksum = g_strdup (checksum);
582 
583         fail_unless_equals_string (ref_checksum, checksum);
584 
585         g_free (checksum);
586         gst_buffer_unref (buffer);
587       }
588       g_free (ref_checksum);
589     }
590     for (i = 0; i < G_N_ELEMENTS (h); i++)
591       gst_harness_teardown (h[i]);
592   }
593 }
594 
595 GST_END_TEST;
596 
597 
598 
599 /* FIXME: add tests for YUV formats */
600 
601 static Suite *
videotestsrc_suite(void)602 videotestsrc_suite (void)
603 {
604   Suite *s = suite_create ("videotestsrc");
605   TCase *tc_chain = tcase_create ("general");
606 
607   suite_add_tcase (s, tc_chain);
608 
609 #ifdef HAVE_VALGRIND
610   if (RUNNING_ON_VALGRIND) {
611     /* test_rgb_formats takes a bit longer, so increase timeout */
612     tcase_set_timeout (tc_chain, 5 * 60);
613   }
614 #endif
615 
616   tcase_add_test (tc_chain, test_all_patterns);
617   tcase_add_test (tc_chain, test_rgb_formats);
618   tcase_add_test (tc_chain, test_backward_playback);
619   tcase_add_test (tc_chain, test_duration_query);
620   tcase_add_test (tc_chain, test_patterns_are_deterministic);
621 
622   return s;
623 }
624 
625 GST_CHECK_MAIN (videotestsrc);
626