#!/bin/bash # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2018, Google Inc. # # Author: Laurent Pinchart # # 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 "^driver[ \t]*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 [[ $# -ne 1 ]] ; then usage $0 exit 1 fi sensor_name=$1 sensor=$(find_sensor $sensor_name) || exit mdev=$(find_media_device) || exit mediactl="media-ctl -d $mdev" parse_pipeline $sensor configure_pipeline capture_frames $frame_count $save_file [[ $save_file -eq 1 ]] && convert_files $frame_count ff
path: root/test/byte-stream-buffer.cpp
blob: d606f146f6ef04ed850b1a905793129185f5818c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2018, Google Inc.
 *
 * byte_stream_buffer.cpp - ByteStreamBuffer tests
 */

#include <array>
#include <iostream>

#include "libcamera/internal/byte_stream_buffer.h"

#include "test.h"

using namespace std;
using namespace libcamera;

class ByteStreamBufferTest : public Test
{
protected:
	int run()
	{
		std::array<uint8_t, 100> data;
		unsigned int i;
		uint32_t value;
		int ret;

		/*
		 * Write mode.
		 */
		ByteStreamBuffer wbuf(data.data(), data.size());

		if (wbuf.base() != data.data() || wbuf.size() != data.size() ||
		    wbuf.offset() != 0 || wbuf.overflow()) {
			cerr << "Write buffer incorrectly constructed" << endl;
			return TestFail;
		}

		/* Test write. */
		value = 0x12345678;
		ret = wbuf.write(&value);
		if (ret || wbuf.offset() != 4 || wbuf.overflow() ||
		    *reinterpret_cast<uint32_t *>(data.data()) != 0x12345678) {
			cerr << "Write failed on write buffer" << endl;
			return TestFail;
		}

		/* Test write carve out. */
		ByteStreamBuffer wco = wbuf.carveOut(10);
		if (wco.base() != wbuf.base() + 4 || wco.size() != 10 ||
		    wco.offset() != 0 || wco.overflow() || wbuf.offset() != 14 ||
		    wbuf.overflow()) {
			cerr << "Carving out write buffer failed" << endl;
			return TestFail;
		}

		/* Test write on the carved out buffer. */
		value = 0x87654321;
		ret = wco.write(&value);
		if (ret || wco.offset() != 4 || wco.overflow() ||
		    *reinterpret_cast<uint32_t *>(data.data() + 4) != 0x87654321) {
			cerr << "Write failed on carve out buffer" << endl;
			return TestFail;
		}

		if (wbuf.offset() != 14 || wbuf.overflow()) {
			cerr << "Write on carve out buffer modified write buffer" << endl;
			return TestFail;
		}

		/* Test read, this should fail. */
		ret = wbuf.read(&value);
		if (!ret || wbuf.overflow()) {
			cerr << "Read should fail on write buffer" << endl;
			return TestFail;
		}

		/* Test overflow on carved out buffer. */
		for (i = 0; i < 2; ++i) {
			ret = wco.write(&value);
			if (ret < 0)
				break;
		}

		if (i != 1 || !wco.overflow() || !wbuf.overflow()) {
			cerr << "Write on carve out buffer failed to overflow" << endl;
			return TestFail;
		}

		/* Test reinitialization of the buffer. */
		wbuf = ByteStreamBuffer(data.data(), data.size());
		if (wbuf.overflow() || wbuf.base() != data.data() ||
		    wbuf.offset() != 0) {
			cerr << "Write buffer reinitialization failed" << endl;
			return TestFail;
		}

		/*
		 * Read mode.
		 */
		ByteStreamBuffer rbuf(const_cast<const uint8_t *>(data.data()),
				      data.size());

		if (rbuf.base() != data.data() || rbuf.size() != data.size() ||
		    rbuf.offset() != 0 || rbuf.overflow()) {
			cerr << "Read buffer incorrectly constructed" << endl;
			return TestFail;
		}

		/* Test read. */
		value = 0;
		ret = rbuf.read(&value);
		if (ret || rbuf.offset() != 4 || rbuf.overflow() ||
		    value != 0x12345678) {
			cerr << "Write failed on write buffer" << endl;
			return TestFail;
		}

		/* Test read carve out. */
		ByteStreamBuffer rco = rbuf.carveOut(10);
		if (rco.base() != rbuf.base() + 4 || rco.size() != 10 ||
		    rco.offset() != 0 || rco.overflow() || rbuf.offset() != 14 ||
		    rbuf.overflow()) {
			cerr << "Carving out read buffer failed" << endl;
			return TestFail;
		}

		/* Test read on the carved out buffer. */
		value = 0;
		ret = rco.read(&value);
		if (ret || rco.offset() != 4 || rco.overflow() || value != 0x87654321) {
			cerr << "Read failed on carve out buffer" << endl;
			return TestFail;
		}

		if (rbuf.offset() != 14 || rbuf.overflow()) {
			cerr << "Read on carve out buffer modified read buffer" << endl;
			return TestFail;
		}

		/* Test write, this should fail. */
		ret = rbuf.write(&value);
		if (!ret || rbuf.overflow()) {
			cerr << "Write should fail on read buffer" << endl;
			return TestFail;
		}

		/* Test overflow on carved out buffer. */
		for (i = 0; i < 2; ++i) {
			ret = rco.read(&value);
			if (ret < 0)
				break;
		}

		if (i != 1 || !rco.overflow() || !rbuf.overflow()) {
			cerr << "Read on carve out buffer failed to overflow" << endl;
			return TestFail;
		}

		/* Test reinitialization of the buffer. */
		rbuf = ByteStreamBuffer(const_cast<const uint8_t *>(data.data()),
					data.size());
		if (rbuf.overflow() || rbuf.base() != data.data() ||
		    rbuf.offset() != 0) {
			cerr << "Read buffer reinitialization failed" << endl;
			return TestFail;
		}

		return TestPass;
	}
};

TEST_REGISTER(ByteStreamBufferTest)