videotestsrc: Make snow deterministic
authorStian Selnes <stian@pexip.com>
Fri, 14 Oct 2016 13:18:28 +0000 (15:18 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 1 Nov 2016 18:05:18 +0000 (20:05 +0200)
Deterministic generation of snow and smpte is important for tests so
that it's not affected by other videotestsrc elements in current or
possibly previous tests.

https://bugzilla.gnome.org/show_bug.cgi?id=773102

gst/videotestsrc/gstvideotestsrc.c
gst/videotestsrc/gstvideotestsrc.h
gst/videotestsrc/videotestsrc.c
tests/check/elements/videotestsrc.c

index 3d5c1e4..d785b5e 100644 (file)
@@ -304,6 +304,7 @@ gst_video_test_src_init (GstVideoTestSrc * src)
   src->foreground_color = DEFAULT_FOREGROUND_COLOR;
   src->background_color = DEFAULT_BACKGROUND_COLOR;
   src->horizontal_speed = DEFAULT_HORIZONTAL_SPEED;
+  src->random_state = 0;
 
   /* we operate in time */
   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
index 90388c2..42dcf33 100644 (file)
@@ -174,6 +174,9 @@ struct _GstVideoTestSrc {
   gint horizontal_offset;
   gint horizontal_speed;
 
+  /* smpte & snow */
+  guint random_state;
+
   void (*make_image) (GstVideoTestSrc *v, GstVideoFrame *frame);
 
   /* temporary AYUV/ARGB scanline */
index ae7ede2..d56f0d1 100644 (file)
 #define TO_16(x) (((x)<<8) | (x))
 
 static unsigned char
-random_char (void)
+random_char (guint * state)
 {
-  static unsigned int state;
-
-  state *= 1103515245;
-  state += 12345;
-  return (state >> 16) & 0xff;
+  *state *= 1103515245;
+  *state += 12345;
+  return (*state >> 16) & 0xff;
 }
 
 enum
@@ -413,7 +411,7 @@ gst_video_test_src_smpte (GstVideoTestSrc * v, GstVideoFrame * frame)
       p->color = &color;
 
       for (i = x1; i < w; i++) {
-        int y = random_char ();
+        int y = random_char (&v->random_state);
         p->tmpline_u8[i] = y;
       }
       videotestsrc_blend_line (v, p->tmpline + x1 * 4, p->tmpline_u8 + x1,
@@ -517,7 +515,7 @@ gst_video_test_src_snow (GstVideoTestSrc * v, GstVideoFrame * frame)
 
   for (j = 0; j < h; j++) {
     for (i = 0; i < w; i++) {
-      int y = random_char ();
+      int y = random_char (&v->random_state);
       p->tmpline_u8[i] = y;
     }
     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
index 127be28..5efb20a 100644 (file)
@@ -32,6 +32,7 @@
 #include <unistd.h>
 
 #include <gst/check/gstcheck.h>
+#include <gst/check/gstharness.h>
 
 /* For ease of programming we use globals to keep refs for our floating
  * src and sink pads we create; otherwise we always have to do get_pad,
@@ -522,6 +523,78 @@ GST_START_TEST (test_duration_query)
 
 GST_END_TEST;
 
+static gchar *
+get_buffer_checksum (GstBuffer *buf)
+{
+  GstMapInfo map = GST_MAP_INFO_INIT;
+  GChecksum *md5 = g_checksum_new (G_CHECKSUM_MD5);
+  gchar *ret;
+
+  gst_buffer_map (buf, &map, GST_MAP_READ);
+  g_checksum_update (md5, map.data, map.size);
+  gst_buffer_unmap (buf, &map);
+
+  ret = g_strdup (g_checksum_get_string (md5));
+  g_checksum_free (md5);
+
+  return ret;
+}
+
+GST_START_TEST (test_patterns_are_deterministic)
+{
+  GType type;
+  GEnumClass * enum_class;
+  gint num_patterns;
+  GstHarness *h[2];
+  const gint num_instances = G_N_ELEMENTS (h);
+  const gint num_frames = 2;
+
+  /* Create an element to register types used below */
+  gst_object_unref (gst_element_factory_make ("videotestsrc", NULL));
+
+  /* Find number of patterns to check */
+  type = g_type_from_name ("GstVideoTestSrcPattern");
+  fail_unless (type != 0);
+  enum_class = g_type_class_ref (type);
+  num_patterns = enum_class->n_values;
+  fail_unless (num_patterns > 0);
+  g_type_class_unref (enum_class);
+
+  /* For each pattern, make sure that all instances produce identical
+   * frames */
+  for (gint pattern = 0; pattern < num_patterns; pattern++) {
+
+    for (gint i = 0; i < G_N_ELEMENTS (h); i++) {
+      h[i] = gst_harness_new ("videotestsrc");
+      g_object_set (h[i]->element, "pattern", pattern, NULL);
+      gst_harness_set_blocking_push_mode (h[i]);
+      gst_harness_play (h[i]);
+    }
+
+    for (gint frame = 0; frame < num_frames; frame++) {
+      gchar *ref_checksum = NULL;
+
+      for (gint i = 0; i < num_instances; i++) {
+        GstBuffer *buffer = gst_harness_pull (h[i]);
+        gchar *checksum = get_buffer_checksum (buffer);
+
+        if (i == 0)
+          ref_checksum = g_strdup (checksum);
+
+        fail_unless_equals_string (ref_checksum, checksum);
+
+        g_free (checksum);
+        gst_buffer_unref (buffer);
+      }
+      g_free (ref_checksum);
+    }
+    for (gint i = 0; i < G_N_ELEMENTS (h); i++)
+      gst_harness_teardown (h[i]);
+  }
+}
+GST_END_TEST;
+
+
 
 /* FIXME: add tests for YUV formats */
 
@@ -544,6 +617,7 @@ videotestsrc_suite (void)
   tcase_add_test (tc_chain, test_rgb_formats);
   tcase_add_test (tc_chain, test_backward_playback);
   tcase_add_test (tc_chain, test_duration_query);
+  tcase_add_test (tc_chain, test_patterns_are_deterministic);
 
   return s;
 }