[RFC PATCH v2 13/16] apps: lc-compliance: Merge `CaptureBalanced` and `CaptureUnbalanced`
Paul Elder
paul.elder at ideasonboard.com
Thu Jan 23 02:56:19 CET 2025
On Tue, Jan 14, 2025 at 06:22:52PM +0000, Barnabás Pőcze wrote:
> The above two classes implement very similar, in fact, the only essential
> difference is how many requests are queued. `CaptureBalanced` queues
> a predetermined number of requests, while `CaptureUnbalanced` queues
> requests without limit.
>
> This can be addressed by introducing a "capture" and a "queue" limit
> into the `Capture` class, which determine at most how many requests
> can be queued, and how many request completions are expected before
> stopping.
>
> Signed-off-by: Barnabás Pőcze <pobrn at protonmail.com>
With Jacopo's comments addressed,
Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>
> ---
> src/apps/lc-compliance/helpers/capture.cpp | 141 +++++++-----------
> src/apps/lc-compliance/helpers/capture.h | 50 ++-----
> src/apps/lc-compliance/tests/capture_test.cpp | 12 +-
> 3 files changed, 71 insertions(+), 132 deletions(-)
>
> diff --git a/src/apps/lc-compliance/helpers/capture.cpp b/src/apps/lc-compliance/helpers/capture.cpp
> index 43db15d2d..77e87c9e4 100644
> --- a/src/apps/lc-compliance/helpers/capture.cpp
> +++ b/src/apps/lc-compliance/helpers/capture.cpp
> @@ -7,12 +7,14 @@
>
> #include "capture.h"
>
> +#include <assert.h>
> +
> #include <gtest/gtest.h>
>
> using namespace libcamera;
>
> Capture::Capture(std::shared_ptr<Camera> camera)
> - : loop_(nullptr), camera_(std::move(camera)),
> + : camera_(std::move(camera)),
> allocator_(camera_)
> {
> }
> @@ -40,153 +42,110 @@ void Capture::configure(StreamRole role)
> }
> }
>
> -void Capture::start()
> +void Capture::run(unsigned int captureLimit, std::optional<unsigned int> queueLimit)
> {
> - Stream *stream = config_->at(0).stream();
> - int count = allocator_.allocate(stream);
> + assert(!queueLimit || captureLimit <= *queueLimit);
>
> - ASSERT_GE(count, 0) << "Failed to allocate buffers";
> - EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected";
> + captureLimit_ = captureLimit;
> + queueLimit_ = queueLimit;
>
> - camera_->requestCompleted.connect(this, &Capture::requestComplete);
> + captureCount_ = queueCount_ = 0;
>
> - ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
> -}
> + EventLoop loop;
> + loop_ = &loop;
>
> -void Capture::stop()
> -{
> - if (!config_ || !allocator_.allocated())
> - return;
> + start();
> + prepareRequests(queueLimit_);
>
> - camera_->stop();
> + for (const auto &request : requests_)
> + queueRequest(request.get());
>
> - camera_->requestCompleted.disconnect(this);
> + EXPECT_EQ(loop_->exec(), 0);
>
> - Stream *stream = config_->at(0).stream();
> - requests_.clear();
> - allocator_.free(stream);
> -}
> + stop();
>
> -/* CaptureBalanced */
> + loop_ = nullptr;
>
> -CaptureBalanced::CaptureBalanced(std::shared_ptr<Camera> camera)
> - : Capture(std::move(camera))
> -{
> + EXPECT_LE(captureLimit_, captureCount_);
> + EXPECT_LE(captureCount_, queueCount_);
> + EXPECT_TRUE(!queueLimit_ || queueCount_ <= *queueLimit_);
> }
>
> -void CaptureBalanced::capture(unsigned int numRequests)
> +void Capture::prepareRequests(std::optional<unsigned int> queueLimit)
> {
> - start();
> + assert(config_);
> + assert(requests_.empty());
>
> 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) {
> + if (queueLimit && *queueLimit < buffers.size()) {
> GTEST_SKIP() << "Camera needs " << buffers.size()
> - << " requests, can't test only " << numRequests;
> + << " requests, can't test only " << *queueLimit;
> }
>
> - 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)
> +int Capture::queueRequest(libcamera::Request *request)
> {
> - queueCount_++;
> - if (queueCount_ > captureLimit_)
> + if (queueLimit_ && queueCount_ >= *queueLimit_)
> return 0;
>
> - return camera_->queueRequest(request);
> + if (int ret = camera_->queueRequest(request); ret < 0)
> + return ret;
> +
> + queueCount_ += 1;
> + return 0;
> }
>
> -void CaptureBalanced::requestComplete(Request *request)
> +void Capture::requestComplete(Request *request)
> {
> - EXPECT_EQ(request->status(), Request::Status::RequestComplete)
> - << "Request didn't complete successfully";
> -
> 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);
> }
>
> -/* CaptureUnbalanced */
> -
> -CaptureUnbalanced::CaptureUnbalanced(std::shared_ptr<Camera> camera)
> - : Capture(std::move(camera))
> -{
> -}
> -
> -void CaptureUnbalanced::capture(unsigned int numRequests)
> +void Capture::start()
> {
> - 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";
> + int count = allocator_.allocate(stream);
>
> - requests_.push_back(std::move(request));
> - }
> + ASSERT_GE(count, 0) << "Failed to allocate buffers";
> + EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected";
>
> - /* Run capture session. */
> - loop_ = new EventLoop();
> - int status = loop_->exec();
> - stop();
> - delete loop_;
> + camera_->requestCompleted.connect(this, &Capture::requestComplete);
>
> - ASSERT_EQ(status, 0);
> + ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
> }
>
> -void CaptureUnbalanced::requestComplete(Request *request)
> +void Capture::stop()
> {
> - captureCount_++;
> - if (captureCount_ >= captureLimit_) {
> - loop_->exit(0);
> + if (!config_ || !allocator_.allocated())
> return;
> - }
>
> - EXPECT_EQ(request->status(), Request::Status::RequestComplete)
> - << "Request didn't complete successfully";
> + camera_->stop();
>
> - request->reuse(Request::ReuseBuffers);
> - if (camera_->queueRequest(request))
> - loop_->exit(-EINVAL);
> + camera_->requestCompleted.disconnect(this);
> +
> + Stream *stream = config_->at(0).stream();
> + requests_.clear();
> + allocator_.free(stream);
> }
> diff --git a/src/apps/lc-compliance/helpers/capture.h b/src/apps/lc-compliance/helpers/capture.h
> index a4cc3a99e..173421fd2 100644
> --- a/src/apps/lc-compliance/helpers/capture.h
> +++ b/src/apps/lc-compliance/helpers/capture.h
> @@ -8,6 +8,7 @@
> #pragma once
>
> #include <memory>
> +#include <optional>
>
> #include <libcamera/libcamera.h>
>
> @@ -16,51 +17,30 @@
> class Capture
> {
> public:
> + Capture(std::shared_ptr<libcamera::Camera> camera);
> + ~Capture();
> +
> void configure(libcamera::StreamRole role);
> + void run(unsigned int captureLimit, std::optional<unsigned int> queueLimit = {});
>
> -protected:
> - Capture(std::shared_ptr<libcamera::Camera> camera);
> - virtual ~Capture();
> +private:
> + LIBCAMERA_DISABLE_COPY_AND_MOVE(Capture)
>
> void start();
> void stop();
>
> - virtual void requestComplete(libcamera::Request *request) = 0;
> -
> - EventLoop *loop_;
> + void prepareRequests(std::optional<unsigned int> queueLimit = {});
> + int queueRequest(libcamera::Request *request);
> + void requestComplete(libcamera::Request *request);
>
> std::shared_ptr<libcamera::Camera> camera_;
> 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_;
> + EventLoop *loop_ = nullptr;
> + unsigned int captureLimit_ = 0;
> + std::optional<unsigned int> queueLimit_;
> + unsigned int captureCount_ = 0;
> + unsigned int queueCount_ = 0;
> };
> diff --git a/src/apps/lc-compliance/tests/capture_test.cpp b/src/apps/lc-compliance/tests/capture_test.cpp
> index 97465a612..93bed48f0 100644
> --- a/src/apps/lc-compliance/tests/capture_test.cpp
> +++ b/src/apps/lc-compliance/tests/capture_test.cpp
> @@ -87,11 +87,11 @@ TEST_P(SingleStream, Capture)
> {
> auto [role, numRequests] = GetParam();
>
> - CaptureBalanced capture(camera_);
> + Capture capture(camera_);
>
> capture.configure(role);
>
> - capture.capture(numRequests);
> + capture.run(numRequests, numRequests);
> }
>
> /*
> @@ -106,12 +106,12 @@ TEST_P(SingleStream, CaptureStartStop)
> auto [role, numRequests] = GetParam();
> unsigned int numRepeats = 3;
>
> - CaptureBalanced capture(camera_);
> + Capture capture(camera_);
>
> capture.configure(role);
>
> for (unsigned int starts = 0; starts < numRepeats; starts++)
> - capture.capture(numRequests);
> + capture.run(numRequests, numRequests);
> }
>
> /*
> @@ -125,11 +125,11 @@ TEST_P(SingleStream, UnbalancedStop)
> {
> auto [role, numRequests] = GetParam();
>
> - CaptureUnbalanced capture(camera_);
> + Capture capture(camera_);
>
> capture.configure(role);
>
> - capture.capture(numRequests);
> + capture.run(numRequests);
> }
>
> INSTANTIATE_TEST_SUITE_P(CaptureTests,
> --
> 2.48.0
>
>
More information about the libcamera-devel
mailing list