spidermqtt/spider-cam/libcamera/test/ipa/ipa_interface_test.cpp

185 lines
4.5 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* Test the IPA interface
*/
#include <fcntl.h>
#include <iostream>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <libcamera/ipa/vimc_ipa_proxy.h>
#include <libcamera/base/event_dispatcher.h>
#include <libcamera/base/event_notifier.h>
#include <libcamera/base/object.h>
#include <libcamera/base/thread.h>
#include <libcamera/base/timer.h>
#include "libcamera/internal/device_enumerator.h"
#include "libcamera/internal/ipa_manager.h"
#include "libcamera/internal/ipa_module.h"
#include "libcamera/internal/pipeline_handler.h"
#include "libcamera/internal/process.h"
#include "test.h"
using namespace libcamera;
using namespace std;
using namespace std::chrono_literals;
class IPAInterfaceTest : public Test, public Object
{
public:
IPAInterfaceTest()
: trace_(ipa::vimc::IPAOperationNone), notifier_(nullptr), fd_(-1)
{
}
~IPAInterfaceTest()
{
delete notifier_;
ipa_.reset();
ipaManager_.reset();
}
protected:
int init() override
{
ipaManager_ = make_unique<IPAManager>();
/* Create a pipeline handler for vimc. */
const std::vector<PipelineHandlerFactoryBase *> &factories =
PipelineHandlerFactoryBase::factories();
for (const PipelineHandlerFactoryBase *factory : factories) {
if (factory->name() == "vimc") {
pipe_ = factory->create(nullptr);
break;
}
}
if (!pipe_) {
cerr << "Vimc pipeline not found" << endl;
return TestPass;
}
/* Create and open the communication FIFO. */
int ret = mkfifo(ipa::vimc::VimcIPAFIFOPath.c_str(), S_IRUSR | S_IWUSR);
if (ret) {
ret = errno;
cerr << "Failed to create IPA test FIFO at '"
<< ipa::vimc::VimcIPAFIFOPath << "': " << strerror(ret)
<< endl;
return TestFail;
}
ret = open(ipa::vimc::VimcIPAFIFOPath.c_str(), O_RDONLY | O_NONBLOCK);
if (ret < 0) {
ret = errno;
cerr << "Failed to open IPA test FIFO at '"
<< ipa::vimc::VimcIPAFIFOPath << "': " << strerror(ret)
<< endl;
unlink(ipa::vimc::VimcIPAFIFOPath.c_str());
return TestFail;
}
fd_ = ret;
notifier_ = new EventNotifier(fd_, EventNotifier::Read, this);
notifier_->activated.connect(this, &IPAInterfaceTest::readTrace);
return TestPass;
}
int run() override
{
EventDispatcher *dispatcher = thread()->eventDispatcher();
Timer timer;
ipa_ = IPAManager::createIPA<ipa::vimc::IPAProxyVimc>(pipe_.get(), 0, 0);
if (!ipa_) {
cerr << "Failed to create VIMC IPA interface" << endl;
return TestFail;
}
/* Test initialization of IPA module. */
std::string conf = ipa_->configurationFile("vimc.conf");
Flags<ipa::vimc::TestFlag> inFlags;
Flags<ipa::vimc::TestFlag> outFlags;
int ret = ipa_->init(IPASettings{ conf, "vimc" },
ipa::vimc::IPAOperationInit,
inFlags, &outFlags);
if (ret < 0) {
cerr << "IPA interface init() failed" << endl;
return TestFail;
}
timer.start(1000ms);
while (timer.isRunning() && trace_ != ipa::vimc::IPAOperationInit)
dispatcher->processEvents();
if (trace_ != ipa::vimc::IPAOperationInit) {
cerr << "Failed to test IPA initialization sequence"
<< endl;
return TestFail;
}
/* Test start of IPA module. */
ipa_->start();
timer.start(1000ms);
while (timer.isRunning() && trace_ != ipa::vimc::IPAOperationStart)
dispatcher->processEvents();
if (trace_ != ipa::vimc::IPAOperationStart) {
cerr << "Failed to test IPA start sequence" << endl;
return TestFail;
}
/* Test stop of IPA module. */
ipa_->stop();
timer.start(1000ms);
while (timer.isRunning() && trace_ != ipa::vimc::IPAOperationStop)
dispatcher->processEvents();
if (trace_ != ipa::vimc::IPAOperationStop) {
cerr << "Failed to test IPA stop sequence" << endl;
return TestFail;
}
return TestPass;
}
void cleanup() override
{
close(fd_);
unlink(ipa::vimc::VimcIPAFIFOPath.c_str());
}
private:
void readTrace()
{
ssize_t s = read(notifier_->fd(), &trace_, sizeof(trace_));
if (s < 0) {
int ret = errno;
cerr << "Failed to read from IPA test FIFO at '"
<< ipa::vimc::VimcIPAFIFOPath << "': " << strerror(ret)
<< endl;
trace_ = ipa::vimc::IPAOperationNone;
}
}
ProcessManager processManager_;
std::shared_ptr<PipelineHandler> pipe_;
std::unique_ptr<ipa::vimc::IPAProxyVimc> ipa_;
std::unique_ptr<IPAManager> ipaManager_;
enum ipa::vimc::IPAOperationCode trace_;
EventNotifier *notifier_;
int fd_;
};
TEST_REGISTER(IPAInterfaceTest)