summaryrefslogtreecommitdiff
path: root/src/apps/lc-compliance/helpers/capture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/apps/lc-compliance/helpers/capture.cpp')
-rw-r--r--src/apps/lc-compliance/helpers/capture.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/apps/lc-compliance/helpers/capture.cpp b/src/apps/lc-compliance/helpers/capture.cpp
new file mode 100644
index 00000000..2a3fa3b6
--- /dev/null
+++ b/src/apps/lc-compliance/helpers/capture.cpp
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020-2021, Google Inc.
+ *
+ * Simple capture helper
+ */
+
+#include "capture.h"
+
+#include <assert.h>
+
+#include <gtest/gtest.h>
+
+using namespace libcamera;
+
+Capture::Capture(std::shared_ptr<Camera> camera)
+ : camera_(std::move(camera)), allocator_(camera_)
+{
+}
+
+Capture::~Capture()
+{
+ stop();
+}
+
+void Capture::configure(libcamera::Span<const libcamera::StreamRole> roles)
+{
+ assert(!roles.empty());
+
+ config_ = camera_->generateConfiguration(roles);
+ if (!config_)
+ GTEST_SKIP() << "Roles not supported by camera";
+
+ ASSERT_EQ(config_->size(), roles.size()) << "Unexpected number of streams in configuration";
+
+ /*
+ * Set the buffers count to the largest value across all streams.
+ * \todo: Should all streams from a Camera have the same buffer count ?
+ */
+ auto largest =
+ std::max_element(config_->begin(), config_->end(),
+ [](const StreamConfiguration &l, const StreamConfiguration &r)
+ { return l.bufferCount < r.bufferCount; });
+
+ assert(largest != config_->end());
+
+ for (auto &cfg : *config_)
+ cfg.bufferCount = largest->bufferCount;
+
+ if (config_->validate() != CameraConfiguration::Valid) {
+ config_.reset();
+ FAIL() << "Configuration not valid";
+ }
+
+ if (camera_->configure(config_.get())) {
+ config_.reset();
+ FAIL() << "Failed to configure camera";
+ }
+}
+
+void Capture::run(unsigned int captureLimit, std::optional<unsigned int> queueLimit)
+{
+ assert(!queueLimit || captureLimit <= *queueLimit);
+
+ captureLimit_ = captureLimit;
+ queueLimit_ = queueLimit;
+
+ captureCount_ = queueCount_ = 0;
+
+ EventLoop loop;
+ loop_ = &loop;
+
+ start();
+
+ for (const auto &request : requests_)
+ queueRequest(request.get());
+
+ EXPECT_EQ(loop_->exec(), 0);
+
+ stop();
+
+ EXPECT_LE(captureLimit_, captureCount_);
+ EXPECT_LE(captureCount_, queueCount_);
+ EXPECT_TRUE(!queueLimit_ || queueCount_ <= *queueLimit_);
+}
+
+int Capture::queueRequest(libcamera::Request *request)
+{
+ if (queueLimit_ && queueCount_ >= *queueLimit_)
+ return 0;
+
+ int ret = camera_->queueRequest(request);
+ if (ret < 0)
+ return ret;
+
+ queueCount_ += 1;
+ return 0;
+}
+
+void Capture::requestComplete(Request *request)
+{
+ captureCount_++;
+ if (captureCount_ >= captureLimit_) {
+ loop_->exit(0);
+ return;
+ }
+
+ EXPECT_EQ(request->status(), Request::Status::RequestComplete)
+ << "Request didn't complete successfully";
+
+ request->reuse(Request::ReuseBuffers);
+ if (queueRequest(request))
+ loop_->exit(-EINVAL);
+}
+
+void Capture::start()
+{
+ assert(config_);
+ assert(!config_->empty());
+ assert(!allocator_.allocated());
+ assert(requests_.empty());
+
+ const auto bufferCount = config_->at(0).bufferCount;
+
+ /* No point in testing less requests then the camera depth. */
+ if (queueLimit_ && *queueLimit_ < bufferCount) {
+ GTEST_SKIP() << "Camera needs " << bufferCount
+ << " requests, can't test only " << *queueLimit_;
+ }
+
+ for (std::size_t i = 0; i < bufferCount; i++) {
+ std::unique_ptr<Request> request = camera_->createRequest();
+ ASSERT_TRUE(request) << "Can't create request";
+ requests_.push_back(std::move(request));
+ }
+
+ for (const auto &cfg : *config_) {
+ Stream *stream = cfg.stream();
+
+ int count = allocator_.allocate(stream);
+ ASSERT_GE(count, 0) << "Failed to allocate buffers";
+
+ const auto &buffers = allocator_.buffers(stream);
+ ASSERT_EQ(buffers.size(), bufferCount) << "Mismatching buffer count";
+
+ for (std::size_t i = 0; i < bufferCount; i++) {
+ ASSERT_EQ(requests_[i]->addBuffer(stream, buffers[i].get()), 0)
+ << "Failed to add buffer to request";
+ }
+ }
+
+ ASSERT_TRUE(allocator_.allocated());
+
+ camera_->requestCompleted.connect(this, &Capture::requestComplete);
+
+ ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
+}
+
+void Capture::stop()
+{
+ if (!config_ || !allocator_.allocated())
+ return;
+
+ camera_->stop();
+
+ camera_->requestCompleted.disconnect(this);
+
+ requests_.clear();
+
+ for (const auto &cfg : *config_) {
+ EXPECT_EQ(allocator_.free(cfg.stream()), 0)
+ << "Failed to free buffers associated with stream";
+ }
+
+ EXPECT_FALSE(allocator_.allocated());
+}