From 22ccb687fae738757818302f3d15445ff46b9cec Mon Sep 17 00:00:00 2001 From: Stian Selnes Date: Fri, 14 Oct 2016 15:18:28 +0200 Subject: [PATCH] videotestsrc: Make snow deterministic 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 | 1 + gst/videotestsrc/gstvideotestsrc.h | 3 ++ gst/videotestsrc/videotestsrc.c | 14 +++--- tests/check/elements/videotestsrc.c | 74 +++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/gst/videotestsrc/gstvideotestsrc.c b/gst/videotestsrc/gstvideotestsrc.c index 3d5c1e4ea3..d785b5e911 100644 --- a/gst/videotestsrc/gstvideotestsrc.c +++ b/gst/videotestsrc/gstvideotestsrc.c @@ -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); diff --git a/gst/videotestsrc/gstvideotestsrc.h b/gst/videotestsrc/gstvideotestsrc.h index 90388c254c..42dcf33aa5 100644 --- a/gst/videotestsrc/gstvideotestsrc.h +++ b/gst/videotestsrc/gstvideotestsrc.h @@ -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 */ diff --git a/gst/videotestsrc/videotestsrc.c b/gst/videotestsrc/videotestsrc.c index ae7ede2126..d56f0d15c8 100644 --- a/gst/videotestsrc/videotestsrc.c +++ b/gst/videotestsrc/videotestsrc.c @@ -35,13 +35,11 @@ #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, diff --git a/tests/check/elements/videotestsrc.c b/tests/check/elements/videotestsrc.c index 127be28f4d..5efb20a682 100644 --- a/tests/check/elements/videotestsrc.c +++ b/tests/check/elements/videotestsrc.c @@ -32,6 +32,7 @@ #include #include +#include /* 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; }