From 62f0b16f639a9ecb116a79819655bdf44e269443 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 16 May 2016 21:55:52 +0300 Subject: Initial commit Signed-off-by: Laurent Pinchart --- scripts/Makefile | 8 + scripts/histo2png.py | 81 ++++++++++ scripts/logger.sh | 11 ++ scripts/vsp-lib.sh | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++ scripts/vsp-runner.sh | 135 ++++++++++++++++ 5 files changed, 676 insertions(+) create mode 100644 scripts/Makefile create mode 100755 scripts/histo2png.py create mode 100755 scripts/logger.sh create mode 100755 scripts/vsp-lib.sh create mode 100755 scripts/vsp-runner.sh (limited to 'scripts') 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 ' % 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('> 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('> 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 -- cgit v1.2.3