summaryrefslogtreecommitdiff
path: root/src/lc-compliance/capture_test.cpp
blob: 52578207c11f5a6cbac565a5c60f5d6062b4c2a1 (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
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2020, Google Inc.
 * Copyright (C) 2021, Collabora Ltd.
 *
 * capture_test.cpp - Test camera capture
 */

#include <iostream>

#include <gtest/gtest.h>

#include "environment.h"
#include "simple_capture.h"

using namespace libcamera;

const std::vector<int> NUMREQUESTS = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
const std::vector<StreamRole> ROLES = { Raw, StillCapture, VideoRecording, Viewfinder };

class SingleStream : public testing::TestWithParam<std::tuple<StreamRole, int>>
{
public:
	static std::string nameParameters(const testing::TestParamInfo<SingleStream::ParamType> &info);

protected:
	void SetUp() override;
	void TearDown() override;

	std::shared_ptr<Camera> camera_;
};

/*
 * We use gtest's SetUp() and TearDown() instead of constructor and destructor
 * in order to be able to assert on them.
 */
void SingleStream::SetUp()
{
	Environment *env = Environment::get();

	camera_ = env->cm()->get(env->cameraId());

	ASSERT_EQ(camera_->acquire(), 0);
}

void SingleStream::TearDown()
{
	if (!camera_)
		return;

	camera_->release();
	camera_.reset();
}

std::string SingleStream::nameParameters(const testing::TestParamInfo<SingleStream::ParamType> &info)
{
	std::map<StreamRole, std::string> rolesMap = { { Raw, "Raw" },
						       { StillCapture, "StillCapture" },
						       { VideoRecording, "VideoRecording" },
						       { Viewfinder, "Viewfinder" } };

	std::string roleName = rolesMap[std::get<0>(info.param)];
	std::string numRequestsName = std::to_string(std::get<1>(info.param));

	return roleName + "_" + numRequestsName;
}

/*
 * Test single capture cycles
 *
 * Makes sure the camera completes the exact number of requests queued. Example
 * failure is a camera that completes less requests than the number of requests
 * queued.
 */
TEST_P(SingleStream, Capture)
{
	auto [role, numRequests] = GetParam();

	SimpleCaptureBalanced capture(camera_);

	capture.configure(role);

	capture.capture(numRequests);
}

/*
 * Test multiple start/stop cycles
 *
 * Makes sure the camera supports multiple start/stop cycles. Example failure is
 * a camera that does not clean up correctly in its error path but is only
 * tested by single-capture applications.
 */
TEST_P(SingleStream, CaptureStartStop)
{
	auto [role, numRequests] = GetParam();
	unsigned int numRepeats = 3;

	SimpleCaptureBalanced capture(camera_);

	capture.configure(role);

	for (unsigned int starts = 0; starts < numRepeats; starts++)
		capture.capture(numRequests);
}

/*
 * Test unbalanced stop
 *
 * Makes sure the camera supports a stop with requests queued. Example failure
 * is a camera that does not handle cancelation of buffers coming back from the
 * video device while stopping.
 */
TEST_P(SingleStream, UnbalancedStop)
{
	auto [role, numRequests] = GetParam();

	SimpleCaptureUnbalanced capture(camera_);

	capture.configure(role);

	capture.capture(numRequests);
}

INSTANTIATE_TEST_SUITE_P(CaptureTests,
			 SingleStream,
			 testing::Combine(testing::ValuesIn(ROLES),
					  testing::ValuesIn(NUMREQUESTS)),
			 SingleStream::nameParameters);
/** * \class PixelFormatInfo * \brief Information about pixel formats * * The PixelFormatInfo class groups together information describing a pixel * format. It facilitates handling of pixel formats by providing data commonly * used in pipeline handlers. * * \var PixelFormatInfo::format * \brief The PixelFormat described by this instance * * \var PixelFormatInfo::v4l2Format * \brief The V4L2 pixel format corresponding to the PixelFormat */ namespace { const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{ /* RGB formats. */ { PixelFormat(DRM_FORMAT_BGR888), { .format = PixelFormat(DRM_FORMAT_BGR888), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGB24), } }, { PixelFormat(DRM_FORMAT_RGB888), { .format = PixelFormat(DRM_FORMAT_RGB888), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_BGR24), } }, { PixelFormat(DRM_FORMAT_ABGR8888), { .format = PixelFormat(DRM_FORMAT_ABGR8888), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGBA32), } }, { PixelFormat(DRM_FORMAT_ARGB8888), { .format = PixelFormat(DRM_FORMAT_ARGB8888), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_ABGR32), } }, { PixelFormat(DRM_FORMAT_BGRA8888), { .format = PixelFormat(DRM_FORMAT_BGRA8888), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_ARGB32), } }, { PixelFormat(DRM_FORMAT_RGBA8888), { .format = PixelFormat(DRM_FORMAT_RGBA8888), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_BGRA32), } }, /* YUV packed formats. */ { PixelFormat(DRM_FORMAT_YUYV), { .format = PixelFormat(DRM_FORMAT_YUYV), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YUYV), } }, { PixelFormat(DRM_FORMAT_YVYU), { .format = PixelFormat(DRM_FORMAT_YVYU), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YVYU), } }, { PixelFormat(DRM_FORMAT_UYVY), { .format = PixelFormat(DRM_FORMAT_UYVY), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_UYVY), } }, { PixelFormat(DRM_FORMAT_VYUY), { .format = PixelFormat(DRM_FORMAT_VYUY), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_VYUY), } }, /* YUV planar formats. */ { PixelFormat(DRM_FORMAT_NV16), { .format = PixelFormat(DRM_FORMAT_NV16), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV16), } }, { PixelFormat(DRM_FORMAT_NV61), { .format = PixelFormat(DRM_FORMAT_NV61), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV61), } }, { PixelFormat(DRM_FORMAT_NV12), { .format = PixelFormat(DRM_FORMAT_NV12), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV12), } }, { PixelFormat(DRM_FORMAT_NV21), { .format = PixelFormat(DRM_FORMAT_NV21), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV21), } }, /* Greyscale formats. */ { PixelFormat(DRM_FORMAT_R8), { .format = PixelFormat(DRM_FORMAT_R8), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_GREY), } }, /* Bayer formats. */ { PixelFormat(DRM_FORMAT_SBGGR8), { .format = PixelFormat(DRM_FORMAT_SBGGR8), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR8), } }, { PixelFormat(DRM_FORMAT_SGBRG8), { .format = PixelFormat(DRM_FORMAT_SGBRG8), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG8), } }, { PixelFormat(DRM_FORMAT_SGRBG8), { .format = PixelFormat(DRM_FORMAT_SGRBG8), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG8), } }, { PixelFormat(DRM_FORMAT_SRGGB8), { .format = PixelFormat(DRM_FORMAT_SRGGB8), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB8), } }, { PixelFormat(DRM_FORMAT_SBGGR10), { .format = PixelFormat(DRM_FORMAT_SBGGR10), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10), } }, { PixelFormat(DRM_FORMAT_SGBRG10), { .format = PixelFormat(DRM_FORMAT_SGBRG10), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10), } }, { PixelFormat(DRM_FORMAT_SGRBG10), { .format = PixelFormat(DRM_FORMAT_SGRBG10), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10), } }, { PixelFormat(DRM_FORMAT_SRGGB10), { .format = PixelFormat(DRM_FORMAT_SRGGB10), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10), } }, { PixelFormat(DRM_FORMAT_SBGGR10, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SBGGR10, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P), } }, { PixelFormat(DRM_FORMAT_SGBRG10, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SGBRG10, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P), } }, { PixelFormat(DRM_FORMAT_SGRBG10, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SGRBG10, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P), } }, { PixelFormat(DRM_FORMAT_SRGGB10, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SRGGB10, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P), } }, { PixelFormat(DRM_FORMAT_SBGGR12), { .format = PixelFormat(DRM_FORMAT_SBGGR12), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12), } }, { PixelFormat(DRM_FORMAT_SGBRG12), { .format = PixelFormat(DRM_FORMAT_SGBRG12), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12), } }, { PixelFormat(DRM_FORMAT_SGRBG12), { .format = PixelFormat(DRM_FORMAT_SGRBG12), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12), } }, { PixelFormat(DRM_FORMAT_SRGGB12), { .format = PixelFormat(DRM_FORMAT_SRGGB12), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12), } }, { PixelFormat(DRM_FORMAT_SBGGR12, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SBGGR12, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12P), } }, { PixelFormat(DRM_FORMAT_SGBRG12, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SGBRG12, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12P), } }, { PixelFormat(DRM_FORMAT_SGRBG12, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SGRBG12, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12P), } }, { PixelFormat(DRM_FORMAT_SRGGB12, MIPI_FORMAT_MOD_CSI2_PACKED), { .format = PixelFormat(DRM_FORMAT_SRGGB12, MIPI_FORMAT_MOD_CSI2_PACKED), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12P), } }, /* Compressed formats. */ { PixelFormat(DRM_FORMAT_MJPEG), { .format = PixelFormat(DRM_FORMAT_MJPEG), .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_MJPEG), } }, }; } /* namespace */ /** * \fn bool PixelFormatInfo::isValid() const * \brief Check if the pixel format info is valid * \return True if the pixel format info is valid, false otherwise */ /** * \brief Retrieve information about a pixel format * \param[in] format The pixel format * \return The PixelFormatInfo describing the \a format if known, or an invalid * PixelFormatInfo otherwise */ const PixelFormatInfo &PixelFormatInfo::info(const PixelFormat &format) { static const PixelFormatInfo invalid{}; const auto iter = pixelFormatInfo.find(format); if (iter == pixelFormatInfo.end()) { LOG(Formats, Warning) << "Unsupported pixel format " << format.toString(); return invalid; } return iter->second; } } /* namespace libcamera */