9a913eb910
In the simple capture tests, in the capture functions, the Requests were auto-deallocated by the function going out of scope after the test completed. However, before the end of the scope, the Framebuffers that the Requests referred to were manually freed. Thus when the Requests were deallocated, they tried to cancel their Framebuffers, which involve setting the status to cancelled, which obviously causes a segfault because the Framebuffers had already been freed. Fix this by moving the list of Requests to a member variable and deallocating them before deallocating the Framebuffers at stop() time. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
191 lines
4.3 KiB
C++
191 lines
4.3 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2020-2021, Google Inc.
|
|
*
|
|
* simple_capture.cpp - Simple capture helper
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "simple_capture.h"
|
|
|
|
using namespace libcamera;
|
|
|
|
SimpleCapture::SimpleCapture(std::shared_ptr<Camera> camera)
|
|
: loop_(nullptr), camera_(camera),
|
|
allocator_(std::make_unique<FrameBufferAllocator>(camera))
|
|
{
|
|
}
|
|
|
|
SimpleCapture::~SimpleCapture()
|
|
{
|
|
stop();
|
|
}
|
|
|
|
void SimpleCapture::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 SimpleCapture::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, &SimpleCapture::requestComplete);
|
|
|
|
ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
|
|
}
|
|
|
|
void SimpleCapture::stop()
|
|
{
|
|
if (!config_ || !allocator_->allocated())
|
|
return;
|
|
|
|
camera_->stop();
|
|
|
|
camera_->requestCompleted.disconnect(this);
|
|
|
|
Stream *stream = config_->at(0).stream();
|
|
requests_.clear();
|
|
allocator_->free(stream);
|
|
}
|
|
|
|
/* SimpleCaptureBalanced */
|
|
|
|
SimpleCaptureBalanced::SimpleCaptureBalanced(std::shared_ptr<Camera> camera)
|
|
: SimpleCapture(camera)
|
|
{
|
|
}
|
|
|
|
void SimpleCaptureBalanced::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 reqeuests. */
|
|
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 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);
|
|
}
|
|
|
|
/* SimpleCaptureUnbalanced */
|
|
|
|
SimpleCaptureUnbalanced::SimpleCaptureUnbalanced(std::shared_ptr<Camera> camera)
|
|
: SimpleCapture(camera)
|
|
{
|
|
}
|
|
|
|
void SimpleCaptureUnbalanced::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 reqeuests. */
|
|
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 SimpleCaptureUnbalanced::requestComplete(Request *request)
|
|
{
|
|
captureCount_++;
|
|
if (captureCount_ >= captureLimit_) {
|
|
loop_->exit(0);
|
|
return;
|
|
}
|
|
|
|
request->reuse(Request::ReuseBuffers);
|
|
if (camera_->queueRequest(request))
|
|
loop_->exit(-EINVAL);
|
|
}
|