summaryrefslogtreecommitdiff
path: root/src/lc-compliance/simple_capture.cpp
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2021-01-27 01:23:51 +0100
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2021-04-12 10:48:56 +0200
commit02bc1108578e8b8eb68fa7d9ae3eeea558723931 (patch)
tree42e99d5d3cfa45b25651e0175b44400823efdfe2 /src/lc-compliance/simple_capture.cpp
parent43ab65df8dd2fd6ef3336fdb1f56909661de2475 (diff)
lc-compliance: Add a libcamera compliance tool
Add a compliance tool to ease testing of cameras. In contrast to the unit-tests under test/ that aims to test the internal components of libcamera the compliance tool aims to test application use-cases and to some extent the public API. This change adds the boilerplate code of a simple framework for the creation of tests. The tests aim both to demonstrate the tool and to catch real problems. The tests added are: - Test that if one queues exactly N requests to a camera exactly N requests are eventually completed. - Test that a configured camera can be started and stopped multiple times in an attempt to exercise cleanup code paths otherwise not often tested with 'cam' for example. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>
Diffstat (limited to 'src/lc-compliance/simple_capture.cpp')
-rw-r--r--src/lc-compliance/simple_capture.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp
new file mode 100644
index 00000000..389dc11f
--- /dev/null
+++ b/src/lc-compliance/simple_capture.cpp
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * simple_capture.cpp - Simple capture helper
+ */
+
+#include "simple_capture.h"
+
+using namespace libcamera;
+
+SimpleCapture::SimpleCapture(std::shared_ptr<Camera> camera)
+ : camera_(camera), allocator_(std::make_unique<FrameBufferAllocator>(camera))
+{
+}
+
+SimpleCapture::~SimpleCapture()
+{
+}
+
+Results::Result SimpleCapture::configure(StreamRole role)
+{
+ config_ = camera_->generateConfiguration({ role });
+
+ if (config_->validate() != CameraConfiguration::Valid) {
+ config_.reset();
+ return { Results::Fail, "Configuration not valid" };
+ }
+
+ if (camera_->configure(config_.get())) {
+ config_.reset();
+ return { Results::Fail, "Failed to configure camera" };
+ }
+
+ return { Results::Pass, "Configure camera" };
+}
+
+Results::Result SimpleCapture::start()
+{
+ Stream *stream = config_->at(0).stream();
+ if (allocator_->allocate(stream) < 0)
+ return { Results::Fail, "Failed to allocate buffers" };
+
+ if (camera_->start())
+ return { Results::Fail, "Failed to start camera" };
+
+ camera_->requestCompleted.connect(this, &SimpleCapture::requestComplete);
+
+ return { Results::Pass, "Started camera" };
+}
+
+Results::Result SimpleCapture::stop()
+{
+ Stream *stream = config_->at(0).stream();
+
+ camera_->stop();
+
+ camera_->requestCompleted.disconnect(this, &SimpleCapture::requestComplete);
+
+ allocator_->free(stream);
+
+ return { Results::Pass, "Stopped camera" };
+}
+
+/* SimpleCaptureBalanced */
+
+SimpleCaptureBalanced::SimpleCaptureBalanced(std::shared_ptr<Camera> camera)
+ : SimpleCapture(camera)
+{
+}
+
+Results::Result SimpleCaptureBalanced::capture(unsigned int numRequests)
+{
+ Results::Result ret = start();
+ if (ret.first != Results::Pass)
+ return ret;
+
+ Stream *stream = config_->at(0).stream();
+ const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_->buffers(stream);
+
+ /* No point in testing less requests then the camera depth. */
+ if (buffers.size() > numRequests) {
+ /* Cache buffers.size() before we destroy it in stop() */
+ int buffers_size = buffers.size();
+ stop();
+
+ return { Results::Skip, "Camera needs " + std::to_string(buffers_size)
+ + " requests, can't test only " + std::to_string(numRequests) };
+ }
+
+ queueCount_ = 0;
+ captureCount_ = 0;
+ captureLimit_ = numRequests;
+
+ /* Queue the recommended number of reqeuests. */
+ std::vector<std::unique_ptr<libcamera::Request>> requests;
+ for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
+ std::unique_ptr<Request> request = camera_->createRequest();
+ if (!request) {
+ stop();
+ return { Results::Fail, "Can't create request" };
+ }
+
+ if (request->addBuffer(stream, buffer.get())) {
+ stop();
+ return { Results::Fail, "Can't set buffer for request" };
+ }
+
+ if (queueRequest(request.get()) < 0) {
+ stop();
+ return { Results::Fail, "Failed to queue request" };
+ }
+
+ requests.push_back(std::move(request));
+ }
+
+ /* Run capture session. */
+ loop_ = new EventLoop();
+ loop_->exec();
+ stop();
+ delete loop_;
+
+ if (captureCount_ != captureLimit_)
+ return { Results::Fail, "Got " + std::to_string(captureCount_) +
+ " request, wanted " + std::to_string(captureLimit_) };
+
+ return { Results::Pass, "Balanced capture of " +
+ std::to_string(numRequests) + " requests" };
+}
+
+int SimpleCaptureBalanced::queueRequest(Request *request)
+{
+ queueCount_++;
+ if (queueCount_ > captureLimit_)
+ return 0;
+
+ return camera_->queueRequest(request);
+}
+
+void SimpleCaptureBalanced::requestComplete(Request *request)
+{
+ captureCount_++;
+ if (captureCount_ >= captureLimit_) {
+ loop_->exit(0);
+ return;
+ }
+
+ request->reuse(Request::ReuseBuffers);
+ if (queueRequest(request))
+ loop_->exit(-EINVAL);
+}