[libcamera-devel] utils: ipu3: Add test capture script

Message ID 20181128224507.24596-1-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • [libcamera-devel] utils: ipu3: Add test capture script
Related show

Commit Message

Laurent Pinchart Nov. 28, 2018, 10:45 p.m. UTC
The script captures raw frames from cameras based on the Intel IPU3. It
takes the sensor name as an argument and isn't meant to depend on a
particular platform.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 utils/ipu3/ipu3-capture.sh | 182 +++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)
 create mode 100755 utils/ipu3/ipu3-capture.sh

Comments

Kieran Bingham Nov. 29, 2018, 12:20 p.m. UTC | #1
Hi Laurent,

On 28/11/2018 22:45, Laurent Pinchart wrote:
> The script captures raw frames from cameras based on the Intel IPU3. It
> takes the sensor name as an argument and isn't meant to depend on a
> particular platform.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Looks like a good addition to get us started.

Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>


> ---
>  utils/ipu3/ipu3-capture.sh | 182 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 182 insertions(+)
>  create mode 100755 utils/ipu3/ipu3-capture.sh
> 
> diff --git a/utils/ipu3/ipu3-capture.sh b/utils/ipu3/ipu3-capture.sh
> new file mode 100755
> index 000000000000..930e697e7b44
> --- /dev/null
> +++ b/utils/ipu3/ipu3-capture.sh
> @@ -0,0 +1,182 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (C) 2018, Google Inc.
> +#
> +# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> +#
> +# ipu3-capture.sh - Capture raw frames from cameras based on the Intel IPU3
> +#
> +# The scripts makes use of the following tools, which are expected to be
> +# executable from the system-wide path or from the local directory:
> +#
> +# - media-ctl (from v4l-utils git://linuxtv.org/v4l-utils.git)
> +# - raw2pnm (from nvt https://github.com/intel/nvt.git)
> +# - yavta (from git://git.ideasonboard.org/yavta.git)
> +
> +# Locate the sensor entity
> +find_sensor() {
> +	local bus
> +	local sensor_name=$1
> +
> +	bus=$(grep "$sensor_name" /sys/class/video4linux/v4l-subdev*/name | cut -d ' ' -f 2)
> +	if [[ -z $bus ]]; then
> +		echo "Sensor '$sensor_name' not found." >&2
> +		exit 1
> +	fi
> +
> +	echo "$sensor_name $bus"
> +}
> +
> +# Locate the media device
> +find_media_device() {
> +	local mdev
> +
> +	for mdev in /dev/media* ; do
> +		media-ctl -d $mdev -p | grep -q ipu3-cio2 && break
> +		mdev=
> +	done
> +
> +	if [[ -z $mdev ]] ; then
> +	       echo "IPU3 media device not found." >&2
> +	       exit 1
> +	fi
> +
> +	echo $mdev
> +}
> +
> +# Locate the CSI2 and CIO2 and get the sensor format
> +parse_pipeline() {
> +	local cio2_queue
> +	local resolution
> +	local sensor=$1
> +
> +	read cio2_queue bus_format sensor_size <<< $($mediactl -p | awk "
> +	/^- entity [0-9]*:/ {
> +		sensor=0;
> +	}
> +
> +	/^- entity [0-9]*: $sensor/ {
> +		sensor=1;
> +	}
> +
> +	/^[ \t]*(stream:0)?\[fmt:/ {
> +		if (sensor) {
> +			gsub(\".*fmt:\", \"\");
> +			gsub(\"[] ].*\", \"\");
> +			gsub(\"/\", \" \");
> +			format=\$0;
> +		}
> +	}
> +
> +	/^[ \t]*->/ {
> +		if (sensor)
> +			cio2=substr(\$3, 0, 1);
> +	}
> +
> +	END {
> +		print cio2 \" \" format;
> +	}
> +	")
> +
> +	ipu3_csi2="ipu3-csi2 $cio2_queue"
> +	ipu3_capture="ipu3-cio2 $cio2_queue"
> +
> +	sensor_width=$(echo $sensor_size | cut -d 'x' -f 1)
> +	sensor_height=$(echo $sensor_size | cut -d 'x' -f 2)
> +
> +	echo "Using device $mdev with IPU3 CIO2 queue $cio2_queue"
> +}
> +
> +# Configure the pipeline
> +configure_pipeline() {
> +	local format="fmt:$bus_format/$sensor_size"
> +
> +	echo "Configuring pipeline for $sensor in $format"
> +
> +	$mediactl -r
> +
> +	$mediactl -l "\"$sensor\":0 -> \"$ipu3_csi2\":0[1]"
> +	$mediactl -l "\"$ipu3_csi2\":1 -> \"$ipu3_capture\":0[1]"
> +
> +	$mediactl -V "\"$sensor\":0 [$format]"
> +	$mediactl -V "\"$ipu3_csi2\":1 [$format]"
> +}
> +
> +# Capture frames
> +capture_frames() {
> +	local file_op
> +	local frame_count=$1
> +	local ipu3_format=IPU3_${bus_format/_1X10/}
> +	local save_file=$2
> +
> +	if [ $save_file -eq 1 ]; then
> +		file_op="--file=/tmp/frame-#.bin"
> +	fi
> +
> +	yavta -c$frame_count -n5 -I -f $ipu3_format -s $sensor_size $file_op \
> +		$($mediactl -e "$ipu3_capture")
> +}
> +
> +# Convert captured files to ppm
> +convert_files() {
> +	local frame_count=$1
> +	local format=${bus_format/_1X10/}
> +	local padded_width=$(expr \( $sensor_width + 49 \) / 50 \* 50)
> +
> +	echo "Converting ${sensor_width}x${sensor_height} (${padded_width}x${sensor_height})"
> +
> +	for i in `seq -f '%06.0f' 0 $(($frame_count - 1))`; do
> +		ipu3-unpack /tmp/frame-$i.bin /tmp/frame-$i.raw
> +		raw2pnm -x$padded_width -y$sensor_height -f$format /tmp/frame-$i.raw /tmp/frame-$i.ppm
> +	done
> +}
> +
> +# Print usage message
> +usage() {
> +	echo "Usage: $1 [options] sensor-name"
> +	echo "Supported options:"
> +	echo "-c,--count n      Number of frame to capture"
> +	echo "--no-save         Do not save captured frames to disk"
> +}
> +
> +# Parse command line arguments
> +frame_count=10
> +save_file=1
> +
> +while (( "$#" )) ; do
> +	case $1 in
> +	-c|--count)
> +		frame_count=$2
> +		shift 2
> +		;;
> +	--no-save)
> +		save_file=0
> +		shift
> +		;;
> +	-*)
> +		echo "Unsupported option $1" >&2
> +		usage $0
> +		exit 1
> +		;;
> +	*)
> +		break
> +		;;
> +	esac
> +done
> +
> +if [ $# != 1 ] ; then
> +	usage $0
> +	exit 1
> +fi
> +
> +sensor_name=$1
> +
> +sensor=$(find_sensor $sensor_name)
> +mdev=$(find_media_device)
> +
> +mediactl="media-ctl -d $mdev"
> +
> +parse_pipeline $sensor
> +configure_pipeline
> +capture_frames $frame_count $save_file
> +[[ $save_file -eq 1 ]] && convert_files $frame_count
>

Patch

diff --git a/utils/ipu3/ipu3-capture.sh b/utils/ipu3/ipu3-capture.sh
new file mode 100755
index 000000000000..930e697e7b44
--- /dev/null
+++ b/utils/ipu3/ipu3-capture.sh
@@ -0,0 +1,182 @@ 
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2018, Google Inc.
+#
+# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+#
+# ipu3-capture.sh - Capture raw frames from cameras based on the Intel IPU3
+#
+# The scripts makes use of the following tools, which are expected to be
+# executable from the system-wide path or from the local directory:
+#
+# - media-ctl (from v4l-utils git://linuxtv.org/v4l-utils.git)
+# - raw2pnm (from nvt https://github.com/intel/nvt.git)
+# - yavta (from git://git.ideasonboard.org/yavta.git)
+
+# Locate the sensor entity
+find_sensor() {
+	local bus
+	local sensor_name=$1
+
+	bus=$(grep "$sensor_name" /sys/class/video4linux/v4l-subdev*/name | cut -d ' ' -f 2)
+	if [[ -z $bus ]]; then
+		echo "Sensor '$sensor_name' not found." >&2
+		exit 1
+	fi
+
+	echo "$sensor_name $bus"
+}
+
+# Locate the media device
+find_media_device() {
+	local mdev
+
+	for mdev in /dev/media* ; do
+		media-ctl -d $mdev -p | grep -q ipu3-cio2 && break
+		mdev=
+	done
+
+	if [[ -z $mdev ]] ; then
+	       echo "IPU3 media device not found." >&2
+	       exit 1
+	fi
+
+	echo $mdev
+}
+
+# Locate the CSI2 and CIO2 and get the sensor format
+parse_pipeline() {
+	local cio2_queue
+	local resolution
+	local sensor=$1
+
+	read cio2_queue bus_format sensor_size <<< $($mediactl -p | awk "
+	/^- entity [0-9]*:/ {
+		sensor=0;
+	}
+
+	/^- entity [0-9]*: $sensor/ {
+		sensor=1;
+	}
+
+	/^[ \t]*(stream:0)?\[fmt:/ {
+		if (sensor) {
+			gsub(\".*fmt:\", \"\");
+			gsub(\"[] ].*\", \"\");
+			gsub(\"/\", \" \");
+			format=\$0;
+		}
+	}
+
+	/^[ \t]*->/ {
+		if (sensor)
+			cio2=substr(\$3, 0, 1);
+	}
+
+	END {
+		print cio2 \" \" format;
+	}
+	")
+
+	ipu3_csi2="ipu3-csi2 $cio2_queue"
+	ipu3_capture="ipu3-cio2 $cio2_queue"
+
+	sensor_width=$(echo $sensor_size | cut -d 'x' -f 1)
+	sensor_height=$(echo $sensor_size | cut -d 'x' -f 2)
+
+	echo "Using device $mdev with IPU3 CIO2 queue $cio2_queue"
+}
+
+# Configure the pipeline
+configure_pipeline() {
+	local format="fmt:$bus_format/$sensor_size"
+
+	echo "Configuring pipeline for $sensor in $format"
+
+	$mediactl -r
+
+	$mediactl -l "\"$sensor\":0 -> \"$ipu3_csi2\":0[1]"
+	$mediactl -l "\"$ipu3_csi2\":1 -> \"$ipu3_capture\":0[1]"
+
+	$mediactl -V "\"$sensor\":0 [$format]"
+	$mediactl -V "\"$ipu3_csi2\":1 [$format]"
+}
+
+# Capture frames
+capture_frames() {
+	local file_op
+	local frame_count=$1
+	local ipu3_format=IPU3_${bus_format/_1X10/}
+	local save_file=$2
+
+	if [ $save_file -eq 1 ]; then
+		file_op="--file=/tmp/frame-#.bin"
+	fi
+
+	yavta -c$frame_count -n5 -I -f $ipu3_format -s $sensor_size $file_op \
+		$($mediactl -e "$ipu3_capture")
+}
+
+# Convert captured files to ppm
+convert_files() {
+	local frame_count=$1
+	local format=${bus_format/_1X10/}
+	local padded_width=$(expr \( $sensor_width + 49 \) / 50 \* 50)
+
+	echo "Converting ${sensor_width}x${sensor_height} (${padded_width}x${sensor_height})"
+
+	for i in `seq -f '%06.0f' 0 $(($frame_count - 1))`; do
+		ipu3-unpack /tmp/frame-$i.bin /tmp/frame-$i.raw
+		raw2pnm -x$padded_width -y$sensor_height -f$format /tmp/frame-$i.raw /tmp/frame-$i.ppm
+	done
+}
+
+# Print usage message
+usage() {
+	echo "Usage: $1 [options] sensor-name"
+	echo "Supported options:"
+	echo "-c,--count n      Number of frame to capture"
+	echo "--no-save         Do not save captured frames to disk"
+}
+
+# Parse command line arguments
+frame_count=10
+save_file=1
+
+while (( "$#" )) ; do
+	case $1 in
+	-c|--count)
+		frame_count=$2
+		shift 2
+		;;
+	--no-save)
+		save_file=0
+		shift
+		;;
+	-*)
+		echo "Unsupported option $1" >&2
+		usage $0
+		exit 1
+		;;
+	*)
+		break
+		;;
+	esac
+done
+
+if [ $# != 1 ] ; then
+	usage $0
+	exit 1
+fi
+
+sensor_name=$1
+
+sensor=$(find_sensor $sensor_name)
+mdev=$(find_media_device)
+
+mediactl="media-ctl -d $mdev"
+
+parse_pipeline $sensor
+configure_pipeline
+capture_frames $frame_count $save_file
+[[ $save_file -eq 1 ]] && convert_files $frame_count