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 "capture.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
using namespace libcamera;
|
using namespace libcamera;
|
||||||
|
|
||||||
Capture::Capture(std::shared_ptr<Camera> camera)
|
Capture::Capture(std::shared_ptr<Camera> camera)
|
||||||
: loop_(nullptr), camera_(std::move(camera)),
|
: camera_(std::move(camera)), allocator_(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()
|
void Capture::start()
|
||||||
{
|
{
|
||||||
|
assert(config_);
|
||||||
|
assert(!config_->empty());
|
||||||
|
assert(!allocator_.allocated());
|
||||||
|
assert(requests_.empty());
|
||||||
|
|
||||||
Stream *stream = config_->at(0).stream();
|
Stream *stream = config_->at(0).stream();
|
||||||
int count = allocator_.allocate(stream);
|
int count = allocator_.allocate(stream);
|
||||||
|
|
||||||
ASSERT_GE(count, 0) << "Failed to allocate buffers";
|
ASSERT_GE(count, 0) << "Failed to allocate buffers";
|
||||||
EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected";
|
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);
|
camera_->requestCompleted.connect(this, &Capture::requestComplete);
|
||||||
|
|
||||||
ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
|
ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
|
||||||
|
@ -66,127 +144,3 @@ void Capture::stop()
|
||||||
requests_.clear();
|
requests_.clear();
|
||||||
allocator_.free(stream);
|
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
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <libcamera/libcamera.h>
|
#include <libcamera/libcamera.h>
|
||||||
|
|
||||||
|
@ -16,51 +17,29 @@
|
||||||
class Capture
|
class Capture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void configure(libcamera::StreamRole role);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Capture(std::shared_ptr<libcamera::Camera> camera);
|
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 start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
virtual void requestComplete(libcamera::Request *request) = 0;
|
int queueRequest(libcamera::Request *request);
|
||||||
|
void requestComplete(libcamera::Request *request);
|
||||||
EventLoop *loop_;
|
|
||||||
|
|
||||||
std::shared_ptr<libcamera::Camera> camera_;
|
std::shared_ptr<libcamera::Camera> camera_;
|
||||||
libcamera::FrameBufferAllocator allocator_;
|
libcamera::FrameBufferAllocator allocator_;
|
||||||
std::unique_ptr<libcamera::CameraConfiguration> config_;
|
std::unique_ptr<libcamera::CameraConfiguration> config_;
|
||||||
std::vector<std::unique_ptr<libcamera::Request>> requests_;
|
std::vector<std::unique_ptr<libcamera::Request>> requests_;
|
||||||
};
|
|
||||||
|
EventLoop *loop_ = nullptr;
|
||||||
class CaptureBalanced : public Capture
|
unsigned int captureLimit_ = 0;
|
||||||
{
|
std::optional<unsigned int> queueLimit_;
|
||||||
public:
|
unsigned int captureCount_ = 0;
|
||||||
CaptureBalanced(std::shared_ptr<libcamera::Camera> camera);
|
unsigned int queueCount_ = 0;
|
||||||
|
|
||||||
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_;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -87,11 +87,11 @@ TEST_P(SingleStream, Capture)
|
||||||
{
|
{
|
||||||
auto [role, numRequests] = GetParam();
|
auto [role, numRequests] = GetParam();
|
||||||
|
|
||||||
CaptureBalanced capture(camera_);
|
Capture capture(camera_);
|
||||||
|
|
||||||
capture.configure(role);
|
capture.configure(role);
|
||||||
|
|
||||||
capture.capture(numRequests);
|
capture.run(numRequests, numRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,12 +106,12 @@ TEST_P(SingleStream, CaptureStartStop)
|
||||||
auto [role, numRequests] = GetParam();
|
auto [role, numRequests] = GetParam();
|
||||||
unsigned int numRepeats = 3;
|
unsigned int numRepeats = 3;
|
||||||
|
|
||||||
CaptureBalanced capture(camera_);
|
Capture capture(camera_);
|
||||||
|
|
||||||
capture.configure(role);
|
capture.configure(role);
|
||||||
|
|
||||||
for (unsigned int starts = 0; starts < numRepeats; starts++)
|
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();
|
auto [role, numRequests] = GetParam();
|
||||||
|
|
||||||
CaptureUnbalanced capture(camera_);
|
Capture capture(camera_);
|
||||||
|
|
||||||
capture.configure(role);
|
capture.configure(role);
|
||||||
|
|
||||||
capture.capture(numRequests);
|
capture.run(numRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(CaptureTests,
|
INSTANTIATE_TEST_SUITE_P(CaptureTests,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue