All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH i-g-t v3 1/2] lib/igt_frame: Add support for analog frame comparison testing
Date: Wed, 19 Jul 2017 16:48:08 +0300	[thread overview]
Message-ID: <20170719134809.8446-2-paul.kocialkowski@linux.intel.com> (raw)
In-Reply-To: <20170719134809.8446-1-paul.kocialkowski@linux.intel.com>

This adds support for analog frame comparison check, as used in VGA.
Since VGA uses a DAC-ADC chain, its data cannot be expected to be pixel
perfect. Thus, it is impossible to uses a CRC check and full frames have
to be analyzed instead. Such an analysis is implemented, based on both
an absolute error threshold and a correlation with the expected error
trend for a DAC-ADC chain. It was tested with a couple encoders and
provides reliable error detection with few false positives.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
---
 configure.ac    |   1 +
 lib/Makefile.am |   2 +
 lib/igt_frame.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_frame.h |   2 +
 4 files changed, 136 insertions(+)

diff --git a/configure.ac b/configure.ac
index 5b41f333..db0015e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -178,6 +178,7 @@ if test x"$udev" = xyes; then
 	AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection])
 fi
 PKG_CHECK_MODULES(GLIB, glib-2.0)
+PKG_CHECK_MODULES(GSL, gsl)
 
 # for chamelium
 AC_ARG_ENABLE(chamelium, AS_HELP_STRING([--disable-chamelium],
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d4f41128..fb922ced 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -35,6 +35,7 @@ AM_CFLAGS = \
 	    $(DRM_CFLAGS) \
 	    $(PCIACCESS_CFLAGS) \
 	    $(LIBUNWIND_CFLAGS) \
+	    $(GSL_CFLAGS) \
 	    $(KMOD_CFLAGS) \
 	    $(PROCPS_CFLAGS) \
 	    $(DEBUG_CFLAGS) \
@@ -54,6 +55,7 @@ libintel_tools_la_LIBADD = \
 	$(DRM_LIBS) \
 	$(PCIACCESS_LIBS) \
 	$(PROCPS_LIBS) \
+	$(GSL_LIBS) \
 	$(KMOD_LIBS) \
 	$(CAIRO_LIBS) \
 	$(LIBUDEV_LIBS) \
diff --git a/lib/igt_frame.c b/lib/igt_frame.c
index dfafe53d..222a45f8 100644
--- a/lib/igt_frame.c
+++ b/lib/igt_frame.c
@@ -29,6 +29,8 @@
 #include <fcntl.h>
 #include <pixman.h>
 #include <cairo.h>
+#include <gsl/gsl_statistics_double.h>
+#include <gsl/gsl_fit.h>
 
 #include "igt.h"
 
@@ -135,3 +137,132 @@ void igt_write_compared_frames_to_png(cairo_surface_t *reference,
 
 	close(fd);
 }
+
+/**
+ * igt_check_analog_frame_match:
+ * @reference: The reference cairo surface
+ * @capture: The captured cairo surface
+ *
+ * Checks that the analog image contained in the chamelium frame dump matches
+ * the given framebuffer.
+ *
+ * In order to determine whether the frame matches the reference, the following
+ * reasoning is implemented:
+ * 1. The absolute error for each color value of the reference is collected.
+ * 2. The average absolute error is calculated for each color value of the
+ *    reference and must not go above 60 (23.5 % of the total range).
+ * 3. A linear fit for the average absolute error from the pixel value is
+ *    calculated, as a DAC-ADC chain is expected to have a linear error curve.
+ * 4. The linear fit is correlated with the actual average absolute error for
+ *    the frame and the correlation coefficient is checked to be > 0.985,
+ *    indicating a match with the expected error trend.
+ *
+ * Most errors (e.g. due to scaling, rotation, color space, etc) can be
+ * reliably detected this way, with a minimized number of false-positives.
+ * However, the brightest values (250 and up) are ignored as the error trend
+ * is often not linear there in practice due to clamping.
+ *
+ * Returns: a boolean indicating whether the frames match
+ */
+
+bool igt_check_analog_frame_match(cairo_surface_t *reference,
+				  cairo_surface_t *capture)
+{
+	pixman_image_t *reference_src, *capture_src;
+	int w, h;
+	int error_count[3][256][2] = { 0 };
+	double error_average[4][250];
+	double error_trend[250];
+	double c0, c1, cov00, cov01, cov11, sumsq;
+	double correlation;
+	unsigned char *reference_pixels, *capture_pixels;
+	unsigned char *p;
+	unsigned char *q;
+	bool match = true;
+	int diff;
+	int x, y;
+	int i, j;
+
+	w = cairo_image_surface_get_width(reference);
+	h = cairo_image_surface_get_height(reference);
+
+	reference_src = pixman_image_create_bits(
+	    PIXMAN_x8r8g8b8, w, h,
+	    (void*)cairo_image_surface_get_data(reference),
+	    cairo_image_surface_get_stride(reference));
+	reference_pixels = (unsigned char *) pixman_image_get_data(reference_src);
+
+	capture_src = pixman_image_create_bits(
+	    PIXMAN_x8r8g8b8, w, h,
+	    (void*)cairo_image_surface_get_data(capture),
+	    cairo_image_surface_get_stride(capture));
+	capture_pixels = (unsigned char *) pixman_image_get_data(capture_src);
+
+	/* Collect the absolute error for each color value */
+	for (x = 0; x < w; x++) {
+		for (y = 0; y < h; y++) {
+			p = &capture_pixels[(x + y * w) * 4];
+			q = &reference_pixels[(x + y * w) * 4];
+
+			for (i = 0; i < 3; i++) {
+				diff = (int) p[i] - q[i];
+				if (diff < 0)
+					diff = -diff;
+
+				error_count[i][q[i]][0] += diff;
+				error_count[i][q[i]][1]++;
+			}
+		}
+	}
+
+	/* Calculate the average absolute error for each color value */
+	for (i = 0; i < 250; i++) {
+		error_average[0][i] = i;
+
+		for (j = 1; j < 4; j++) {
+			error_average[j][i] = (double) error_count[j-1][i][0] /
+					      error_count[j-1][i][1];
+
+			if (error_average[j][i] > 60) {
+				igt_warn("Error average too high (%f)\n",
+					 error_average[j][i]);
+
+				match = false;
+				goto complete;
+			}
+		}
+	}
+
+	/*
+	 * Calculate error trend from linear fit.
+	 * A DAC-ADC chain is expected to have a linear absolute error on
+	 * most of its range
+	 */
+	for (i = 1; i < 4; i++) {
+		gsl_fit_linear((const double *) &error_average[0], 1,
+			       (const double *) &error_average[i], 1, 250,
+			       &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
+
+		for (j = 0; j < 250; j++)
+			error_trend[j] = c0 + j * c1;
+
+		correlation = gsl_stats_correlation((const double *) &error_trend,
+						    1,
+						    (const double *) &error_average[i],
+						    1, 250);
+
+		if (correlation < 0.985) {
+			igt_warn("Error with reference not correlated (%f)\n",
+				 correlation);
+
+			match = false;
+			goto complete;
+		}
+	}
+
+complete:
+	pixman_image_unref(reference_src);
+	pixman_image_unref(capture_src);
+
+	return match;
+}
diff --git a/lib/igt_frame.h b/lib/igt_frame.h
index ec6a1643..1d9bbf6a 100644
--- a/lib/igt_frame.h
+++ b/lib/igt_frame.h
@@ -39,5 +39,7 @@ void igt_write_compared_frames_to_png(cairo_surface_t *reference,
 				      cairo_surface_t *capture,
 				      const char *reference_suffix,
 				      const char *capture_suffix);
+bool igt_check_analog_frame_match(cairo_surface_t *reference,
+				  cairo_surface_t *capture);
 
 #endif
-- 
2.13.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2017-07-19 13:48 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-06 13:26 [PATCH i-g-t 0/1] chamelium: Add support for VGA frame comparison testing Paul Kocialkowski
2017-07-06 13:26 ` [PATCH i-g-t] " Paul Kocialkowski
2017-07-12 14:57 ` [PATCH i-g-t v2 0/2] Analogue/VGA frame comparison support Paul Kocialkowski
2017-07-12 14:57   ` [PATCH i-g-t v2 1/2] lib/igt_frame: Add support for analogue frame comparison testing Paul Kocialkowski
2017-07-12 14:57   ` [PATCH i-g-t v2 2/2] chamelium: Add support for VGA " Paul Kocialkowski
2017-07-17 17:35     ` Lyude Paul
2017-07-19 12:31       ` Paul Kocialkowski
2017-07-17 17:38 ` [PATCH i-g-t 0/1] " Lyude Paul
2017-07-19 13:48 ` [PATCH i-g-t v3 0/2] Analogue/VGA frame comparison support Paul Kocialkowski
2017-07-19 13:48   ` Paul Kocialkowski [this message]
2017-07-19 13:48   ` [PATCH i-g-t v3 2/2] chamelium: Add support for VGA frame comparison testing Paul Kocialkowski
2017-07-19 17:50   ` [PATCH i-g-t v3 0/2] Analogue/VGA frame comparison support Lyude Paul
2017-07-20 15:15     ` Paul Kocialkowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170719134809.8446-2-paul.kocialkowski@linux.intel.com \
    --to=paul.kocialkowski@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.