tests: add colorspace unit test

Compares colorspace result with ffmpegcolorspace output using SSIM.
Also probes for possible crashes for odd width and height image by applying
all possible colorspace transformations.
This commit is contained in:
Mark Nauwelaerts 2011-06-16 17:17:07 +02:00
parent 6429ead4bc
commit af1fca6d7d
2 changed files with 313 additions and 1 deletions

View file

@ -138,7 +138,8 @@ endif
VALGRIND_TO_FIX = \ VALGRIND_TO_FIX = \
elements/mpeg2enc \ elements/mpeg2enc \
elements/mplex \ elements/mplex \
elements/zbar elements/zbar \
pipeline/colorspace
# valgrind testing # valgrind testing
VALGRIND_TESTS_DISABLE = \ VALGRIND_TESTS_DISABLE = \
@ -183,6 +184,7 @@ check_PROGRAMS = \
elements/mxfmux \ elements/mxfmux \
elements/id3mux \ elements/id3mux \
pipelines/mxf \ pipelines/mxf \
pipelines/colorspace \
$(check_mimic) \ $(check_mimic) \
elements/rtpmux \ elements/rtpmux \
$(check_schro) \ $(check_schro) \

View file

@ -0,0 +1,310 @@
/* GStreamer
*
* unit comparison test for colorspace
*
* Copyright 2011 Collabora Ltd.
* @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
* Copyright 2011 Nokia Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gst/check/gstcheck.h>
static GMainLoop *loop;
static void
message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
{
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:
case GST_MESSAGE_WARNING:
g_assert_not_reached ();
break;
case GST_MESSAGE_EOS:
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ELEMENT:
{
const GstStructure *s = gst_message_get_structure (message);
const gchar *name = gst_structure_get_name (s);
fail_unless (strcmp (name, "delta") == 0);
break;
}
default:
break;
}
}
/* compare output with ffmpegcolorspace */
static void
colorspace_compare (gint width, gint height, gboolean comp)
{
GstBus *bus;
GstElement *pipeline, *src, *filter1, *filter2, *csp, *fcsp, *fakesink;
GstElement *queue1, *queue2, *tee, *compare;
GstCaps *caps, *tcaps, *rcaps, *fcaps;
const GstCaps *ccaps;
GstPad *pad;
gint i, j;
/* create elements */
pipeline = gst_pipeline_new ("pipeline");
src = gst_element_factory_make ("videotestsrc", "videotestsrc");
fail_unless (src != NULL);
filter1 = gst_element_factory_make ("capsfilter", "capsfilter1");
fail_unless (filter1 != NULL);
csp = gst_element_factory_make ("colorspace", "colorspace");
fail_unless (csp != NULL);
filter2 = gst_element_factory_make ("capsfilter", "capsfilter2");
fail_unless (filter2 != NULL);
if (comp) {
fcsp = gst_element_factory_make ("ffmpegcolorspace", "ffmpegcolorspace");
fail_unless (fcsp != NULL);
tee = gst_element_factory_make ("tee", "tee");
fail_unless (tee != NULL);
queue1 = gst_element_factory_make ("queue", "queue1");
fail_unless (queue1 != NULL);
queue2 = gst_element_factory_make ("queue", "queue2");
fail_unless (queue2 != NULL);
compare = gst_element_factory_make ("compare", "compare");
fail_unless (compare != NULL);
} else {
fcsp = tee = queue1 = queue2 = compare = NULL;
}
fakesink = gst_element_factory_make ("fakesink", "fakesink");
fail_unless (fakesink != NULL);
/* add and link */
gst_bin_add_many (GST_BIN (pipeline), src, filter1, filter2, csp, fakesink,
tee, queue1, queue2, fcsp, compare, NULL);
fail_unless (gst_element_link (src, filter1));
if (comp) {
fail_unless (gst_element_link (filter1, tee));
fail_unless (gst_element_link (tee, queue1));
fail_unless (gst_element_link (queue1, fcsp));
fail_unless (gst_element_link_pads (fcsp, NULL, compare, "sink"));
fail_unless (gst_element_link (tee, queue2));
fail_unless (gst_element_link (queue2, csp));
fail_unless (gst_element_link_pads (csp, NULL, compare, "check"));
fail_unless (gst_element_link (compare, filter2));
} else {
fail_unless (gst_element_link (filter1, csp));
fail_unless (gst_element_link (csp, filter2));
}
fail_unless (gst_element_link (filter2, fakesink));
/* obtain possible caps combinations */
if (comp) {
pad = gst_element_get_static_pad (fcsp, "sink");
fail_unless (pad != NULL);
ccaps = gst_pad_get_pad_template_caps (pad);
fail_unless (ccaps != NULL);
fcaps = gst_caps_copy (ccaps);
gst_object_unref (pad);
} else {
fcaps = gst_caps_new_any ();
}
pad = gst_element_get_static_pad (csp, "sink");
fail_unless (pad != NULL);
ccaps = gst_pad_get_pad_template_caps (pad);
fail_unless (ccaps != NULL);
gst_object_unref (pad);
/* handle videotestsrc limitations */
pad = gst_element_get_static_pad (src, "src");
fail_unless (pad != NULL);
caps = (GstCaps *) gst_pad_get_pad_template_caps (pad);
fail_unless (caps != NULL);
gst_object_unref (pad);
rcaps = gst_caps_new_simple ("video/x-raw-yuv",
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
"framerate", GST_TYPE_FRACTION, 25, 1,
"color-matrix", G_TYPE_STRING, "sdtv",
"chroma-site", G_TYPE_STRING, "mpeg2", NULL);
gst_caps_append (rcaps, gst_caps_new_simple ("video/x-raw-rgb",
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
"framerate", GST_TYPE_FRACTION, 25, 1,
"depth", G_TYPE_INT, 32, NULL));
/* FIXME also allow x-raw-gray if/when colorspace actually handles those */
/* limit to supported compare types */
if (comp) {
gst_caps_append (rcaps, gst_caps_new_simple ("video/x-raw-rgb",
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
"framerate", GST_TYPE_FRACTION, 25, 1,
"depth", G_TYPE_INT, 24, NULL));
}
tcaps = gst_caps_intersect (fcaps, ccaps);
gst_caps_unref (fcaps);
caps = gst_caps_intersect (tcaps, caps);
gst_caps_unref (tcaps);
tcaps = caps;
caps = gst_caps_intersect (tcaps, rcaps);
gst_caps_unref (tcaps);
gst_caps_unref (rcaps);
/* normalize to finally have a list of acceptable fixed formats */
gst_caps_do_simplify (caps);
tcaps = caps;
caps = gst_caps_normalize (tcaps);
gst_caps_unref (tcaps);
/* set up for running stuff */
loop = g_main_loop_new (NULL, FALSE);
bus = gst_element_get_bus (pipeline);
gst_bus_add_signal_watch (bus);
g_signal_connect (bus, "message::eos", (GCallback) message_cb, NULL);
gst_object_unref (bus);
g_object_set (src, "num-buffers", 5, NULL);
if (comp) {
/* set lower bound for ssim comparison, and allow slightly different caps */
g_object_set (compare, "method", 2, NULL);
g_object_set (compare, "meta", 3, NULL);
g_object_set (compare, "threshold", 0.90, NULL);
g_object_set (compare, "upper", FALSE, NULL);
}
GST_INFO ("possible caps to check %d", gst_caps_get_size (caps));
/* loop over all input and output combinations */
for (i = 0; i < gst_caps_get_size (caps); i++) {
for (j = 0; j < gst_caps_get_size (caps); j++) {
GstCaps *in_caps, *out_caps;
GstStructure *s;
guint32 fourcc;
in_caps = gst_caps_copy_nth (caps, i);
out_caps = gst_caps_copy_nth (caps, j);
/* FIXME remove if videotestsrc and video format handle these properly */
s = gst_caps_get_structure (in_caps, 0);
if (gst_structure_get_fourcc (s, "format", &fourcc)) {
if (fourcc == GST_MAKE_FOURCC ('Y', 'U', 'V', '9') ||
fourcc == GST_MAKE_FOURCC ('Y', 'V', 'U', '9') ||
fourcc == GST_MAKE_FOURCC ('v', '2', '1', '6')) {
gst_caps_unref (in_caps);
gst_caps_unref (out_caps);
continue;
}
}
GST_INFO ("checking conversion from %" GST_PTR_FORMAT " (%d)"
" to %" GST_PTR_FORMAT " (%d)", in_caps, i, out_caps, j);
g_object_set (filter1, "caps", in_caps, NULL);
g_object_set (filter2, "caps", out_caps, NULL);
fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING)
!= GST_STATE_CHANGE_FAILURE);
g_main_loop_run (loop);
fail_unless (gst_element_set_state (pipeline, GST_STATE_NULL)
== GST_STATE_CHANGE_SUCCESS);
gst_caps_unref (in_caps);
gst_caps_unref (out_caps);
}
}
gst_caps_unref (caps);
gst_object_unref (pipeline);
g_main_loop_unref (loop);
}
#define WIDTH 176
#define HEIGHT 120
GST_START_TEST (test_colorspace_compare)
{
colorspace_compare (WIDTH, HEIGHT, TRUE);
}
GST_END_TEST;
/* enable if you like stuff (ffmpegcolorspace) crashing */
#ifdef TEST_ODD
GST_START_TEST (test_colorspace_compare_odd_height)
{
colorspace_compare (WIDTH, HEIGHT + 1, TRUE);
}
GST_END_TEST;
GST_START_TEST (test_colorspace_compare_odd_width)
{
colorspace_compare (WIDTH + 1, HEIGHT, TRUE);
}
GST_END_TEST;
GST_START_TEST (test_colorspace_compare_odd)
{
colorspace_compare (WIDTH + 1, HEIGHT + 1, TRUE);
}
GST_END_TEST;
#endif
/* useful for crash and valgrind check */
GST_START_TEST (test_colorspace)
{
colorspace_compare (WIDTH + 1, HEIGHT + 1, FALSE);
}
GST_END_TEST;
static Suite *
colorspace_suite (void)
{
Suite *s = suite_create ("colorspace");
TCase *tc_chain;
tc_chain = tcase_create ("colorspace_compare");
tcase_add_test (tc_chain, test_colorspace_compare);
#ifdef TEST_ODD
tcase_add_test (tc_chain, test_colorspace_compare_odd_height);
tcase_add_test (tc_chain, test_colorspace_compare_odd_width);
tcase_add_test (tc_chain, test_colorspace_compare_odd);
#endif
tcase_add_test (tc_chain, test_colorspace);
suite_add_tcase (s, tc_chain);
/* test may take some time */
tcase_set_timeout (tc_chain, 600);
return s;
}
GST_CHECK_MAIN (colorspace)