diff options
Diffstat (limited to 'src/apps/lc-compliance/helpers')
-rw-r--r-- | src/apps/lc-compliance/helpers/capture.cpp | 196 | ||||
-rw-r--r-- | src/apps/lc-compliance/helpers/capture.h | 66 |
2 files changed, 262 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..5aab973f --- /dev/null +++ b/src/apps/lc-compliance/helpers/capture.cpp @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020-2021, Google Inc. + * + * simple_capture.cpp - Simple capture helper + */ + +#include "capture.h" + +#include <gtest/gtest.h> + +using namespace libcamera; + +Capture::Capture(std::shared_ptr<Camera> camera) + : loop_(nullptr), camera_(camera), + allocator_(std::make_unique<FrameBufferAllocator>(camera)) +{ +} + +Capture::~Capture() +{ + stop(); +} + +void Capture::configure(StreamRole role) +{ + config_ = camera_->generateConfiguration({ role }); + + if (!config_) { + std::cout << "Role not supported by camera" << std::endl; + GTEST_SKIP(); + } + + 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::start() +{ + Stream *stream = config_->at(0).stream(); + int count = allocator_->allocate(stream); + + ASSERT_GE(count, 0) << "Failed to allocate buffers"; + EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected"; + + 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); + + Stream *stream = config_->at(0).stream(); + requests_.clear(); + allocator_->free(stream); +} + +/* CaptureBalanced */ + +CaptureBalanced::CaptureBalanced(std::shared_ptr<Camera> camera) + : Capture(camera) +{ +} + +void CaptureBalanced::capture(unsigned int numRequests) +{ + start(); + + 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) { + std::cout << "Camera needs " + std::to_string(buffers.size()) + + " requests, can't test only " + + std::to_string(numRequests) << std::endl; + GTEST_SKIP(); + } + + queueCount_ = 0; + captureCount_ = 0; + captureLimit_ = numRequests; + + /* Queue the recommended number of requests. */ + for (const std::unique_ptr<FrameBuffer> &buffer : buffers) { + std::unique_ptr<Request> request = camera_->createRequest(); + ASSERT_TRUE(request) << "Can't create request"; + + ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; + + ASSERT_EQ(queueRequest(request.get()), 0) << "Failed to queue request"; + + requests_.push_back(std::move(request)); + } + + /* Run capture session. */ + loop_ = new EventLoop(); + loop_->exec(); + stop(); + delete loop_; + + ASSERT_EQ(captureCount_, captureLimit_); +} + +int CaptureBalanced::queueRequest(Request *request) +{ + queueCount_++; + if (queueCount_ > captureLimit_) + return 0; + + return camera_->queueRequest(request); +} + +void CaptureBalanced::requestComplete(Request *request) +{ + EXPECT_EQ(request->status(), Request::Status::RequestComplete) + << "Request didn't complete successfully"; + + captureCount_++; + if (captureCount_ >= captureLimit_) { + loop_->exit(0); + return; + } + + request->reuse(Request::ReuseBuffers); + if (queueRequest(request)) + loop_->exit(-EINVAL); +} + +/* CaptureUnbalanced */ + +CaptureUnbalanced::CaptureUnbalanced(std::shared_ptr<Camera> camera) + : Capture(camera) +{ +} + +void CaptureUnbalanced::capture(unsigned int numRequests) +{ + start(); + + Stream *stream = config_->at(0).stream(); + const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_->buffers(stream); + + captureCount_ = 0; + captureLimit_ = numRequests; + + /* Queue the recommended number of requests. */ + for (const std::unique_ptr<FrameBuffer> &buffer : buffers) { + std::unique_ptr<Request> request = camera_->createRequest(); + ASSERT_TRUE(request) << "Can't create request"; + + ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; + + ASSERT_EQ(camera_->queueRequest(request.get()), 0) << "Failed to queue request"; + + requests_.push_back(std::move(request)); + } + + /* Run capture session. */ + loop_ = new EventLoop(); + int status = loop_->exec(); + stop(); + delete loop_; + + ASSERT_EQ(status, 0); +} + +void CaptureUnbalanced::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 (camera_->queueRequest(request)) + loop_->exit(-EINVAL); +} diff --git a/src/apps/lc-compliance/helpers/capture.h b/src/apps/lc-compliance/helpers/capture.h new file mode 100644 index 00000000..0574ab1c --- /dev/null +++ b/src/apps/lc-compliance/helpers/capture.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020-2021, Google Inc. + * + * simple_capture.h - Simple capture helper + */ + +#pragma once + +#include <memory> + +#include <libcamera/libcamera.h> + +#include "../common/event_loop.h" + +class Capture +{ +public: + void configure(libcamera::StreamRole role); + +protected: + Capture(std::shared_ptr<libcamera::Camera> camera); + virtual ~Capture(); + + void start(); + void stop(); + + virtual void requestComplete(libcamera::Request *request) = 0; + + EventLoop *loop_; + + std::shared_ptr<libcamera::Camera> camera_; + std::unique_ptr<libcamera::FrameBufferAllocator> allocator_; + std::unique_ptr<libcamera::CameraConfiguration> config_; + std::vector<std::unique_ptr<libcamera::Request>> requests_; +}; + +class CaptureBalanced : public Capture +{ +public: + CaptureBalanced(std::shared_ptr<libcamera::Camera> camera); + + void capture(unsigned int numRequests); + +private: + int queueRequest(libcamera::Request *request); + void requestComplete(libcamera::Request *request) override; + + unsigned int queueCount_; + unsigned int captureCount_; + unsigned int captureLimit_; +}; + +class CaptureUnbalanced : public Capture +{ +public: + CaptureUnbalanced(std::shared_ptr<libcamera::Camera> camera); + + void capture(unsigned int numRequests); + +private: + void requestComplete(libcamera::Request *request) override; + + unsigned int captureCount_; + unsigned int captureLimit_; +}; |