An attempt at getting image data back
This commit is contained in:
184
spider-cam/libcamera/test/ipa/ipa_interface_test.cpp
Normal file
184
spider-cam/libcamera/test/ipa/ipa_interface_test.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/* 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)
|
||||
73
spider-cam/libcamera/test/ipa/ipa_module_test.cpp
Normal file
73
spider-cam/libcamera/test/ipa/ipa_module_test.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* Test loading of the VIMC IPA module and verify its info
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
#include "libcamera/internal/ipa_module.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libcamera;
|
||||
|
||||
class IPAModuleTest : public Test
|
||||
{
|
||||
protected:
|
||||
int runTest(const string &path, const struct IPAModuleInfo &testInfo)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
IPAModule *ll = new IPAModule(path);
|
||||
|
||||
if (!ll->isValid()) {
|
||||
cerr << "test IPA module " << path << " is invalid"
|
||||
<< endl;
|
||||
delete ll;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const struct IPAModuleInfo &info = ll->info();
|
||||
|
||||
if (memcmp(&info, &testInfo, sizeof(info))) {
|
||||
cerr << "IPA module information mismatch: expected:" << endl
|
||||
<< "moduleAPIVersion = " << testInfo.moduleAPIVersion << endl
|
||||
<< "pipelineVersion = " << testInfo.pipelineVersion << endl
|
||||
<< "pipelineName = " << testInfo.pipelineName << endl
|
||||
<< "name = " << testInfo.name
|
||||
<< "got: " << endl
|
||||
<< "moduleAPIVersion = " << info.moduleAPIVersion << endl
|
||||
<< "pipelineVersion = " << info.pipelineVersion << endl
|
||||
<< "pipelineName = " << info.pipelineName << endl
|
||||
<< "name = " << info.name << endl;
|
||||
}
|
||||
|
||||
delete ll;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
const struct IPAModuleInfo testInfo = {
|
||||
IPA_MODULE_API_VERSION,
|
||||
0,
|
||||
"vimc",
|
||||
"vimc",
|
||||
};
|
||||
|
||||
count += runTest("src/ipa/vimc/ipa_vimc.so", testInfo);
|
||||
|
||||
if (count < 0)
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_REGISTER(IPAModuleTest)
|
||||
17
spider-cam/libcamera/test/ipa/meson.build
Normal file
17
spider-cam/libcamera/test/ipa/meson.build
Normal file
@@ -0,0 +1,17 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
subdir('rkisp1')
|
||||
|
||||
ipa_test = [
|
||||
{'name': 'ipa_module_test', 'sources': ['ipa_module_test.cpp']},
|
||||
{'name': 'ipa_interface_test', 'sources': ['ipa_interface_test.cpp']},
|
||||
]
|
||||
|
||||
foreach test : ipa_test
|
||||
exe = executable(test['name'], test['sources'], libcamera_generated_ipa_headers,
|
||||
dependencies : [libcamera_private, libipa_dep],
|
||||
link_with : [test_libraries],
|
||||
include_directories : [test_includes_internal])
|
||||
|
||||
test(test['name'], exe, suite : 'ipa')
|
||||
endforeach
|
||||
15
spider-cam/libcamera/test/ipa/rkisp1/meson.build
Normal file
15
spider-cam/libcamera/test/ipa/rkisp1/meson.build
Normal file
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
rkisp1_ipa_test = [
|
||||
{'name': 'rkisp1-utils', 'sources': ['rkisp1-utils.cpp']},
|
||||
]
|
||||
|
||||
foreach test : rkisp1_ipa_test
|
||||
exe = executable(test['name'], test['sources'], libcamera_generated_ipa_headers,
|
||||
dependencies : [libcamera_private, libipa_dep],
|
||||
link_with : [test_libraries],
|
||||
include_directories : [test_includes_internal,
|
||||
'../../../src/ipa/rkisp1/'])
|
||||
|
||||
test(test['name'], exe, suite : 'ipa')
|
||||
endforeach
|
||||
108
spider-cam/libcamera/test/ipa/rkisp1/rkisp1-utils.cpp
Normal file
108
spider-cam/libcamera/test/ipa/rkisp1/rkisp1-utils.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
|
||||
*
|
||||
* Miscellaneous utility tests
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../src/ipa/rkisp1/utils.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libcamera;
|
||||
using namespace ipa::rkisp1;
|
||||
|
||||
class RkISP1UtilsTest : public Test
|
||||
{
|
||||
protected:
|
||||
/* R for real, I for integer */
|
||||
template<unsigned int IntPrec, unsigned int FracPrec, typename I, typename R>
|
||||
int testFixedToFloat(I input, R expected)
|
||||
{
|
||||
R out = utils::fixedToFloatingPoint<IntPrec, FracPrec, R>(input);
|
||||
R prec = 1.0 / (1 << FracPrec);
|
||||
if (std::abs(out - expected) > prec) {
|
||||
cerr << "Reverse conversion expected " << input
|
||||
<< " to convert to " << expected
|
||||
<< ", got " << out << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
template<unsigned int IntPrec, unsigned int FracPrec, typename T>
|
||||
int testSingleFixedPoint(double input, T expected)
|
||||
{
|
||||
T ret = utils::floatingToFixedPoint<IntPrec, FracPrec, T>(input);
|
||||
if (ret != expected) {
|
||||
cerr << "Expected " << input << " to convert to "
|
||||
<< expected << ", got " << ret << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* The precision check is fairly arbitrary but is based on what
|
||||
* the rkisp1 is capable of in the crosstalk module.
|
||||
*/
|
||||
double f = utils::fixedToFloatingPoint<IntPrec, FracPrec, double>(ret);
|
||||
if (std::abs(f - input) > 0.005) {
|
||||
cerr << "Reverse conversion expected " << ret
|
||||
<< " to convert to " << input
|
||||
<< ", got " << f << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int testFixedPoint()
|
||||
{
|
||||
/*
|
||||
* The second 7.992 test is to test that unused bits don't
|
||||
* affect the result.
|
||||
*/
|
||||
std::map<double, uint16_t> testCases = {
|
||||
{ 7.992, 0x3ff },
|
||||
{ 0.2, 0x01a },
|
||||
{ -0.2, 0x7e6 },
|
||||
{ -0.8, 0x79a },
|
||||
{ -0.4, 0x7cd },
|
||||
{ -1.4, 0x74d },
|
||||
{ -8, 0x400 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
int ret;
|
||||
for (const auto &testCase : testCases) {
|
||||
ret = testSingleFixedPoint<4, 7, uint16_t>(testCase.first,
|
||||
testCase.second);
|
||||
if (ret != TestPass)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Special case with a superfluous one in the unused bits */
|
||||
ret = testFixedToFloat<4, 7, uint16_t, double>(0xbff, 7.992);
|
||||
if (ret != TestPass)
|
||||
return ret;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
/* fixed point conversion test */
|
||||
if (testFixedPoint() != TestPass)
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_REGISTER(RkISP1UtilsTest)
|
||||
Reference in New Issue
Block a user