summaryrefslogtreecommitdiff
path: root/test/camera/statemachine.cpp
blob: 325b4674bcc958d8905d0090f835132fa9ba220f (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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * libcamera Camera API tests
 */

#include <iostream>

#include "camera_test.h"
#include "test.h"

using namespace std;

namespace {

class Statemachine : public CameraTest, public Test
{
public:
	Statemachine()
		: CameraTest("VIMC Sensor B")
	{
	}

protected:
	int testAvailable()
	{
		/* Test operations which should fail. */
		if (camera_->configure(defconf_.get()) != -EACCES)
			return TestFail;

		if (camera_->createRequest())
			return TestFail;

		if (camera_->start() != -EACCES)
			return TestFail;

		Request request(camera_.get());
		if (camera_->queueRequest(&request) != -EACCES)
			return TestFail;

		if (camera_->stop() != -EACCES)
			return TestFail;

		/* Test operations which should pass. */
		if (camera_->release())
			return TestFail;

		/* Test valid state transitions, end in Acquired state. */
		if (camera_->acquire())
			return TestFail;

		return TestPass;
	}

	int testAcquired()
	{
		/* Test operations which should fail. */
		if (camera_->acquire() != -EBUSY)
			return TestFail;

		if (camera_->createRequest())
			return TestFail;

		if (camera_->start() != -EACCES)
			return TestFail;

		Request request(camera_.get());
		if (camera_->queueRequest(&request) != -EACCES)
			return TestFail;

		if (camera_->stop() != -EACCES)
			return TestFail;

		/* Test valid state transitions, end in Configured state. */
		if (camera_->release())
			return TestFail;

		if (camera_->acquire())
			return TestFail;

		if (camera_->configure(defconf_.get()))
			return TestFail;

		return TestPass;
	}

	int testConfigured()
	{
		/* Test operations which should fail. */
		if (camera_->acquire() != -EBUSY)
			return TestFail;

		Request request1(camera_.get());
		if (camera_->queueRequest(&request1) != -EACCES)
			return TestFail;

		if (camera_->stop() != -EACCES)
			return TestFail;

		/* Test operations which should pass. */
		Request *request2 = camera_->createRequest();
		if (!request2)
			return TestFail;

		/* Never handed to hardware so need to manually delete it. */
		delete request2;

		/* Test valid state transitions, end in Running state. */
		if (camera_->release())
			return TestFail;

		if (camera_->acquire())
			return TestFail;

		if (camera_->configure(defconf_.get()))
			return TestFail;

		/* Use internally allocated buffers. */
		allocator_ = new FrameBufferAllocator(camera_);
		Stream *stream = *camera_->streams().begin();
		if (allocator_->allocate(stream) < 0)
			return TestFail;

		if (camera_->start())
			return TestFail;

		return TestPass;
	}

	int testRuning()
	{
		/* Test operations which should fail. */
		if (camera_->acquire() != -EBUSY)
			return TestFail;

		if (camera_->release() != -EBUSY)
			return TestFail;

		if (camera_->configure(defconf_.get()) != -EACCES)
			return TestFail;

		if (camera_->start() != -EACCES)
			return TestFail;

		/* Test operations which should pass. */
		Request *request = camera_->createRequest();
		if (!request)
			return TestFail;

		Stream *stream = *camera_->streams().begin();
		if (request->addBuffer(stream, allocator_->buffers(stream)[0].get()))
			return TestFail;

		if (camera_->queueRequest(request))
			return TestFail;

		/* Test valid state transitions, end in Available state. */
		if (camera_->stop())
			return TestFail;

		delete allocator_;

		if (camera_->release())
			return TestFail;

		return TestPass;
	}

	int init() override
	{
		if (status_ != TestPass)
			return status_;

		defconf_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
		if (!defconf_) {
			cout << "Failed to generate default configuration" << endl;
			return TestFail;
		}

		return TestPass;
	}

	int run() override
	{
		if (testAvailable() != TestPass) {
			cout << "State machine in Available state failed" << endl;
			return TestFail;
		}

		if (testAcquired() != TestPass) {
			cout << "State machine in Acquired state failed" << endl;
			return TestFail;
		}

		if (testConfigured() != TestPass) {
			cout << "State machine in Configured state failed" << endl;
			return TestFail;
		}

		if (testRuning() != TestPass) {
			cout << "State machine in Running state failed" << endl;
			return TestFail;
		}

		return TestPass;
	}

	std::unique_ptr<CameraConfiguration> defconf_;
	FrameBufferAllocator *allocator_;
};

} /* namespace */

TEST_REGISTER(Statemachine);
a id='n726' href='#n726'>726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * geometry.cpp - Geometry-related structures
 */

#include <libcamera/geometry.h>

#include <sstream>
#include <stdint.h>

#include <libcamera/base/log.h>

/**
 * \file geometry.h
 * \brief Data structures related to geometric objects
 */

namespace libcamera {

/**
 * \class Point
 * \brief Describe a point in two-dimensional space
 *
 * The Point structure defines a point in two-dimensional space with integer
 * precision. The coordinates of a Point may be negative as well as positive.
 */

/**
 * \fn Point::Point()
 * \brief Construct a Point with x and y set to 0
 */

/**
 * \fn Point::Point(int xpos, int ypos)
 * \brief Construct a Point at given \a xpos and \a ypos values
 * \param[in] xpos The x-coordinate
 * \param[in] ypos The y-coordinate
 */

/**
 * \var Point::x
 * \brief The x-coordinate of the Point
 */

/**
 * \var Point::y
 * \brief The y-coordinate of the Point
 */

/**
 * \brief Assemble and return a string describing the point
 * \return A string describing the point
 */
const std::string Point::toString() const
{
	std::stringstream ss;

	ss << "(" << x << "," << y << ")";

	return ss.str();
}

/**
 * \fn Point Point::operator-() const
 * \brief Negate a Point by negating both its x and y coordinates
 * \return The negated point
 */

/**
 * \brief Compare points for equality
 * \return True if the two points are equal, false otherwise
 */
bool operator==(const Point &lhs, const Point &rhs)
{
	return lhs.x == rhs.x && lhs.y == rhs.y;
}

/**
 * \fn bool operator!=(const Point &lhs, const Point &rhs)
 * \brief Compare points for inequality
 * \return True if the two points are not equal, false otherwise
 */

/**
 * \struct Size
 * \brief Describe a two-dimensional size
 *
 * The Size structure defines a two-dimensional size with integer precision.
 */

/**
 * \fn Size::Size()
 * \brief Construct a Size with width and height set to 0
 */

/**
 * \fn Size::Size(unsigned int width, unsigned int height)
 * \brief Construct a Size with given \a width and \a height
 * \param[in] width The Size width
 * \param[in] height The Size height
 */

/**
 * \var Size::width
 * \brief The Size width
 */

/**
 * \var Size::height
 * \brief The Size height
 */

/**
 * \fn bool Size::isNull() const
 * \brief Check if the size is null
 * \return True if both the width and height are 0, or false otherwise
 */

/**
 * \brief Assemble and return a string describing the size
 * \return A string describing the size
 */
const std::string Size::toString() const
{
	return std::to_string(width) + "x" + std::to_string(height);
}

/**
 * \fn Size::alignDownTo(unsigned int hAlignment, unsigned int vAlignment)
 * \brief Align the size down horizontally and vertically in place
 * \param[in] hAlignment Horizontal alignment
 * \param[in] vAlignment Vertical alignment
 *
 * This functions rounds the width and height down to the nearest multiple of
 * \a hAlignment and \a vAlignment respectively.
 *
 * \return A reference to this object
 */

/**
 * \fn Size::alignUpTo(unsigned int hAlignment, unsigned int vAlignment)
 * \brief Align the size up horizontally and vertically in place
 * \param[in] hAlignment Horizontal alignment
 * \param[in] vAlignment Vertical alignment
 *
 * This functions rounds the width and height up to the nearest multiple of
 * \a hAlignment and \a vAlignment respectively.
 *
 * \return A reference to this object
 */

/**
 * \fn Size::boundTo(const Size &bound)
 * \brief Bound the size to \a bound in place
 * \param[in] bound The maximum size
 *
 * This function sets the width and height to the minimum of this size and the
 * \a bound size.
 *
 * \return A reference to this object
 */

/**
 * \fn Size::expandTo(const Size &expand)
 * \brief Expand the size to \a expand
 * \param[in] expand The minimum size
 *
 * This function sets the width and height to the maximum of this size and the
 * \a expand size.
 *
 * \return A reference to this object
 */

/**
 * \fn Size::growBy(const Size &margins)
 * \brief Grow the size by \a margins in place
 * \param[in] margins The margins to add to the size
 *
 * This function adds the width and height of the \a margin size to this size.
 *
 * \return A reference to this object
 */

/**
 * \fn Size::shrinkBy(const Size &margins)
 * \brief Shrink the size by \a margins in place
 * \param[in] margins The margins to subtract to the size
 *
 * This function subtracts the width and height of the \a margin size from this
 * size. If the width or height of the size are smaller than those of \a
 * margins, the result is clamped to 0.
 *
 * \return A reference to this object
 */

/**
 * \fn Size::alignedDownTo(unsigned int hAlignment, unsigned int vAlignment)
 * \brief Align the size down horizontally and vertically
 * \param[in] hAlignment Horizontal alignment
 * \param[in] vAlignment Vertical alignment
 * \return A Size whose width and height are equal to the width and height of
 * this size rounded down to the nearest multiple of \a hAlignment and
 * \a vAlignment respectively
 */

/**
 * \fn Size::alignedUpTo(unsigned int hAlignment, unsigned int vAlignment)
 * \brief Align the size up horizontally and vertically
 * \param[in] hAlignment Horizontal alignment
 * \param[in] vAlignment Vertical alignment
 * \return A Size whose width and height are equal to the width and height of
 * this size rounded up to the nearest multiple of \a hAlignment and
 * \a vAlignment respectively
 */

/**
 * \fn Size::boundedTo(const Size &bound)
 * \brief Bound the size to \a bound
 * \param[in] bound The maximum size
 * \return A Size whose width and height are the minimum of the width and
 * height of this size and the \a bound size
 */

/**
 * \fn Size::expandedTo(const Size &expand)
 * \brief Expand the size to \a expand
 * \param[in] expand The minimum size
 * \return A Size whose width and height are the maximum of the width and
 * height of this size and the \a expand size
 */

/**
 * \fn Size::grownBy(const Size &margins)
 * \brief Grow the size by \a margins
 * \param[in] margins The margins to add to the size
 * \return A Size whose width and height are the sum of the width and height of
 * this size and the \a margins size
 */

/**
 * \fn Size::shrunkBy(const Size &margins)
 * \brief Shrink the size by \a margins
 * \param[in] margins The margins to subtract to the size
 *
 * If the width or height of the size are smaller than those of \a margins, the
 * resulting size has its width or height clamped to 0.
 *
 * \return A Size whose width and height are the difference of the width and
 * height of this size and the \a margins size, clamped to 0
 */

/**
 * \brief Bound the size down to match the aspect ratio given by \a ratio
 * \param[in] ratio The size whose aspect ratio must be matched
 *
 * The behaviour of this function is undefined if either the width or the
 * height of the \a ratio is zero.
 *
 * \return A Size whose width and height are equal to the width and height
 * of this Size aligned down to the aspect ratio of \a ratio
 */
Size Size::boundedToAspectRatio(const Size &ratio) const
{
	ASSERT(ratio.width && ratio.height);

	uint64_t ratio1 = static_cast<uint64_t>(width) *
			  static_cast<uint64_t>(ratio.height);
	uint64_t ratio2 = static_cast<uint64_t>(ratio.width) *
			  static_cast<uint64_t>(height);

	if (ratio1 > ratio2)
		return { static_cast<unsigned int>(ratio2 / ratio.height), height };
	else
		return { width, static_cast<unsigned int>(ratio1 / ratio.width) };
}

/**
 * \brief Expand the size to match the aspect ratio given by \a ratio
 * \param[in] ratio The size whose aspect ratio must be matched
 *
 * The behaviour of this function is undefined if either the width or the
 * height of the \a ratio is zero.
 *