An attempt at getting image data back
This commit is contained in:
182
spider-cam/libcamera/test/camera/buffer_import.cpp
Normal file
182
spider-cam/libcamera/test/camera/buffer_import.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* libcamera Camera API tests
|
||||
*
|
||||
* Test importing buffers exported from the VIVID output device into a Camera
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include <libcamera/base/event_dispatcher.h>
|
||||
#include <libcamera/base/thread.h>
|
||||
#include <libcamera/base/timer.h>
|
||||
|
||||
#include "libcamera/internal/device_enumerator.h"
|
||||
#include "libcamera/internal/media_device.h"
|
||||
#include "libcamera/internal/v4l2_videodevice.h"
|
||||
|
||||
#include "buffer_source.h"
|
||||
#include "camera_test.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
|
||||
class BufferImportTest : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
BufferImportTest()
|
||||
: CameraTest("platform/vimc.0 Sensor B")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void bufferComplete([[maybe_unused]] Request *request,
|
||||
FrameBuffer *buffer)
|
||||
{
|
||||
if (buffer->metadata().status != FrameMetadata::FrameSuccess)
|
||||
return;
|
||||
|
||||
completeBuffersCount_++;
|
||||
}
|
||||
|
||||
void requestComplete(Request *request)
|
||||
{
|
||||
if (request->status() != Request::RequestComplete)
|
||||
return;
|
||||
|
||||
const Request::BufferMap &buffers = request->buffers();
|
||||
|
||||
completeRequestsCount_++;
|
||||
|
||||
/* Create a new request. */
|
||||
const Stream *stream = buffers.begin()->first;
|
||||
FrameBuffer *buffer = buffers.begin()->second;
|
||||
|
||||
request->reuse();
|
||||
request->addBuffer(stream, buffer);
|
||||
camera_->queueRequest(request);
|
||||
|
||||
dispatcher_->interrupt();
|
||||
}
|
||||
|
||||
int init() override
|
||||
{
|
||||
if (status_ != TestPass)
|
||||
return status_;
|
||||
|
||||
config_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||
if (!config_ || config_->size() != 1) {
|
||||
std::cout << "Failed to generate default configuration" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
dispatcher_ = Thread::current()->eventDispatcher();
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
StreamConfiguration &cfg = config_->at(0);
|
||||
|
||||
if (camera_->acquire()) {
|
||||
std::cout << "Failed to acquire the camera" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (camera_->configure(config_.get())) {
|
||||
std::cout << "Failed to set default configuration" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
Stream *stream = cfg.stream();
|
||||
|
||||
BufferSource source;
|
||||
int ret = source.allocate(cfg);
|
||||
if (ret != TestPass)
|
||||
return ret;
|
||||
|
||||
for (const std::unique_ptr<FrameBuffer> &buffer : source.buffers()) {
|
||||
std::unique_ptr<Request> request = camera_->createRequest();
|
||||
if (!request) {
|
||||
std::cout << "Failed to create request" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (request->addBuffer(stream, buffer.get())) {
|
||||
std::cout << "Failed to associating buffer with request" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
requests_.push_back(std::move(request));
|
||||
}
|
||||
|
||||
completeRequestsCount_ = 0;
|
||||
completeBuffersCount_ = 0;
|
||||
|
||||
camera_->bufferCompleted.connect(this, &BufferImportTest::bufferComplete);
|
||||
camera_->requestCompleted.connect(this, &BufferImportTest::requestComplete);
|
||||
|
||||
if (camera_->start()) {
|
||||
std::cout << "Failed to start camera" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
for (std::unique_ptr<Request> &request : requests_) {
|
||||
if (camera_->queueRequest(request.get())) {
|
||||
std::cout << "Failed to queue request" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int nFrames = cfg.bufferCount * 2;
|
||||
|
||||
Timer timer;
|
||||
timer.start(500ms * nFrames);
|
||||
while (timer.isRunning()) {
|
||||
dispatcher_->processEvents();
|
||||
if (completeRequestsCount_ > nFrames)
|
||||
break;
|
||||
}
|
||||
|
||||
if (completeRequestsCount_ < nFrames) {
|
||||
std::cout << "Failed to capture enough frames (got "
|
||||
<< completeRequestsCount_ << " expected at least "
|
||||
<< nFrames << ")" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (completeRequestsCount_ != completeBuffersCount_) {
|
||||
std::cout << "Number of completed buffers and requests differ" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (camera_->stop()) {
|
||||
std::cout << "Failed to stop camera" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
private:
|
||||
EventDispatcher *dispatcher_;
|
||||
|
||||
std::vector<std::unique_ptr<Request>> requests_;
|
||||
|
||||
unsigned int completeBuffersCount_;
|
||||
unsigned int completeRequestsCount_;
|
||||
std::unique_ptr<CameraConfiguration> config_;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
TEST_REGISTER(BufferImportTest)
|
||||
264
spider-cam/libcamera/test/camera/camera_reconfigure.cpp
Normal file
264
spider-cam/libcamera/test/camera/camera_reconfigure.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2021, Google Inc.
|
||||
*
|
||||
* Test:
|
||||
* - Multiple reconfigurations of the Camera without stopping the CameraManager
|
||||
* - Validate there are no file descriptor leaks when using IPC
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <libcamera/base/event_dispatcher.h>
|
||||
#include <libcamera/base/file.h>
|
||||
#include <libcamera/base/thread.h>
|
||||
#include <libcamera/base/timer.h>
|
||||
|
||||
#include <libcamera/framebuffer_allocator.h>
|
||||
|
||||
#include "camera_test.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
|
||||
class CameraReconfigure : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
/* Initialize CameraTest with isolated IPA */
|
||||
CameraReconfigure()
|
||||
: CameraTest(kCamId_, true)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr const char *kCamId_ = "platform/vimc.0 Sensor B";
|
||||
static constexpr const char *kIpaProxyName_ = "vimc_ipa_proxy";
|
||||
static constexpr unsigned int kNumOfReconfigures_ = 10;
|
||||
|
||||
void requestComplete(Request *request)
|
||||
{
|
||||
if (request->status() != Request::RequestComplete)
|
||||
return;
|
||||
|
||||
const Request::BufferMap &buffers = request->buffers();
|
||||
|
||||
const Stream *stream = buffers.begin()->first;
|
||||
FrameBuffer *buffer = buffers.begin()->second;
|
||||
|
||||
/* Reuse the request and re-queue it with the same buffers. */
|
||||
request->reuse();
|
||||
request->addBuffer(stream, buffer);
|
||||
camera_->queueRequest(request);
|
||||
}
|
||||
|
||||
int startAndStop()
|
||||
{
|
||||
StreamConfiguration &cfg = config_->at(0);
|
||||
|
||||
if (camera_->acquire()) {
|
||||
cerr << "Failed to acquire the camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (camera_->configure(config_.get())) {
|
||||
cerr << "Failed to set default configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
Stream *stream = cfg.stream();
|
||||
|
||||
/*
|
||||
* The configuration is consistent so we can re-use the
|
||||
* same buffer allocation for each run.
|
||||
*/
|
||||
if (!allocated_) {
|
||||
int ret = allocator_->allocate(stream);
|
||||
if (ret < 0) {
|
||||
cerr << "Failed to allocate buffers" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
allocated_ = true;
|
||||
}
|
||||
|
||||
for (const unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) {
|
||||
unique_ptr<Request> request = camera_->createRequest();
|
||||
if (!request) {
|
||||
cerr << "Failed to create request" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (request->addBuffer(stream, buffer.get())) {
|
||||
cerr << "Failed to associate buffer with request" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
requests_.push_back(std::move(request));
|
||||
}
|
||||
|
||||
camera_->requestCompleted.connect(this, &CameraReconfigure::requestComplete);
|
||||
|
||||
if (camera_->start()) {
|
||||
cerr << "Failed to start camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
for (unique_ptr<Request> &request : requests_) {
|
||||
if (camera_->queueRequest(request.get())) {
|
||||
cerr << "Failed to queue request" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
}
|
||||
|
||||
EventDispatcher *dispatcher = Thread::current()->eventDispatcher();
|
||||
|
||||
Timer timer;
|
||||
timer.start(100ms);
|
||||
while (timer.isRunning())
|
||||
dispatcher->processEvents();
|
||||
|
||||
if (camera_->stop()) {
|
||||
cerr << "Failed to stop camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (camera_->release()) {
|
||||
cerr << "Failed to release camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
camera_->requestCompleted.disconnect(this);
|
||||
|
||||
requests_.clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdsOpen(pid_t pid)
|
||||
{
|
||||
string proxyFdPath = "/proc/" + to_string(pid) + "/fd";
|
||||
DIR *dir;
|
||||
struct dirent *ptr;
|
||||
unsigned int openFds = 0;
|
||||
|
||||
dir = opendir(proxyFdPath.c_str());
|
||||
if (dir == nullptr) {
|
||||
int err = errno;
|
||||
cerr << "Error opening " << proxyFdPath << ": "
|
||||
<< strerror(-err) << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((ptr = readdir(dir)) != nullptr) {
|
||||
if ((strcmp(ptr->d_name, ".") == 0) ||
|
||||
(strcmp(ptr->d_name, "..") == 0))
|
||||
continue;
|
||||
|
||||
openFds++;
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return openFds;
|
||||
}
|
||||
|
||||
pid_t findProxyPid()
|
||||
{
|
||||
string proxyPid;
|
||||
string proxyName(kIpaProxyName_);
|
||||
DIR *dir;
|
||||
struct dirent *ptr;
|
||||
|
||||
dir = opendir("/proc");
|
||||
while ((ptr = readdir(dir)) != nullptr) {
|
||||
if (ptr->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
string pname("/proc/" + string(ptr->d_name) + "/comm");
|
||||
if (File::exists(pname)) {
|
||||
ifstream pfile(pname.c_str());
|
||||
string comm;
|
||||
getline(pfile, comm);
|
||||
pfile.close();
|
||||
|
||||
proxyPid = comm == proxyName ? string(ptr->d_name) : "";
|
||||
}
|
||||
|
||||
if (!proxyPid.empty())
|
||||
break;
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
if (!proxyPid.empty())
|
||||
return atoi(proxyPid.c_str());
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int init() override
|
||||
{
|
||||
if (status_ != TestPass)
|
||||
return status_;
|
||||
|
||||
config_ = camera_->generateConfiguration({ StreamRole::StillCapture });
|
||||
if (!config_ || config_->size() != 1) {
|
||||
cerr << "Failed to generate default configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
allocator_ = make_unique<FrameBufferAllocator>(camera_);
|
||||
allocated_ = false;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
unsigned int openFdsAtStart = 0;
|
||||
unsigned int openFds = 0;
|
||||
|
||||
pid_t proxyPid = findProxyPid();
|
||||
if (proxyPid < 0) {
|
||||
cerr << "Cannot find " << kIpaProxyName_
|
||||
<< " pid, exiting" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
openFdsAtStart = fdsOpen(proxyPid);
|
||||
for (unsigned int i = 0; i < kNumOfReconfigures_; i++) {
|
||||
startAndStop();
|
||||
openFds = fdsOpen(proxyPid);
|
||||
if (openFds == 0) {
|
||||
cerr << "No open fds found whereas "
|
||||
<< "open fds at start: " << openFdsAtStart
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (openFds != openFdsAtStart) {
|
||||
cerr << "Leaking fds for " << kIpaProxyName_
|
||||
<< " - Open fds: " << openFds << " vs "
|
||||
<< "Open fds at start: " << openFdsAtStart
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
bool allocated_;
|
||||
|
||||
vector<unique_ptr<Request>> requests_;
|
||||
|
||||
unique_ptr<CameraConfiguration> config_;
|
||||
unique_ptr<FrameBufferAllocator> allocator_;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
TEST_REGISTER(CameraReconfigure)
|
||||
181
spider-cam/libcamera/test/camera/capture.cpp
Normal file
181
spider-cam/libcamera/test/camera/capture.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* libcamera Camera API tests
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <libcamera/framebuffer_allocator.h>
|
||||
|
||||
#include <libcamera/base/event_dispatcher.h>
|
||||
#include <libcamera/base/thread.h>
|
||||
#include <libcamera/base/timer.h>
|
||||
|
||||
#include "camera_test.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace {
|
||||
|
||||
class Capture : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
Capture()
|
||||
: CameraTest("platform/vimc.0 Sensor B")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
unsigned int completeBuffersCount_;
|
||||
unsigned int completeRequestsCount_;
|
||||
|
||||
void bufferComplete([[maybe_unused]] Request *request,
|
||||
FrameBuffer *buffer)
|
||||
{
|
||||
if (buffer->metadata().status != FrameMetadata::FrameSuccess)
|
||||
return;
|
||||
|
||||
completeBuffersCount_++;
|
||||
}
|
||||
|
||||
void requestComplete(Request *request)
|
||||
{
|
||||
if (request->status() != Request::RequestComplete)
|
||||
return;
|
||||
|
||||
const Request::BufferMap &buffers = request->buffers();
|
||||
|
||||
completeRequestsCount_++;
|
||||
|
||||
/* Create a new request. */
|
||||
const Stream *stream = buffers.begin()->first;
|
||||
FrameBuffer *buffer = buffers.begin()->second;
|
||||
|
||||
request->reuse();
|
||||
request->addBuffer(stream, buffer);
|
||||
camera_->queueRequest(request);
|
||||
|
||||
dispatcher_->interrupt();
|
||||
}
|
||||
|
||||
int init() override
|
||||
{
|
||||
if (status_ != TestPass)
|
||||
return status_;
|
||||
|
||||
config_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||
if (!config_ || config_->size() != 1) {
|
||||
cout << "Failed to generate default configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
allocator_ = new FrameBufferAllocator(camera_);
|
||||
dispatcher_ = Thread::current()->eventDispatcher();
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
void cleanup() override
|
||||
{
|
||||
delete allocator_;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
StreamConfiguration &cfg = config_->at(0);
|
||||
|
||||
if (camera_->acquire()) {
|
||||
cout << "Failed to acquire the camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (camera_->configure(config_.get())) {
|
||||
cout << "Failed to set default configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
Stream *stream = cfg.stream();
|
||||
|
||||
int ret = allocator_->allocate(stream);
|
||||
if (ret < 0)
|
||||
return TestFail;
|
||||
|
||||
for (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) {
|
||||
std::unique_ptr<Request> request = camera_->createRequest();
|
||||
if (!request) {
|
||||
cout << "Failed to create request" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (request->addBuffer(stream, buffer.get())) {
|
||||
cout << "Failed to associate buffer with request" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
requests_.push_back(std::move(request));
|
||||
}
|
||||
|
||||
completeRequestsCount_ = 0;
|
||||
completeBuffersCount_ = 0;
|
||||
|
||||
camera_->bufferCompleted.connect(this, &Capture::bufferComplete);
|
||||
camera_->requestCompleted.connect(this, &Capture::requestComplete);
|
||||
|
||||
if (camera_->start()) {
|
||||
cout << "Failed to start camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
for (std::unique_ptr<Request> &request : requests_) {
|
||||
if (camera_->queueRequest(request.get())) {
|
||||
cout << "Failed to queue request" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int nFrames = allocator_->buffers(stream).size() * 2;
|
||||
|
||||
Timer timer;
|
||||
timer.start(500ms * nFrames);
|
||||
while (timer.isRunning()) {
|
||||
dispatcher_->processEvents();
|
||||
if (completeRequestsCount_ > nFrames)
|
||||
break;
|
||||
}
|
||||
|
||||
if (completeRequestsCount_ < nFrames) {
|
||||
cout << "Failed to capture enough frames (got "
|
||||
<< completeRequestsCount_ << " expected at least "
|
||||
<< nFrames * 2 << ")" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (completeRequestsCount_ != completeBuffersCount_) {
|
||||
cout << "Number of completed buffers and requests differ" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (camera_->stop()) {
|
||||
cout << "Failed to stop camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
EventDispatcher *dispatcher_;
|
||||
|
||||
std::vector<std::unique_ptr<Request>> requests_;
|
||||
|
||||
std::unique_ptr<CameraConfiguration> config_;
|
||||
FrameBufferAllocator *allocator_;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
TEST_REGISTER(Capture)
|
||||
60
spider-cam/libcamera/test/camera/configuration_default.cpp
Normal file
60
spider-cam/libcamera/test/camera/configuration_default.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* libcamera Camera API tests
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "camera_test.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
class ConfigurationDefault : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
ConfigurationDefault()
|
||||
: CameraTest("platform/vimc.0 Sensor B")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
int init() override
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
std::unique_ptr<CameraConfiguration> config;
|
||||
|
||||
/* Test asking for configuration for a video stream. */
|
||||
config = camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||
if (!config || config->size() != 1) {
|
||||
cout << "Default configuration invalid" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that asking for configuration for an empty array of
|
||||
* stream roles returns an empty camera configuration.
|
||||
*/
|
||||
config = camera_->generateConfiguration({});
|
||||
if (!config || config->size() != 0) {
|
||||
cout << "Failed to retrieve configuration for empty roles list"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
TEST_REGISTER(ConfigurationDefault)
|
||||
106
spider-cam/libcamera/test/camera/configuration_set.cpp
Normal file
106
spider-cam/libcamera/test/camera/configuration_set.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* libcamera Camera API tests
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "camera_test.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
class ConfigurationSet : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
ConfigurationSet()
|
||||
: CameraTest("platform/vimc.0 Sensor B")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
int init() override
|
||||
{
|
||||
if (status_ != TestPass)
|
||||
return status_;
|
||||
|
||||
config_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||
if (!config_ || config_->size() != 1) {
|
||||
cout << "Failed to generate default configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
StreamConfiguration &cfg = config_->at(0);
|
||||
|
||||
if (camera_->acquire()) {
|
||||
cout << "Failed to acquire the camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* Test that setting the default configuration works. */
|
||||
if (camera_->configure(config_.get())) {
|
||||
cout << "Failed to set default configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that configuring the camera fails if it is not
|
||||
* acquired, this will also test release and reacquiring
|
||||
* of the camera.
|
||||
*/
|
||||
if (camera_->release()) {
|
||||
cout << "Failed to release the camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (!camera_->configure(config_.get())) {
|
||||
cout << "Setting configuration on a camera not acquired succeeded when it should have failed"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (camera_->acquire()) {
|
||||
cout << "Failed to acquire the camera" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that modifying the default configuration works. Doubling
|
||||
* the default configuration of the VIMC camera is known to
|
||||
* work.
|
||||
*/
|
||||
cfg.size.width *= 2;
|
||||
cfg.size.height *= 2;
|
||||
if (camera_->configure(config_.get())) {
|
||||
cout << "Failed to set modified configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that setting an invalid configuration fails.
|
||||
*/
|
||||
cfg.size = { 0, 0 };
|
||||
if (!camera_->configure(config_.get())) {
|
||||
cout << "Invalid configuration incorrectly accepted" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
std::unique_ptr<CameraConfiguration> config_;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
TEST_REGISTER(ConfigurationSet)
|
||||
20
spider-cam/libcamera/test/camera/meson.build
Normal file
20
spider-cam/libcamera/test/camera/meson.build
Normal file
@@ -0,0 +1,20 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
# Tests are listed in order of complexity.
|
||||
# They are not alphabetically sorted.
|
||||
camera_tests = [
|
||||
{'name': 'configuration_default', 'sources': ['configuration_default.cpp']},
|
||||
{'name': 'configuration_set', 'sources': ['configuration_set.cpp']},
|
||||
{'name': 'buffer_import', 'sources': ['buffer_import.cpp']},
|
||||
{'name': 'statemachine', 'sources': ['statemachine.cpp']},
|
||||
{'name': 'capture', 'sources': ['capture.cpp']},
|
||||
{'name': 'camera_reconfigure', 'sources': ['camera_reconfigure.cpp']},
|
||||
]
|
||||
|
||||
foreach test : camera_tests
|
||||
exe = executable(test['name'], test['sources'],
|
||||
dependencies : libcamera_private,
|
||||
link_with : test_libraries,
|
||||
include_directories : test_includes_internal)
|
||||
test(test['name'], exe, suite : 'camera', is_parallel : false)
|
||||
endforeach
|
||||
216
spider-cam/libcamera/test/camera/statemachine.cpp
Normal file
216
spider-cam/libcamera/test/camera/statemachine.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* libcamera Camera API tests
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <libcamera/framebuffer_allocator.h>
|
||||
|
||||
#include "camera_test.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
class Statemachine : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
Statemachine()
|
||||
: CameraTest("platform/vimc.0 Sensor B")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
int testAvailable()
|
||||
{
|
||||
/* Test operations which should fail. */
|
||||
if (camera_->configure(defconf_.get()) != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
if (camera_->createRequest())
|
||||
return TestFail;
|
||||
|
||||
if (camera_->start() != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
Request request(camera_.get());
|
||||
if (camera_->queueRequest(&request) != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
/* Test operations which should pass. */
|
||||
if (camera_->release())
|
||||
return TestFail;
|
||||
|
||||
if (camera_->stop())
|
||||
return TestFail;
|
||||
|
||||
/* Test valid state transitions, end in Acquired state. */
|
||||
if (camera_->acquire())
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int testAcquired()
|
||||
{
|
||||
/* Test operations which should fail. */
|
||||
if (camera_->acquire() != -EBUSY)
|
||||
return TestFail;
|
||||
|
||||
if (camera_->createRequest())
|
||||
return TestFail;
|
||||
|
||||
if (camera_->start() != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
Request request(camera_.get());
|
||||
if (camera_->queueRequest(&request) != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
/* Test operations which should pass. */
|
||||
if (camera_->stop())
|
||||
return TestFail;
|
||||
|
||||
/* Test valid state transitions, end in Configured state. */
|
||||
if (camera_->release())
|
||||
return TestFail;
|
||||
|
||||
if (camera_->acquire())
|
||||
return TestFail;
|
||||
|
||||
if (camera_->configure(defconf_.get()))
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int testConfigured()
|
||||
{
|
||||
/* Test operations which should fail. */
|
||||
if (camera_->acquire() != -EBUSY)
|
||||
return TestFail;
|
||||
|
||||
Request request1(camera_.get());
|
||||
if (camera_->queueRequest(&request1) != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
/* Test operations which should pass. */
|
||||
std::unique_ptr<Request> request2 = camera_->createRequest();
|
||||
if (!request2)
|
||||
return TestFail;
|
||||
|
||||
if (camera_->stop())
|
||||
return TestFail;
|
||||
|
||||
/* Test valid state transitions, end in Running state. */
|
||||
if (camera_->release())
|
||||
return TestFail;
|
||||
|
||||
if (camera_->acquire())
|
||||
return TestFail;
|
||||
|
||||
if (camera_->configure(defconf_.get()))
|
||||
return TestFail;
|
||||
|
||||
/* Use internally allocated buffers. */
|
||||
allocator_ = new FrameBufferAllocator(camera_);
|
||||
Stream *stream = *camera_->streams().begin();
|
||||
if (allocator_->allocate(stream) < 0)
|
||||
return TestFail;
|
||||
|
||||
if (camera_->start())
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int testRuning()
|
||||
{
|
||||
/* Test operations which should fail. */
|
||||
if (camera_->acquire() != -EBUSY)
|
||||
return TestFail;
|
||||
|
||||
if (camera_->release() != -EBUSY)
|
||||
return TestFail;
|
||||
|
||||
if (camera_->configure(defconf_.get()) != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
if (camera_->start() != -EACCES)
|
||||
return TestFail;
|
||||
|
||||
/* Test operations which should pass. */
|
||||
std::unique_ptr<Request> request = camera_->createRequest();
|
||||
if (!request)
|
||||
return TestFail;
|
||||
|
||||
Stream *stream = *camera_->streams().begin();
|
||||
if (request->addBuffer(stream, allocator_->buffers(stream)[0].get()))
|
||||
return TestFail;
|
||||
|
||||
if (camera_->queueRequest(request.get()))
|
||||
return TestFail;
|
||||
|
||||
/* Test valid state transitions, end in Available state. */
|
||||
if (camera_->stop())
|
||||
return TestFail;
|
||||
|
||||
delete allocator_;
|
||||
|
||||
if (camera_->release())
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int init() override
|
||||
{
|
||||
if (status_ != TestPass)
|
||||
return status_;
|
||||
|
||||
defconf_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||
if (!defconf_) {
|
||||
cout << "Failed to generate default configuration" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
if (testAvailable() != TestPass) {
|
||||
cout << "State machine in Available state failed" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (testAcquired() != TestPass) {
|
||||
cout << "State machine in Acquired state failed" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (testConfigured() != TestPass) {
|
||||
cout << "State machine in Configured state failed" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (testRuning() != TestPass) {
|
||||
cout << "State machine in Running state failed" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
std::unique_ptr<CameraConfiguration> defconf_;
|
||||
FrameBufferAllocator *allocator_;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
TEST_REGISTER(Statemachine)
|
||||
Reference in New Issue
Block a user