apps: lc-compliance: Merge CaptureBalanced
and CaptureUnbalanced
The above two classes have very similar implementations, 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@protonmail.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
This commit is contained in:
parent
995bb7e507
commit
74c0e8cbf1
3 changed files with 102 additions and 169 deletions
|
@ -7,13 +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)),
|
||||
allocator_(camera_)
|
||||
: camera_(std::move(camera)), allocator_(camera_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -40,14 +41,91 @@ void Capture::configure(StreamRole role)
|
|||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
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";
|
||||
|
||||
const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_.buffers(stream);
|
||||
|
||||
/* No point in testing less requests then the camera depth. */
|
||||
if (queueLimit_ && *queueLimit_ < buffers.size()) {
|
||||
GTEST_SKIP() << "Camera needs " << buffers.size()
|
||||
<< " requests, can't test only " << *queueLimit_;
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
requests_.push_back(std::move(request));
|
||||
}
|
||||
|
||||
camera_->requestCompleted.connect(this, &Capture::requestComplete);
|
||||
|
||||
ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
|
||||
|
@ -66,127 +144,3 @@ void Capture::stop()
|
|||
requests_.clear();
|
||||
allocator_.free(stream);
|
||||
}
|
||||
|
||||
/* CaptureBalanced */
|
||||
|
||||
CaptureBalanced::CaptureBalanced(std::shared_ptr<Camera> camera)
|
||||
: Capture(std::move(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) {
|
||||
GTEST_SKIP() << "Camera needs " << buffers.size()
|
||||
<< " requests, can't test only " << numRequests;
|
||||
}
|
||||
|
||||
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(std::move(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);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <libcamera/libcamera.h>
|
||||
|
||||
|
@ -16,51 +17,29 @@
|
|||
class Capture
|
||||
{
|
||||
public:
|
||||
void configure(libcamera::StreamRole role);
|
||||
|
||||
protected:
|
||||
Capture(std::shared_ptr<libcamera::Camera> camera);
|
||||
virtual ~Capture();
|
||||
~Capture();
|
||||
|
||||
void configure(libcamera::StreamRole role);
|
||||
void run(unsigned int captureLimit, std::optional<unsigned int> queueLimit = {});
|
||||
|
||||
private:
|
||||
LIBCAMERA_DISABLE_COPY_AND_MOVE(Capture)
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
virtual void requestComplete(libcamera::Request *request) = 0;
|
||||
|
||||
EventLoop *loop_;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue