summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2016-05-16 21:55:52 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2016-05-19 16:55:07 +0300
commit62f0b16f639a9ecb116a79819655bdf44e269443 (patch)
treef66dc07c616b3f387f3ec941537e840fce261322
Initial commit
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--Makefile12
-rw-r--r--README57
-rw-r--r--data/Makefile12
-rw-r--r--data/frames/.gitignore1
-rw-r--r--data/frames/Makefile9
-rw-r--r--data/frames/frame-reference-1024x768.rgb.gzbin0 -> 21213 bytes
-rw-r--r--data/frames/frame-reference-1024x768.yuv.gzbin0 -> 12518 bytes
-rw-r--r--data/frames/frame-reference-640x480.rgb.gzbin0 -> 9581 bytes
-rw-r--r--data/frames/frame-reference-640x480.yuv.gzbin0 -> 7016 bytes
-rw-r--r--data/frames/frame-scaled-1024x768.rgb.gzbin0 -> 63035 bytes
-rw-r--r--data/frames/frame-scaled-1024x768.yuv.gzbin0 -> 51094 bytes
-rw-r--r--data/frames/frame-scaled-640x480.rgb.gzbin0 -> 16703 bytes
-rw-r--r--data/frames/frame-scaled-640x480.yuv.gzbin0 -> 13513 bytes
-rwxr-xr-xdata/frames/gen-frames.py350
-rw-r--r--scripts/Makefile8
-rwxr-xr-xscripts/histo2png.py81
-rwxr-xr-xscripts/logger.sh11
-rwxr-xr-xscripts/vsp-lib.sh441
-rwxr-xr-xscripts/vsp-runner.sh135
-rw-r--r--tests/Makefile8
-rwxr-xr-xtests/vsp-unit-test-0001.sh36
-rwxr-xr-xtests/vsp-unit-test-0002.sh36
-rwxr-xr-xtests/vsp-unit-test-0003.sh40
-rwxr-xr-xtests/vsp-unit-test-0004.sh37
-rwxr-xr-xtests/vsp-unit-test-0005.sh62
-rwxr-xr-xtests/vsp-unit-test-0006.sh44
-rwxr-xr-xtests/vsp-unit-test-0007.sh43
-rwxr-xr-xtests/vsp-unit-test-0008.sh49
28 files changed, 1472 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4e4a02d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+SUBDIRS=data scripts tests
+
+recursive=all clean install
+
+all:
+
+$(recursive):
+ @target=$@ ; \
+ for subdir in $(SUBDIRS); do \
+ echo "Making $$target in $$subdir" ; \
+ $(MAKE) -C $$subdir $$target; \
+ done
diff --git a/README b/README
new file mode 100644
index 0000000..f551b4d
--- /dev/null
+++ b/README
@@ -0,0 +1,57 @@
+vsp-tests
+---------
+
+Test suite for the Renesas R-Car VSP1 and VSP2 video processing engines.
+
+You can find the latest version of vsp-tests in the project's git tree at
+
+ git://git.ideasonboard.com/renesas/vsp-tests.git
+ http://git.ideasonboard.com/renesas/vsp-tests.git
+
+
+--------
+Building
+--------
+
+The vsp-tests suite requires the following tools to be installed on the host
+to generate the test script and test data.
+
+* make
+* python
+
+After installing the needed packages, you can build the test suite by running
+
+ make
+
+in the vsp-tests root directory. Then, to install the test suite, run
+
+ make install INSTALL_DIR=/path/to/target/directory
+
+This will copy the test scripts and data to the target directory to be copied
+or exported to the host. As test data take more than 200MB of disk space usage
+of nfsroot is recommended to run the tests.
+
+
+--------------------
+Runtime Dependencies
+--------------------
+
+The tests scripts require the following tools to be installed on the target
+system in a directory included in $PATH.
+
+* compare (part of ImageMagick)
+* media-ctl (part of v4l-utils, available at git://linuxtv.org/v4l-utils.git)
+* raw2rgbpnm (available at git://git.retiisi.org.uk/~sailus/raw2rgbpnm.git)
+* yavta (available at git://git.ideasonboard.org/yavta.git)
+
+All but the HGO test can be run with the latest version of these tools. To
+test the HGO, the 'metadata' branch of 'yavta' is currently needed.
+
+
+-----------------
+Running the Tests
+-----------------
+
+The test scripts are named vsp-unit-test-[0-9]*.sh. They can be run directly
+from the test suite root directory.
+
diff --git a/data/Makefile b/data/Makefile
new file mode 100644
index 0000000..768a346
--- /dev/null
+++ b/data/Makefile
@@ -0,0 +1,12 @@
+SUBDIRS=frames
+
+recursive=all clean install
+
+all:
+
+$(recursive):
+ @target=$@ ; \
+ for subdir in $(SUBDIRS); do \
+ echo "Making $$target in $$subdir" ; \
+ $(MAKE) -C $$subdir $$target; \
+ done
diff --git a/data/frames/.gitignore b/data/frames/.gitignore
new file mode 100644
index 0000000..a8a0dce
--- /dev/null
+++ b/data/frames/.gitignore
@@ -0,0 +1 @@
+*.bin
diff --git a/data/frames/Makefile b/data/frames/Makefile
new file mode 100644
index 0000000..326e447
--- /dev/null
+++ b/data/frames/Makefile
@@ -0,0 +1,9 @@
+all:
+ @./gen-frames.py
+
+clean:
+ @rm *.bin
+
+install:
+ mkdir -p $(INSTALL_DIR)/frames/
+ cp frame-reference-*.bin $(INSTALL_DIR)/frames/
diff --git a/data/frames/frame-reference-1024x768.rgb.gz b/data/frames/frame-reference-1024x768.rgb.gz
new file mode 100644
index 0000000..480239c
--- /dev/null
+++ b/data/frames/frame-reference-1024x768.rgb.gz
Binary files differ
diff --git a/data/frames/frame-reference-1024x768.yuv.gz b/data/frames/frame-reference-1024x768.yuv.gz
new file mode 100644
index 0000000..55d3e7a
--- /dev/null
+++ b/data/frames/frame-reference-1024x768.yuv.gz
Binary files differ
diff --git a/data/frames/frame-reference-640x480.rgb.gz b/data/frames/frame-reference-640x480.rgb.gz
new file mode 100644
index 0000000..7c5bd16
--- /dev/null
+++ b/data/frames/frame-reference-640x480.rgb.gz
Binary files differ
diff --git a/data/frames/frame-reference-640x480.yuv.gz b/data/frames/frame-reference-640x480.yuv.gz
new file mode 100644
index 0000000..3f27be3
--- /dev/null
+++ b/data/frames/frame-reference-640x480.yuv.gz
Binary files differ
diff --git a/data/frames/frame-scaled-1024x768.rgb.gz b/data/frames/frame-scaled-1024x768.rgb.gz
new file mode 100644
index 0000000..fba101d
--- /dev/null
+++ b/data/frames/frame-scaled-1024x768.rgb.gz
Binary files differ
diff --git a/data/frames/frame-scaled-1024x768.yuv.gz b/data/frames/frame-scaled-1024x768.yuv.gz
new file mode 100644
index 0000000..d3c3aae
--- /dev/null
+++ b/data/frames/frame-scaled-1024x768.yuv.gz
Binary files differ
diff --git a/data/frames/frame-scaled-640x480.rgb.gz b/data/frames/frame-scaled-640x480.rgb.gz
new file mode 100644
index 0000000..08c1be8
--- /dev/null
+++ b/data/frames/frame-scaled-640x480.rgb.gz
Binary files differ
diff --git a/data/frames/frame-scaled-640x480.yuv.gz b/data/frames/frame-scaled-640x480.yuv.gz
new file mode 100644
index 0000000..821919f
--- /dev/null
+++ b/data/frames/frame-scaled-640x480.yuv.gz
Binary files differ
diff --git a/data/frames/gen-frames.py b/data/frames/gen-frames.py
new file mode 100755
index 0000000..4742793
--- /dev/null
+++ b/data/frames/gen-frames.py
@@ -0,0 +1,350 @@
+#!/usr/bin/python
+
+import copy
+import glob
+import gzip
+import itertools
+import operator
+import re
+import struct
+import sys
+
+class FormatRGB:
+ def __init__(self, name, mapping):
+ self.name = name
+ self.mapping = copy.copy(mapping)
+ self.depth = sum(v[1] for v in mapping.values())
+
+ if self.mapping.has_key('a'):
+ self.alpha_bits = self.mapping['a'][1]
+ elif self.mapping.has_key('x'):
+ self.alpha_bits = self.mapping['x'][1]
+ else:
+ self.alpha_bits = 0
+
+ def alpha(self, alpha):
+ if self.mapping.has_key('a'):
+ return (alpha >> (8 - self.mapping['a'][1])) << self.mapping['a'][0]
+ elif self.mapping.has_key('x'):
+ return (alpha >> (8 - self.mapping['x'][1])) << self.mapping['x'][0]
+ else:
+ return 0
+
+ def generate_8(self, width, height, rgb):
+ output = []
+ for i in xrange(width * height):
+ r, g, b = rgb[i]
+ pixel = ((r >> (8 - self.mapping['r'][1])) << self.mapping['r'][0]) \
+ | ((g >> (8 - self.mapping['g'][1])) << self.mapping['g'][0]) \
+ | ((b >> (8 - self.mapping['b'][1])) << self.mapping['b'][0])
+ output.append(struct.pack('B', pixel))
+ return ''.join(output)
+
+ def generate_16(self, width, height, rgb, alpha):
+ output = []
+ for i in xrange(width * height):
+ r, g, b = rgb[i]
+ pixel = ((r >> (8 - self.mapping['r'][1])) << self.mapping['r'][0]) \
+ | ((g >> (8 - self.mapping['g'][1])) << self.mapping['g'][0]) \
+ | ((b >> (8 - self.mapping['b'][1])) << self.mapping['b'][0]) \
+ | self.alpha(alpha)
+ output.append(struct.pack('<H', pixel))
+ return ''.join(output)
+
+ def generate_24(self, width, height, rgb):
+ output = []
+ for i in xrange(width * height):
+ r, g, b = rgb[i]
+ pixel = ((r >> (8 - self.mapping['r'][1])) << self.mapping['r'][0]) \
+ | ((g >> (8 - self.mapping['g'][1])) << self.mapping['g'][0]) \
+ | ((b >> (8 - self.mapping['b'][1])) << self.mapping['b'][0])
+ output.append(struct.pack('<I', pixel)[0:3])
+ return ''.join(output)
+
+ def generate_32(self, width, height, rgb, alpha):
+ output = []
+ for i in xrange(width * height):
+ r, g, b = rgb[i]
+ pixel = ((r >> (8 - self.mapping['r'][1])) << self.mapping['r'][0]) \
+ | ((g >> (8 - self.mapping['g'][1])) << self.mapping['g'][0]) \
+ | ((b >> (8 - self.mapping['b'][1])) << self.mapping['b'][0]) \
+ | self.alpha(alpha)
+ output.append(struct.pack('<I', pixel))
+ return ''.join(output)
+
+ def convert(self, width, height, rgb, alpha):
+ if self.depth == 8:
+ return self.generate_8(width, height, rgb)
+ elif self.depth == 16:
+ return self.generate_16(width, height, rgb, alpha)
+ elif self.depth == 24:
+ return self.generate_24(width, height, rgb)
+ elif self.depth == 32:
+ return self.generate_32(width, height, rgb, alpha)
+ else:
+ raise RuntimeError, 'Invalid depth %s' % self.depth
+
+ def bin(self, bins, val):
+ bins[val >> 2] += 1
+
+ def histogram(self, width, height, rgb):
+ rgb_min = [255, 255, 255]
+ rgb_max = [0, 0, 0]
+ rgb_sum = [0, 0, 0]
+ rgb_bins = [[0] * 64, [0] * 64, [0] * 64]
+
+ for i in xrange(width * height):
+ pixel = rgb[i]
+
+ rgb_min = map(min, pixel, rgb_min)
+ rgb_max = map(max, pixel, rgb_max)
+ rgb_sum = map(operator.add, pixel, rgb_sum)
+
+ map(self.bin, rgb_bins, pixel)
+
+ output = []
+ for i in xrange(len(rgb_min)):
+ output.append(struct.pack('BBBB', rgb_min[i], 0, rgb_max[i], 0))
+ output.append(struct.pack('<3I', *rgb_sum))
+ for i in xrange(len(rgb_bins)):
+ output.append(struct.pack('<64I', *rgb_bins[i]))
+
+ return ''.join(output)
+
+ def compose(self, ninputs, width, height, rgb):
+ output = [(0, 0, 0)] * (width * height)
+ offset = 50
+
+ for input in xrange(ninputs):
+ length = width - offset
+ for y in xrange(height - offset):
+ dst_offset = (y + offset) * width + offset
+ src_offset = y * width
+ output[dst_offset:dst_offset+length] = rgb[src_offset:src_offset+length]
+ offset += 50
+
+ return ''.join(chr(d) for d in list(itertools.chain.from_iterable(output)))
+
+
+class FormatYUVPacked:
+ def __init__(self, name, mapping):
+ self.name = name
+ self.mapping = copy.copy(mapping)
+
+ def convert(self, width, height, yuv):
+ output = []
+ for i in xrange(width * height / 2):
+ pixel = yuv[i*4:(i+1)*4]
+ pixel = (pixel[self.mapping[0]], pixel[self.mapping[1]],
+ pixel[self.mapping[2]], pixel[self.mapping[3]])
+ output.extend(pixel)
+ return ''.join(output)
+
+ def bin(self, bins, val):
+ bins[val >> 2] += 1
+
+ def histogram(self, width, height, yuv):
+ vyu_min = [255, 255, 255]
+ vyu_max = [0, 0, 0]
+ vyu_sum = [0, 0, 0]
+ vyu_bins = [[0] * 64, [0] * 64, [0] * 64]
+
+ for y in xrange(height):
+ for x in xrange(width / 2):
+ offset = y * width * 2 + x * 4
+ u0 = ord(yuv[offset])
+ y0 = ord(yuv[offset+1])
+ v0 = ord(yuv[offset+2])
+ y1 = ord(yuv[offset+3])
+
+ if x != width / 2 - 1:
+ u2 = ord(yuv[offset+4])
+ v2 = ord(yuv[offset+6])
+ u1 = (u0 + u2) / 2
+ v1 = (v0 + v2) / 2
+ else:
+ u1 = u0
+ v1 = v1
+
+ for vyu in ((v0, y0, u0), (v1, y1, u1)):
+ vyu_min = map(min, vyu, vyu_min)
+ vyu_max = map(max, vyu, vyu_max)
+ vyu_sum = map(operator.add, vyu, vyu_sum)
+
+ map(self.bin, vyu_bins, vyu)
+
+ output = []
+ for i in xrange(len(vyu_min)):
+ output.append(struct.pack('BBBB', vyu_min[i], 0, vyu_max[i], 0))
+ output.append(struct.pack('<3I', *vyu_sum))
+ for i in xrange(len(vyu_bins)):
+ output.append(struct.pack('<64I', *vyu_bins[i]))
+
+ return ''.join(output)
+
+ def compose(self, ninputs, width, height, yuv):
+ output = ['\0'] * (width * height * 2)
+ offset = 50
+
+ for input in xrange(ninputs):
+ length = (width - offset) * 2
+ for y in xrange(height - offset):
+ dst_offset = ((y + offset) * width + offset) * 2
+ src_offset = y * width * 2
+ output[dst_offset:dst_offset+length] = yuv[src_offset:src_offset+length]
+ offset += 50
+
+ return ''.join(output)
+
+
+class FormatNV:
+ def __init__(self, name, hsub, vsub, mapping):
+ self.name = name
+ self.hsub = hsub
+ self.vsub = vsub
+ self.mapping = copy.copy(mapping)
+
+ def convert(self, width, height, yuv):
+ output = []
+
+ for i in xrange(width * height):
+ output.append(yuv[2*i+1])
+
+ for y in xrange(height / self.vsub):
+ for x in xrange(width / 2):
+ offset = (y * self.vsub * width * 2) + x * 4
+ uv = (yuv[offset], yuv[offset+2])
+ uv = (uv[self.mapping[0]], uv[self.mapping[1]])
+ output.extend(uv)
+
+ return ''.join(output)
+
+
+class FormatYUVPlanar:
+ def __init__(self, name, hsub, vsub, mapping):
+ self.name = name
+ self.hsub = hsub
+ self.vsub = vsub
+ self.mapping = copy.copy(mapping)
+
+ def convert(self, width, height, yuv):
+ output = []
+
+ for i in xrange(width * height):
+ output.append(yuv[2*i+1])
+
+ for y in xrange(height / self.vsub):
+ for x in xrange(width / 2):
+ offset = (y * self.vsub * width * 2) + x * 4
+ u = yuv[offset + self.mapping[0] * 2]
+ output.append(u)
+
+ for y in xrange(height / self.vsub):
+ for x in xrange(width / 2):
+ offset = (y * self.vsub * width * 2) + x * 4
+ v = yuv[offset + self.mapping[1] * 2]
+ output.append(v)
+
+ return ''.join(output)
+
+
+formats_rgb = {
+ 'rgb332': FormatRGB('rgb332', {'r': (5, 3), 'g': (2, 3), 'b': (0, 2)}),
+ 'rgb565': FormatRGB('rgb565', {'r': (11, 5), 'g': (5, 6), 'b': (0, 5)}),
+ 'bgr24': FormatRGB('bgr24', {'r': (16, 8), 'g': (8, 8), 'b': (0, 8)}),
+ 'rgb24': FormatRGB('rgb24', {'r': (0, 8), 'g': (8, 8), 'b': (16, 8)}),
+}
+
+formats_argb = {
+ 'argb555': FormatRGB('argb555', {'a': (15, 1), 'r': (10, 5), 'g': (5, 5), 'b': (0, 5)}),
+ 'xrgb555': FormatRGB('xrgb555', {'x': (15, 1), 'r': (10, 5), 'g': (5, 5), 'b': (0, 5)}),
+ 'abgr32': FormatRGB('abgr32', {'a': (24, 8), 'r': (16, 8), 'g': (8, 8), 'b': (0, 8)}),
+ 'argb32': FormatRGB('argb32', {'a': (0, 8), 'r': (8, 8), 'g': (16, 8), 'b': (24, 8)}),
+ 'xbgr32': FormatRGB('xbgr32', {'x': (24, 8), 'r': (16, 8), 'g': (8, 8), 'b': (0, 8)}),
+ 'xrgb32': FormatRGB('xrgb32', {'x': (0, 8), 'r': (8, 8), 'g': (16, 8), 'b': (24, 8)}),
+}
+
+formats_yuv = {
+ 'uyvy': FormatYUVPacked('uyvy', (0, 1, 2, 3)),
+ 'vyuy': FormatYUVPacked('vyuy', (2, 1, 0, 3)),
+ 'yuyv': FormatYUVPacked('yuyv', (1, 0, 3, 2)),
+ 'yvyu': FormatYUVPacked('yvyu', (1, 2, 3, 0)),
+ 'nv12m': FormatNV('nv12m', 2, 2, (0, 1)),
+ 'nv21m': FormatNV('nv21m', 2, 2, (1, 0)),
+ 'nv16m': FormatNV('nv16m', 2, 1, (0, 1)),
+ 'nv61m': FormatNV('nv61m', 2, 1, (1, 0)),
+ 'yuv420m': FormatYUVPlanar('yuv420m', 2, 2, (0, 1)),
+}
+
+resolutions = ((640, 480), (1024, 768))
+
+def main(argv):
+ re_fname = re.compile('frame-([a-z]*)-([0-9]*)x([0-9]*).([a-z]*).gz')
+
+ for fname in glob.glob('*.gz'):
+ match = re_fname.match(fname)
+ if not match:
+ continue
+
+ typ = match.group(1)
+ res = (int(match.group(2)), int(match.group(3)))
+ fmt = match.group(4)
+
+ if fmt == 'rgb':
+ rgb = gzip.open(fname, 'rb').read()
+ rgb = [struct.unpack('BBB', rgb[i*3:(i+1)*3]) for i in xrange(len(rgb) / 3)]
+
+ for format in formats_rgb.values():
+ bin_fname = 'frame-%s-%s-%ux%u.bin' % (typ, format.name, res[0], res[1])
+ print 'Generating %s' % bin_fname
+ bin = format.convert(res[0], res[1], rgb, 0)
+ file(bin_fname, 'wb').write(bin)
+
+ for format in formats_argb.values():
+ for alpha in (0, 100, 200, 255):
+ if format.alpha_bits == 1 and alpha not in (0, 255):
+ continue
+ bin_fname = 'frame-%s-%s-%ux%u-alpha%u.bin' % (typ, format.name, res[0], res[1], alpha)
+ print 'Generating %s' % bin_fname
+ bin = format.convert(res[0], res[1], rgb, alpha)
+ file(bin_fname, 'wb').write(bin)
+
+ format = formats_rgb['rgb24']
+
+ bin_fname = 'histo-%s-%s-%ux%u.bin' % (typ, format.name, res[0], res[1])
+ print 'Generating %s' % bin_fname
+ bin = format.histogram(res[0], res[1], rgb)
+ file(bin_fname, 'wb').write(bin)
+
+ if typ == 'reference' and res[0] == 1024 and res[1] == 768:
+ for ninputs in xrange(1, 6):
+ bin_fname = 'frame-composed-%u-%s-%ux%u.bin' % (ninputs, format.name, res[0], res[1])
+ print 'Generating %s' % bin_fname
+ bin = format.compose(ninputs, res[0], res[1], rgb)
+ file(bin_fname, 'wb').write(bin)
+
+ elif fmt == 'yuv':
+ yuv = gzip.open(fname, 'rb').read()
+
+ for format in formats_yuv.values():
+ bin_fname = 'frame-%s-%s-%ux%u.bin' % (typ, format.name, res[0], res[1])
+ print 'Generating %s' % bin_fname
+ bin = format.convert(res[0], res[1], yuv)
+ file(bin_fname, 'wb').write(bin)
+
+ format = formats_yuv['uyvy']
+ bin_fname = 'histo-%s-%s-%ux%u.bin' % (typ, format.name, res[0], res[1])
+ print 'Generating %s' % bin_fname
+ bin = format.histogram(res[0], res[1], yuv)
+ file(bin_fname, 'wb').write(bin)
+
+ if typ == 'reference' and res[0] == 1024 and res[1] == 768:
+ for ninputs in xrange(1, 6):
+ bin_fname = 'frame-composed-%u-%s-%ux%u.bin' % (ninputs, format.name, res[0], res[1])
+ print 'Generating %s' % bin_fname
+ bin = format.compose(ninputs, res[0], res[1], yuv)
+ file(bin_fname, 'wb').write(bin)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/scripts/Makefile b/scripts/Makefile
new file mode 100644
index 0000000..27bac1a
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,8 @@
+SCRIPTS=logger.sh vsp-lib.sh vsp1.sh
+
+all:
+
+clean:
+
+install:
+ cp $(SCRIPTS) $(INSTALL_DIR)/
diff --git a/scripts/histo2png.py b/scripts/histo2png.py
new file mode 100755
index 0000000..ff1da21
--- /dev/null
+++ b/scripts/histo2png.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+import matplotlib.pyplot as plt
+import struct
+import sys
+
+
+def usage(argv0):
+ print 'Usage: %s <histo.bin>' % argv0
+
+
+def main(argv):
+
+ if len(argv) != 2:
+ usage(argv[0])
+ return 1
+
+ data = file(argv[1], 'rb').read()
+
+ if len(data) == (2 + 64) * 4 or len(data) == (2 + 256) * 4:
+ maxmin = struct.unpack('<I', data[0:4])
+ sums = struct.unpack('<I', data[4:8])
+ histo = struct.unpack('<%uI' % (len(data[8:]) / 4), data[8:])
+
+ num_bins = len(histo);
+
+ title = 'min %u max %u sum %u' % \
+ ((maxmin[0] >> 0) & 0xff, (maxmin[0] >> 16) & 0xff, sums[0])
+
+ print 'pixels (%u)' % sum(histo)
+
+ plt.figure(figsize=(10, 10))
+ plt.xlim([0, num_bins])
+ plt.ylim([0, max(histo)])
+ plt.bar(range(num_bins), histo, color='r');
+
+ elif len(data) == (6 + 64 * 3) * 4:
+ maxmin = struct.unpack('<III', data[0:12])
+ sums = struct.unpack('<III', data[12:24])
+ histo = [struct.unpack('<I', data[24+i*4:24+i*4+4])[0] for i in xrange(len(data[24:])/4)]
+
+ num_bins = len(histo) / 3;
+
+ histo_r = histo[0:num_bins]
+ histo_g = histo[num_bins:2*num_bins]
+ histo_b = histo[num_bins*2:]
+
+ title = 'RGB min (%u,%u,%u) max (%u,%u,%u) sum (%u,%u,%u)' % \
+ ((maxmin[0] >> 0) & 0xff, (maxmin[1] >> 0) & 0xff, (maxmin[2] >> 0) & 0xff,
+ (maxmin[0] >> 16) & 0xff, (maxmin[1] >> 16) & 0xff, (maxmin[2] >> 16) & 0xff,
+ sums[0], sums[1], sums[2])
+
+ print 'pixels RGB (%u,%u,%u)' % (sum(histo_r), sum(histo_g), sum(histo_b))
+
+ plt.figure(figsize=(10, 20))
+ plt.subplot(3, 1, 1)
+ plt.xlim([0, num_bins])
+ plt.ylim([0, max(histo_r)])
+ plt.bar(range(num_bins), histo_r, color='r');
+ plt.subplot(3, 1, 2)
+ plt.xlim([0, num_bins])
+ plt.ylim([0, max(histo_g)])
+ plt.bar(range(num_bins), histo_g, color='g');
+ plt.subplot(3, 1, 3)
+ plt.xlim([0, num_bins])
+ plt.ylim([0, max(histo_b)])
+ plt.bar(range(num_bins), histo_b, color='b');
+
+ else:
+ print 'Invalid histogram length %u' % len(data)
+ return 1
+
+ plt.suptitle(title)
+ plt.savefig(argv[1].replace('bin', 'png'), dpi=72)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
+
diff --git a/scripts/logger.sh b/scripts/logger.sh
new file mode 100755
index 0000000..8123f0c
--- /dev/null
+++ b/scripts/logger.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+now() {
+ awk '/^now/ {time=$3; printf("[%u.%06u]", time / 1000000000, (time % 1000000000) / 1000) ; exit}' /proc/timer_list
+}
+
+label=${1:+ [$1]}
+
+while read line ; do
+ echo "$(now)$label $line"
+done
diff --git a/scripts/vsp-lib.sh b/scripts/vsp-lib.sh
new file mode 100755
index 0000000..4d3d166
--- /dev/null
+++ b/scripts/vsp-lib.sh
@@ -0,0 +1,441 @@
+#!/bin/sh
+
+mediactl='media-ctl'
+yavta='yavta'
+
+# ------------------------------------------------------------------------------
+# Miscellaneous
+#
+
+vsp1_device() {
+ $mediactl -d $mdev -p | grep 'bus info' | sed 's/.*platform://'
+}
+
+vsp1_has_feature() {
+ feature=$1
+
+ $mediactl -d $mdev -p | grep -q -- "- entity.*$feature"
+}
+
+vsp1_count_rpfs() {
+ $mediactl -d $mdev -p | grep -- '- entity.*rpf.[0-9] [^i]' | wc -l
+}
+
+vsp1_count_wpfs() {
+ $mediactl -d $mdev -p | grep -- '- entity.*wpf.[0-9] [^o]' | wc -l
+}
+
+vsp1_count_bru_inputs() {
+ num_pads=`media-ctl -p | grep 'entity.*bru' | sed 's/.*(\([0-9]\) pads.*/\1/'`
+ echo $((num_pads-1))
+}
+
+vsp1_entity_get_size() {
+ entity=$1
+ pad=$2
+
+ $mediactl -d $mdev --get-v4l2 "'$dev $entity':$pad" | grep fmt | \
+ sed 's/.*\/\([0-9x]*\).*/\1/'
+}
+
+# ------------------------------------------------------------------------------
+# Image and histogram comparison
+#
+
+#
+# Compare the two frames for exact match.
+#
+compare_frame_exact() {
+ img_a=$3
+ img_b=$4
+
+ match='fail'
+ diff -q $img_a $img_b > /dev/null && match='pass'
+
+ echo "Compared $img_a and $img_b: $match" | ./logger.sh check >> $logfile
+
+ if [ $match = 'pass' ] ; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+#
+# Compare the two frames using a fuzzy match algorithm to account for errors
+# introduced by the YUV packing. Accept a maximum 1% mean average error over
+# the whole frame with no more than 5% of the pixels differing.
+#
+compare_frame_fuzzy() {
+ fmt=$(echo $1 | sed 's/M$//')
+ size=$2
+ img_a=$3
+ img_b=$4
+
+ png_a=${img_a/bin/png}
+ png_b=${img_b/bin/png}
+
+ raw2rgbpnm -f $fmt -s $size $img_a $png_a > /dev/null
+ raw2rgbpnm -f $fmt -s $size $img_b $png_b > /dev/null
+
+ ae=$(compare -metric ae $png_a $png_b /dev/null 2>&1)
+ mae=$(compare -metric mae $png_a $png_b /dev/null 2>&1 | sed 's/.*(\(.*\))/\1/')
+
+ rm $png_a
+ rm $png_b
+
+ width=$(echo $size | cut -d 'x' -f 1)
+ height=$(echo $size | cut -d 'x' -f 2)
+
+ ae_match=$(echo $ae $width $height | awk '{ if ($1 / $2 / $3 < 0.05) { print "pass" } else { print "fail" } }')
+ mae_match=$(echo $mae | awk '{ if ($1 < 0.01) { print "pass" } else { print "fail" } }')
+
+ echo "Compared $img_a and $img_b: ae $ae ($ae_match) mae $mae ($mae_match)" | ./logger.sh check >> $logfile
+
+ if [ $ae_match = 'pass' -a $mae_match = 'pass' ] ; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+compare_frames() {
+ method=$1
+ reftype=$2
+ format=$3
+ wpf=$4
+
+ fmt=$(echo $format | tr '[:upper:]' '[:lower:]')
+ size=$(vsp1_entity_get_size wpf.$wpf 1)
+
+ case $format in
+ ARGB555)
+ reference="frame-$reftype-$fmt-$size-alpha255.bin"
+ ;;
+ ABGR32 | ARGB32)
+ reference="frame-$reftype-$fmt-$size-alpha200.bin"
+ ;;
+ XRGB555)
+ # XRGB555 has the X bit hardcoded to 0
+ reference="frame-$reftype-$fmt-$size-alpha0.bin"
+ ;;
+ XBGR32 | XRGB32)
+ # The X bits are configurable with a default value of 255
+ reference="frame-$reftype-$fmt-$size-alpha255.bin"
+ ;;
+ *)
+ reference="frame-$reftype-$fmt-$size.bin"
+ ;;
+ esac
+
+ result="pass"
+ for frame in frame-*.bin ; do
+ (compare_frame_$method $format $size $frame frames/$reference) || {
+ mv $frame ${0/.sh/}-${frame/.bin/-$reftype-$fmt-$size.bin} ;
+ result="fail"
+ }
+ done
+
+ echo $result
+}
+
+compare_histogram() {
+ histo_a=$1
+ histo_b=$2
+
+ match='fail'
+ diff -q $histo_a $histo_b > /dev/null && match='pass'
+
+ echo "Compared $histo_a and $histo_b: $match" | ./logger.sh check >> $logfile
+
+ if [ $match = 'pass' ] ; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+compare_histograms() {
+ format=$1
+ wpf=$2
+
+ fmt=$(echo $format | tr '[:upper:]' '[:lower:]')
+ size=$(vsp1_entity_get_size wpf.$wpf 1)
+ reference="histo-reference-$fmt-$size.bin"
+
+ result="pass"
+ for histo in histo-*.bin ; do
+ (compare_histogram $histo frames/$reference) || {
+ mv $histo ${0/.sh/}-${histo/.bin/-$fmt.bin} ;
+ result="fail"
+ }
+ done
+
+ echo $result
+}
+
+# ------------------------------------------------------------------------------
+# Pipeline configuration
+#
+
+pipe_none() {
+ # Nothing to be done
+ return
+}
+
+pipe_rpf_bru() {
+ ninputs=$1
+
+ bru_output=$(vsp1_count_bru_inputs)
+
+ for input in `seq 0 1 $((ninputs-1))` ; do
+ $mediactl -d $mdev -l "'$dev rpf.$input':1 -> '$dev bru':$input [1]"
+ done
+ $mediactl -d $mdev -l "'$dev bru':$bru_output -> '$dev wpf.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev wpf.0':1 -> '$dev wpf.0 output':0 [1]"
+}
+
+pipe_rpf_bru_uds() {
+ bru_output=$(vsp1_count_bru_inputs)
+
+ $mediactl -d $mdev -l "'$dev rpf.0':1 -> '$dev bru':0 [1]"
+ $mediactl -d $mdev -l "'$dev bru':$bru_output -> '$dev uds.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev uds.0':1 -> '$dev wpf.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev wpf.0':1 -> '$dev wpf.0 output':0 [1]"
+}
+
+pipe_rpf_hgo() {
+ $mediactl -d $mdev -l "'$dev rpf.0':1 -> '$dev wpf.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev rpf.0':1 -> '$dev hgo':0 [1]"
+ $mediactl -d $mdev -l "'$dev wpf.0':1 -> '$dev wpf.0 output':0 [1]"
+}
+
+pipe_rpf_uds() {
+ $mediactl -d $mdev -l "'$dev rpf.0':1 -> '$dev uds.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev uds.0':1 -> '$dev wpf.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev wpf.0':1 -> '$dev wpf.0 output':0 [1]"
+}
+
+pipe_rpf_uds_bru() {
+ bru_output=$(vsp1_count_bru_inputs)
+
+ $mediactl -d $mdev -l "'$dev rpf.0':1 -> '$dev uds.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev uds.0':1 -> '$dev bru':0 [1]"
+ $mediactl -d $mdev -l "'$dev bru':$bru_output -> '$dev wpf.0':0 [1]"
+ $mediactl -d $mdev -l "'$dev wpf.0':1 -> '$dev wpf.0 output':0 [1]"
+}
+
+pipe_rpf_wpf() {
+ rpf=$1
+ wpf=$2
+
+ $mediactl -d $mdev -l "'$dev rpf.$rpf':1 -> '$dev wpf.$wpf':0 [1]"
+ $mediactl -d $mdev -l "'$dev wpf.$wpf':1 -> '$dev wpf.$wpf output':0 [1]"
+}
+
+pipe_reset() {
+ $mediactl -d $mdev -r
+}
+
+pipe_configure() {
+ pipe=${1//-/_}
+ shift 1
+
+ pipe_reset
+ pipe_$pipe $*
+}
+
+# ------------------------------------------------------------------------------
+# Format Configuration
+#
+
+format_v4l2_to_mbus() {
+ case $1 in
+ RGB332 | ARGB555 | XRGB555 | RGB565 | BGR24 | RGB24 | XBGR32 | XRGB32 | ABGR32 | ARGB32)
+ echo "ARGB32";
+ ;;
+
+ NV12M | NV16M | NV21M | NV61M | UYVY | VYUY | YUV420M | YUYV | YVYU)
+ echo "AYUV32"
+ ;;
+
+ *)
+ echo "Invalid format $1" >&2
+ echo -e "Valid formats are
+\tRGB332, ARGB555, XRGB555, RGB565, BGR24, RGB24,
+\tXBGR32, XRGB32, ABGR32, ARGB32,
+\tNV12M, NV16M, NV21M, NV61M, UYVY, VYUY, YUV420M, YUYV, YVYU" >&2
+ exit 1
+ esac
+}
+
+format_rpf() {
+ format=$(format_v4l2_to_mbus $1)
+ size=$2
+ rpf=$3
+
+ $mediactl -d $mdev -V "'$dev rpf.$rpf':0 [fmt:$format/$size]"
+}
+
+format_rpf_bru() {
+ format=$(format_v4l2_to_mbus $1)
+ size=$2
+ ninputs=$3
+ offset=0
+
+ bru_output=$(vsp1_count_bru_inputs)
+
+ for input in `seq 0 1 $((ninputs-1))` ; do
+ offset=$((offset+50))
+ $mediactl -d $mdev -V "'$dev rpf.$input':0 [fmt:$format/$size]"
+ $mediactl -d $mdev -V "'$dev bru':$input [fmt:$format/$size compose:($offset,$offset)/$size]"
+ done
+
+ $mediactl -d $mdev -V "'$dev bru':$bru_output [fmt:$format/$size]"
+ $mediactl -d $mdev -V "'$dev wpf.0':0 [fmt:$format/$size]"
+ $mediactl -d $mdev -V "'$dev wpf.0':1 [fmt:$format/$size]"
+}
+
+format_rpf_bru_uds() {
+ infmt=$(format_v4l2_to_mbus $1)
+ insize=$2
+ outfmt=$(format_v4l2_to_mbus $3)
+ outsize=$4
+
+ bru_output=$(vsp1_count_bru_inputs)
+
+ $mediactl -d $mdev -V "'$dev rpf.0':0 [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev bru':0 [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev bru':$bru_output [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev uds.0':0 [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev uds.0':1 [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev wpf.0':0 [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev wpf.0':1 [fmt:$outfmt/$outsize]"
+}
+
+format_rpf_hgo() {
+ format=$(format_v4l2_to_mbus $1)
+ size=$2
+ crop=${3:+crop:$3}
+ compose=${4:+compose:$4}
+
+ $mediactl -d $mdev -V "'$dev rpf.0':0 [fmt:$format/$size]"
+ $mediactl -d $mdev -V "'$dev wpf.0':0 [fmt:$format/$size]"
+ $mediactl -d $mdev -V "'$dev wpf.0':1 [fmt:$format/$size]"
+ $mediactl -d $mdev -V "'$dev hgo':0 [fmt:$format/$size $crop $compose]"
+}
+
+format_rpf_uds() {
+ infmt=$(format_v4l2_to_mbus $1)
+ insize=$2
+ outfmt=$(format_v4l2_to_mbus $3)
+ outsize=$4
+
+ $mediactl -d $mdev -V "'$dev rpf.0':0 [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev uds.0':0 [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev uds.0':1 [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev wpf.0':0 [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev wpf.0':1 [fmt:$outfmt/$outsize]"
+}
+
+format_rpf_uds_bru() {
+ infmt=$(format_v4l2_to_mbus $1)
+ insize=$2
+ outfmt=$(format_v4l2_to_mbus $3)
+ outsize=$4
+
+ bru_output=$(vsp1_count_bru_inputs)
+
+ $mediactl -d $mdev -V "'$dev rpf.0':0 [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev uds.0':0 [fmt:$infmt/$insize]"
+ $mediactl -d $mdev -V "'$dev uds.0':1 [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev bru':0 [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev bru':$bru_output [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev wpf.0':0 [fmt:$infmt/$outsize]"
+ $mediactl -d $mdev -V "'$dev wpf.0':1 [fmt:$outfmt/$outsize]"
+}
+
+format_rpf_wpf() {
+ rpf=$1
+ wpf=$2
+ infmt=$(format_v4l2_to_mbus $3)
+ size=$4
+ outfmt=$(format_v4l2_to_mbus $5)
+ crop=$6
+
+ if [ x$crop != 'x' ] ; then
+ crop="crop:$crop"
+ outsize=$(echo $crop | sed 's/.*\///')
+ else
+ outsize=$size
+ fi
+
+ $mediactl -d $mdev -V "'$dev rpf.$rpf':0 [fmt:$infmt/$size]"
+ $mediactl -d $mdev -V "'$dev wpf.$wpf':0 [fmt:$infmt/$size $crop]"
+ $mediactl -d $mdev -V "'$dev wpf.$wpf':1 [fmt:$outfmt/$outsize]"
+}
+
+format_wpf() {
+ format=$(format_v4l2_to_mbus $1)
+ size=$2
+ wpf=$3
+
+ $mediactl -d $mdev -V "'$dev wpf.$wpf':0 [fmt:$format/$size]"
+ $mediactl -d $mdev -V "'$dev wpf.$wpf':1 [fmt:$format/$size]"
+}
+
+format_configure() {
+ pipe=${1//-/_}
+ shift 1
+
+ format_$pipe $*
+}
+
+# ------------------------------------------------------------------------------
+# Test run
+#
+
+test_init() {
+ logfile=${1/sh/log}
+ features=$2
+
+ rm -f $logfile
+ rm -f *.bin
+
+ for mdev in /dev/media* ; do
+ match='true'
+ for feature in $features ; do
+ $(vsp1_has_feature $feature) || {
+ match='false';
+ break;
+ }
+ done
+
+ if [ $match == 'true' ] ; then
+ break
+ fi
+ done
+
+ if [ $match == 'false' ] ; then
+ echo "No device found with feature set $features" | ./logger.sh config >> $logfile
+ exit 1
+ fi
+
+ dev=$(vsp1_device $mdev)
+ echo "Using device $mdev ($dev)" | ./logger.sh config >> $logfile
+
+ vsp_runner=./vsp-runner.sh
+}
+
+test_start() {
+ echo "Testing $1" | ./logger.sh >> $logfile
+ echo -n "Testing $1: " >&2
+}
+
+test_complete() {
+ echo "Done: $1" | ./logger.sh >> $logfile
+ echo $1 >&2
+
+ rm -f frame-*.bin
+ rm -f histo-*.bin
+}
diff --git a/scripts/vsp-runner.sh b/scripts/vsp-runner.sh
new file mode 100755
index 0000000..e92eda1
--- /dev/null
+++ b/scripts/vsp-runner.sh
@@ -0,0 +1,135 @@
+#!/bin/sh
+
+set -e
+
+source vsp-lib.sh
+
+mediactl='media-ctl'
+yavta='yavta'
+
+# ------------------------------------------------------------------------------
+# Format retrieval
+#
+
+frame_reference() {
+ format=$1
+ size=$2
+
+ lcfmt=`echo $infmt | tr '[:upper:]' '[:lower:]'`
+
+ case $format in
+ ARGB555)
+ echo "frames/frame-reference-$lcfmt-$size-alpha255.bin"
+ ;;
+ ABGR32 | ARGB32)
+ echo "frames/frame-reference-$lcfmt-$size-alpha200.bin"
+ ;;
+ XRGB555 | XBGR32 | XRGB32)
+ echo "frames/frame-reference-$lcfmt-$size-alpha0.bin"
+ ;;
+ *)
+ echo "frames/frame-reference-$lcfmt-$size.bin"
+ ;;
+ esac
+}
+
+# ------------------------------------------------------------------------------
+# Parse the command line and retrieve the formats
+#
+
+syntax() {
+ echo "Syntax: vsp-runner.sh dev cmd [...]"
+ echo ""
+ echo "Supported commands:"
+ echo " hgo [options]"
+ echo " input index infmt [options]"
+ echo " output index outfmt [options]"
+}
+
+parse() {
+ if [ $# -lt 2 ] ; then
+ syntax
+ return 1
+ fi
+
+ mdev=$1
+ dev=`$mediactl -d $mdev -p | grep 'bus info' | sed 's/.*platform://'`
+
+ if [ -z $dev ] ; then
+ echo "Error: Device $dev doesn't exist"
+ syntax
+ return 1
+ fi
+
+ cmd=$2
+
+ case $cmd in
+ hgo)
+ options=$3
+ ;;
+
+ input)
+ index=$3
+ infmt=$4
+ options=$5
+ ;;
+
+ output)
+ index=$3
+ outfmt=$4
+ options=$5
+ ;;
+
+ *)
+ echo "Invalid command $cmd"
+ ;;
+ esac
+}
+
+# ------------------------------------------------------------------------------
+# Execute the command
+#
+
+execute() {
+ case $cmd in
+ hgo)
+ if [ "x$options" = xinfinite ] ; then
+ $yavta -c -n 4 \
+ `$mediactl -d $mdev -e "$dev hgo histo"`
+ else
+ $yavta -c10 -n 10 --file=histo-#.bin $options \
+ `$mediactl -d $mdev -e "$dev hgo histo"`
+ fi
+ ;;
+
+ input)
+ rpf=rpf.$index
+ size=$(vsp1_entity_get_size $rpf 0)
+
+ file=$(frame_reference $infmt $size)
+
+ if [ "x$options" = xinfinite ] ; then
+ $yavta -c -n 4 -f $infmt -s $size --file=$file $options \
+ `$mediactl -d $mdev -e "$dev $rpf input"`
+ else
+ $yavta -c10 -n 4 -f $infmt -s $size --file=$file $options \
+ `$mediactl -d $mdev -e "$dev $rpf input"`
+ fi
+ ;;
+
+ output)
+ wpf=wpf.$index
+ size=$(vsp1_entity_get_size $wpf 1)
+
+ if [ "x$options" = xinfinite ] ; then
+ $yavta -c -n 4 -f $outfmt -s $size \
+ `$mediactl -d $mdev -e "$dev $wpf output"`
+ else
+ $yavta -c10 -n 4 -f $outfmt -s $size --skip 7 -F $options \
+ `$mediactl -d $mdev -e "$dev $wpf output"`
+ fi
+ ;;
+ esac
+}
+
+parse $* && execute
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..6586b29
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,8 @@
+SCRIPTS=$(wildcard *.sh)
+
+all:
+
+clean:
+
+install:
+ cp $(SCRIPTS) $(INSTALL_DIR)/
diff --git a/tests/vsp-unit-test-0001.sh b/tests/vsp-unit-test-0001.sh
new file mode 100755
index 0000000..2cb0cb3
--- /dev/null
+++ b/tests/vsp-unit-test-0001.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+#
+# Test WPF packing in RGB mode. Use a RPF -> WPF pipeline with a fixed ARGB32
+# format on the input and capture output frames in all RGB formats supported
+# by the WPF.
+#
+
+source vsp-lib.sh
+
+features="rpf.0 wpf.0"
+formats="RGB332 ARGB555 XRGB555 RGB565 BGR24 RGB24 ABGR32 ARGB32 XBGR32 XRGB32"
+
+test_wpf_packing() {
+ test_start "WPF packing in $format"
+
+ pipe_configure rpf-wpf 0 0 | ./logger.sh config >> $logfile
+ format_configure rpf-wpf 0 0 \
+ ARGB32 1024x768 $format | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev input 0 ARGB32 | ./logger.sh input.0 >> $logfile &
+ $vsp_runner $mdev output 0 $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_frames exact reference $format 0)
+
+ test_complete $result
+}
+
+test_run() {
+ for format in $formats ; do
+ test_wpf_packing $format
+ done
+}
+
+test_init $0 "$features"
+test_run
diff --git a/tests/vsp-unit-test-0002.sh b/tests/vsp-unit-test-0002.sh
new file mode 100755
index 0000000..e2602d8
--- /dev/null
+++ b/tests/vsp-unit-test-0002.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+#
+# Test WPF packing in YUV mode. Use a RPF -> WPF pipeline with a fixed YUYV
+# format on the input and capture output frames in all YUV formats supported
+# by the WPF.
+#
+
+source vsp-lib.sh
+
+features="rpf.0 wpf.0"
+formats="NV12M NV16M NV21M NV61M UYVY VYUY YUV420M YUYV YVYU"
+
+test_wpf_packing() {
+ test_start "WPF packing in $format"
+
+ pipe_configure rpf-wpf 0 0 | ./logger.sh config >> $logfile
+ format_configure rpf-wpf 0 0 \
+ YUYV 1024x768 $format | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev input 0 YUYV | ./logger.sh input.0 >> $logfile &
+ $vsp_runner $mdev output 0 $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_frames fuzzy reference $format 0)
+
+ test_complete $result
+}
+
+test_run() {
+ for format in $formats ; do
+ test_wpf_packing $format
+ done
+}
+
+test_init $0 "$features"
+test_run
diff --git a/tests/vsp-unit-test-0003.sh b/tests/vsp-unit-test-0003.sh
new file mode 100755
index 0000000..ff81509
--- /dev/null
+++ b/tests/vsp-unit-test-0003.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+#
+# Test downscaling and upscaling in RGB and YUV modes. Use a RPF -> UDS -> WPF
+# pipeline with identical input and output formats.
+#
+
+source vsp-lib.sh
+
+features="rpf.0 uds wpf.0"
+formats="RGB24 UYVY"
+
+test_scale() {
+ format=$1
+ insize=$2
+ outsize=$3
+
+ test_start "scaling from $insize to $outsize in $format"
+
+ pipe_configure rpf-uds | ./logger.sh config >> $logfile
+ format_configure rpf-uds \
+ $format $insize $format $outsize | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev input 0 $format | ./logger.sh input.0 >> $logfile &
+ $vsp_runner $mdev output 0 $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_frames exact scaled $format 0)
+
+ test_complete $result
+}
+
+test_run() {
+ for format in $formats ; do
+ test_scale $format 1024x768 640x480
+ test_scale $format 640x480 1024x768
+ done
+}
+
+test_init $0 "$features"
+test_run
diff --git a/tests/vsp-unit-test-0004.sh b/tests/vsp-unit-test-0004.sh
new file mode 100755
index 0000000..af5dfdb
--- /dev/null
+++ b/tests/vsp-unit-test-0004.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+#
+# Test 1D histogram generation. Use a RPF -> WPF pipeline with the HGO hooked
+# up at the RPF output.
+#
+
+source vsp-lib.sh
+
+features="hgo rpf.0 wpf.0"
+formats="RGB24 UYVY"
+
+test_histogram() {
+ test_start "histogram in $format"
+
+ pipe_configure rpf-hgo | ./logger.sh config >> $logfile
+ format_configure rpf-hgo \
+ $format 1024x768 | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev m2m-hgo $format $format | ./logger.sh config >> $logfile
+ $vsp_runner $mdev hgo | ./logger.sh hgo >> $logfile &
+ $vsp_runner $mdev input 0 $format | ./logger.sh input.0 >> $logfile &
+ $vsp_runner $mdev output 0 $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_histograms $format 0)
+
+ test_complete $result
+}
+
+test_run() {
+ for format in $formats ; do
+ test_histogram $format
+ done
+}
+
+test_init $0 "$features"
+test_run
diff --git a/tests/vsp-unit-test-0005.sh b/tests/vsp-unit-test-0005.sh
new file mode 100755
index 0000000..aeb0ca2
--- /dev/null
+++ b/tests/vsp-unit-test-0005.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+#
+# Test RPF -> WPF with all RPF and WPF instances in sequence. The format
+# doesn't matter much, use RGB24 to simplify frame comparison.
+#
+
+source vsp-lib.sh
+
+features="rpf.0 rpf.1 wpf.0 wpf.1"
+format=RGB24
+
+test_rpf() {
+ rpf=$1
+
+ test_start "RPF.$rpf"
+
+ pipe_configure rpf-wpf $rpf 0 | ./logger.sh config >> $logfile
+ format_configure rpf-wpf $rpf 0 \
+ $format 1024x768 $format | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev input $rpf $format | ./logger.sh input.0 >> $logfile &
+ $vsp_runner $mdev output 0 $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_frames exact reference $format 0)
+
+ test_complete $result
+}
+
+test_wpf() {
+ wpf=$1
+
+ test_start "WPF.$wpf"
+
+ pipe_configure rpf-wpf 0 $wpf | ./logger.sh config >> $logfile
+ format_configure rpf-wpf 0 $wpf \
+ $format 1024x768 $format | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev input 0 $format | ./logger.sh input.0 >> $logfile &
+ $vsp_runner $mdev output $wpf $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_frames exact reference $format $wpf)
+
+ test_complete $result
+}
+
+test_run() {
+ num_rpfs=$(vsp1_count_rpfs)
+ num_wpfs=$(vsp1_count_wpfs)
+
+ for rpf in `seq 0 1 $((num_rpfs-1))` ; do
+ test_rpf $rpf
+ done
+
+ # Skip WPF.0, it has already been tested during the RPF tests.
+ for wpf in `seq $((num_wpfs-1))` ; do
+ test_wpf $wpf
+ done
+}
+
+test_init $0 "$features"
+test_run
diff --git a/tests/vsp-unit-test-0006.sh b/tests/vsp-unit-test-0006.sh
new file mode 100755
index 0000000..0ae4259
--- /dev/null
+++ b/tests/vsp-unit-test-0006.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+#
+# Test invalid pipelines, without an RPF or without a WPF.
+#
+
+source vsp-lib.sh
+
+features="rpf.0 wpf.0"
+format=RGB24
+
+test_no_rpf() {
+ test_start "invalid pipeline with no RPF"
+
+ pipe_configure none | ./logger.sh config >> $logfile
+ format_configure wpf \
+ $format 1024x768 0 | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev output 0 $format | ./logger.sh input.0 >> $logfile
+
+ # The test always passes if the kernel doesn't crash
+ test_complete pass
+}
+
+test_no_wpf() {
+ test_start "invalid pipeline with no WPF"
+
+ pipe_configure none | ./logger.sh config >> $logfile
+ format_configure rpf \
+ $format 1024x768 0 | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev input 0 $format | ./logger.sh input.0 >> $logfile
+
+ # The test always passes if the kernel doesn't crash
+ test_complete pass
+}
+
+test_run() {
+ test_no_rpf
+ test_no_wpf
+}
+
+test_init $0 "$features"
+test_run
diff --git a/tests/vsp-unit-test-0007.sh b/tests/vsp-unit-test-0007.sh
new file mode 100755
index 0000000..c124c29
--- /dev/null
+++ b/tests/vsp-unit-test-0007.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+#
+# Test composition through the BRU in RGB and YUV formats.
+#
+
+source vsp-lib.sh
+
+features="rpf.0 rpf.1 bru wpf.0"
+formats="RGB24 UYVY"
+
+test_bru() {
+ format=$1
+ ninputs=$2
+
+ test_start "BRU in $format with $ninputs inputs"
+
+ pipe_configure rpf-bru $ninputs | ./logger.sh config >> $logfile
+ format_configure rpf-bru \
+ $format 1024x768 $ninputs | ./logger.sh config >> $logfile
+
+ for input in `seq 0 1 $((ninputs-1))` ; do
+ $vsp_runner $mdev input $input $format | ./logger.sh input.$input >> $logfile &
+ done
+ $vsp_runner $mdev output 0 $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_frames fuzzy composed-$ninputs $format 0)
+
+ test_complete $result
+}
+
+test_run() {
+ max_inputs=$(vsp1_count_bru_inputs)
+
+ for format in $formats ; do
+ for ninputs in `seq $max_inputs` ; do
+ test_bru $format $ninputs
+ done
+ done
+}
+
+test_init $0 "$features"
+test_run
diff --git a/tests/vsp-unit-test-0008.sh b/tests/vsp-unit-test-0008.sh
new file mode 100755
index 0000000..b3b0510
--- /dev/null
+++ b/tests/vsp-unit-test-0008.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+#
+# Test downscaling and upscaling in RGB and YUV modes with a BRU inserted in
+# the pipeline, both before and after the scaler.
+#
+
+source vsp-lib.sh
+
+features="bru rpf.0 uds wpf.0"
+formats="RGB24 UYVY"
+
+test_scale() {
+ format=$1
+ insize=$2
+ outsize=$3
+ order=$4
+
+ if [ $order = 'after' ] ; then
+ pipe=rpf-bru-uds
+ else
+ pipe=rpf-uds-bru
+ fi
+
+ test_start "scaling from $insize to $outsize in $format $order BRU"
+
+ pipe_configure $pipe | ./logger.sh config >> $logfile
+ format_configure $pipe \
+ $format $insize $format $outsize | ./logger.sh config >> $logfile
+
+ $vsp_runner $mdev input 0 $format | ./logger.sh input.0 >> $logfile &
+ $vsp_runner $mdev output 0 $format | ./logger.sh output.0 >> $logfile
+
+ result=$(compare_frames exact scaled $format 0)
+
+ test_complete $result
+}
+
+test_run() {
+ for format in $formats ; do
+ test_scale $format 1024x768 640x480 before
+ test_scale $format 640x480 1024x768 before
+ test_scale $format 1024x768 640x480 after
+ test_scale $format 640x480 1024x768 after
+ done
+}
+
+test_init $0 "$features"
+test_run