Initial commit
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Mon, 16 May 2016 18:55:52 +0000 (21:55 +0300)
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Thu, 19 May 2016 13:55:07 +0000 (16:55 +0300)
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
28 files changed:
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
data/Makefile [new file with mode: 0644]
data/frames/.gitignore [new file with mode: 0644]
data/frames/Makefile [new file with mode: 0644]
data/frames/frame-reference-1024x768.rgb.gz [new file with mode: 0644]
data/frames/frame-reference-1024x768.yuv.gz [new file with mode: 0644]
data/frames/frame-reference-640x480.rgb.gz [new file with mode: 0644]
data/frames/frame-reference-640x480.yuv.gz [new file with mode: 0644]
data/frames/frame-scaled-1024x768.rgb.gz [new file with mode: 0644]
data/frames/frame-scaled-1024x768.yuv.gz [new file with mode: 0644]
data/frames/frame-scaled-640x480.rgb.gz [new file with mode: 0644]
data/frames/frame-scaled-640x480.yuv.gz [new file with mode: 0644]
data/frames/gen-frames.py [new file with mode: 0755]
scripts/Makefile [new file with mode: 0644]
scripts/histo2png.py [new file with mode: 0755]
scripts/logger.sh [new file with mode: 0755]
scripts/vsp-lib.sh [new file with mode: 0755]
scripts/vsp-runner.sh [new file with mode: 0755]
tests/Makefile [new file with mode: 0644]
tests/vsp-unit-test-0001.sh [new file with mode: 0755]
tests/vsp-unit-test-0002.sh [new file with mode: 0755]
tests/vsp-unit-test-0003.sh [new file with mode: 0755]
tests/vsp-unit-test-0004.sh [new file with mode: 0755]
tests/vsp-unit-test-0005.sh [new file with mode: 0755]
tests/vsp-unit-test-0006.sh [new file with mode: 0755]
tests/vsp-unit-test-0007.sh [new file with mode: 0755]
tests/vsp-unit-test-0008.sh [new file with mode: 0755]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
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 (file)
index 0000000..768a346
--- /dev/null
@@ -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 (file)
index 0000000..a8a0dce
--- /dev/null
@@ -0,0 +1 @@
+*.bin
diff --git a/data/frames/Makefile b/data/frames/Makefile
new file mode 100644 (file)
index 0000000..326e447
--- /dev/null
@@ -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 (file)
index 0000000..480239c
Binary files /dev/null and b/data/frames/frame-reference-1024x768.rgb.gz differ
diff --git a/data/frames/frame-reference-1024x768.yuv.gz b/data/frames/frame-reference-1024x768.yuv.gz
new file mode 100644 (file)
index 0000000..55d3e7a
Binary files /dev/null and b/data/frames/frame-reference-1024x768.yuv.gz differ
diff --git a/data/frames/frame-reference-640x480.rgb.gz b/data/frames/frame-reference-640x480.rgb.gz
new file mode 100644 (file)
index 0000000..7c5bd16
Binary files /dev/null and b/data/frames/frame-reference-640x480.rgb.gz differ
diff --git a/data/frames/frame-reference-640x480.yuv.gz b/data/frames/frame-reference-640x480.yuv.gz
new file mode 100644 (file)
index 0000000..3f27be3
Binary files /dev/null and b/data/frames/frame-reference-640x480.yuv.gz differ
diff --git a/data/frames/frame-scaled-1024x768.rgb.gz b/data/frames/frame-scaled-1024x768.rgb.gz
new file mode 100644 (file)
index 0000000..fba101d
Binary files /dev/null and b/data/frames/frame-scaled-1024x768.rgb.gz differ
diff --git a/data/frames/frame-scaled-1024x768.yuv.gz b/data/frames/frame-scaled-1024x768.yuv.gz
new file mode 100644 (file)
index 0000000..d3c3aae
Binary files /dev/null and b/data/frames/frame-scaled-1024x768.yuv.gz differ
diff --git a/data/frames/frame-scaled-640x480.rgb.gz b/data/frames/frame-scaled-640x480.rgb.gz
new file mode 100644 (file)
index 0000000..08c1be8
Binary files /dev/null and b/data/frames/frame-scaled-640x480.rgb.gz differ
diff --git a/data/frames/frame-scaled-640x480.yuv.gz b/data/frames/frame-scaled-640x480.yuv.gz
new file mode 100644 (file)
index 0000000..821919f
Binary files /dev/null and b/data/frames/frame-scaled-640x480.yuv.gz differ
diff --git a/data/frames/gen-frames.py b/data/frames/gen-frames.py
new file mode 100755 (executable)
index 0000000..4742793
--- /dev/null
@@ -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 (file)
index 0000000..27bac1a
--- /dev/null
@@ -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 (executable)
index 0000000..ff1da21
--- /dev/null
@@ -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 (executable)
index 0000000..8123f0c
--- /dev/null
@@ -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 (executable)
index 0000000..4d3d166
--- /dev/null
@@ -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 (executable)
index 0000000..e92eda1
--- /dev/null
@@ -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 (file)
index 0000000..6586b29
--- /dev/null
@@ -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 (executable)
index 0000000..2cb0cb3
--- /dev/null
@@ -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 (executable)
index 0000000..e2602d8
--- /dev/null
@@ -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 (executable)
index 0000000..ff81509
--- /dev/null
@@ -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 (executable)
index 0000000..af5dfdb
--- /dev/null
@@ -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 (executable)
index 0000000..aeb0ca2
--- /dev/null
@@ -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 (executable)
index 0000000..0ae4259
--- /dev/null
@@ -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 (executable)
index 0000000..c124c29
--- /dev/null
@@ -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 (executable)
index 0000000..b3b0510
--- /dev/null
@@ -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