pipeline: ipa: raspberrypi: Refactor and move the Raspberry Pi code
Split the Raspberry Pi pipeline handler and IPA source code into common
and VC4/BCM2835 specific file structures.
For the pipeline handler, the common code files now live in
src/libcamera/pipeline/rpi/common/
and the VC4-specific files in src/libcamera/pipeline/rpi/vc4/.
For the IPA, the common code files now live in
src/ipa/rpi/{cam_helper,controller}/
and the vc4 specific files in src/ipa/rpi/vc4/. With this change, the
camera tuning files are now installed under share/libcamera/ipa/rpi/vc4/.
To build the pipeline and IPA, the meson configuration options have now
changed from "raspberrypi" to "rpi/vc4":
meson setup build -Dipas=rpi/vc4 -Dpipelines=rpi/vc4
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
committed by
Laurent Pinchart
parent
46aefed208
commit
726e9274ea
@@ -0,0 +1,181 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2019, Raspberry Pi Ltd
|
||||
*
|
||||
* controller.cpp - ISP controller
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <libcamera/base/file.h>
|
||||
#include <libcamera/base/log.h>
|
||||
|
||||
#include "libcamera/internal/yaml_parser.h"
|
||||
|
||||
#include "algorithm.h"
|
||||
#include "controller.h"
|
||||
|
||||
using namespace RPiController;
|
||||
using namespace libcamera;
|
||||
|
||||
LOG_DEFINE_CATEGORY(RPiController)
|
||||
|
||||
static const std::map<std::string, Controller::HardwareConfig> HardwareConfigMap = {
|
||||
{
|
||||
"bcm2835",
|
||||
{
|
||||
/*
|
||||
* There are only ever 15 AGC regions computed by the firmware
|
||||
* due to zoning, but the HW defines AGC_REGIONS == 16!
|
||||
*/
|
||||
.agcRegions = { 15 , 1 },
|
||||
.agcZoneWeights = { 15 , 1 },
|
||||
.awbRegions = { 16, 12 },
|
||||
.focusRegions = { 4, 3 },
|
||||
.numHistogramBins = 128,
|
||||
.numGammaPoints = 33,
|
||||
.pipelineWidth = 13
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Controller::Controller()
|
||||
: switchModeCalled_(false)
|
||||
{
|
||||
}
|
||||
|
||||
Controller::~Controller() {}
|
||||
|
||||
int Controller::read(char const *filename)
|
||||
{
|
||||
File file(filename);
|
||||
if (!file.open(File::OpenModeFlag::ReadOnly)) {
|
||||
LOG(RPiController, Warning)
|
||||
<< "Failed to open tuning file '" << filename << "'";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
std::unique_ptr<YamlObject> root = YamlParser::parse(file);
|
||||
double version = (*root)["version"].get<double>(1.0);
|
||||
target_ = (*root)["target"].get<std::string>("bcm2835");
|
||||
|
||||
if (version < 2.0) {
|
||||
LOG(RPiController, Warning)
|
||||
<< "This format of the tuning file will be deprecated soon!"
|
||||
<< " Please use the convert_tuning.py utility to update to version 2.0.";
|
||||
|
||||
for (auto const &[key, value] : root->asDict()) {
|
||||
int ret = createAlgorithm(key, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else if (version < 3.0) {
|
||||
if (!root->contains("algorithms")) {
|
||||
LOG(RPiController, Error)
|
||||
<< "Tuning file " << filename
|
||||
<< " does not have an \"algorithms\" list!";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (auto const &rootAlgo : (*root)["algorithms"].asList())
|
||||
for (auto const &[key, value] : rootAlgo.asDict()) {
|
||||
int ret = createAlgorithm(key, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
LOG(RPiController, Error)
|
||||
<< "Unrecognised version " << version
|
||||
<< " for the tuning file " << filename;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Controller::createAlgorithm(const std::string &name, const YamlObject ¶ms)
|
||||
{
|
||||
auto it = getAlgorithms().find(name);
|
||||
if (it == getAlgorithms().end()) {
|
||||
LOG(RPiController, Warning)
|
||||
<< "No algorithm found for \"" << name << "\"";
|
||||
return 0;
|
||||
}
|
||||
|
||||
Algorithm *algo = (*it->second)(this);
|
||||
int ret = algo->read(params);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
algorithms_.push_back(AlgorithmPtr(algo));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Controller::initialise()
|
||||
{
|
||||
for (auto &algo : algorithms_)
|
||||
algo->initialise();
|
||||
}
|
||||
|
||||
void Controller::switchMode(CameraMode const &cameraMode, Metadata *metadata)
|
||||
{
|
||||
for (auto &algo : algorithms_)
|
||||
algo->switchMode(cameraMode, metadata);
|
||||
switchModeCalled_ = true;
|
||||
}
|
||||
|
||||
void Controller::prepare(Metadata *imageMetadata)
|
||||
{
|
||||
assert(switchModeCalled_);
|
||||
for (auto &algo : algorithms_)
|
||||
algo->prepare(imageMetadata);
|
||||
}
|
||||
|
||||
void Controller::process(StatisticsPtr stats, Metadata *imageMetadata)
|
||||
{
|
||||
assert(switchModeCalled_);
|
||||
for (auto &algo : algorithms_)
|
||||
algo->process(stats, imageMetadata);
|
||||
}
|
||||
|
||||
Metadata &Controller::getGlobalMetadata()
|
||||
{
|
||||
return globalMetadata_;
|
||||
}
|
||||
|
||||
Algorithm *Controller::getAlgorithm(std::string const &name) const
|
||||
{
|
||||
/*
|
||||
* The passed name must be the entire algorithm name, or must match the
|
||||
* last part of it with a period (.) just before.
|
||||
*/
|
||||
size_t nameLen = name.length();
|
||||
for (auto &algo : algorithms_) {
|
||||
char const *algoName = algo->name();
|
||||
size_t algoNameLen = strlen(algoName);
|
||||
if (algoNameLen >= nameLen &&
|
||||
strcasecmp(name.c_str(),
|
||||
algoName + algoNameLen - nameLen) == 0 &&
|
||||
(nameLen == algoNameLen ||
|
||||
algoName[algoNameLen - nameLen - 1] == '.'))
|
||||
return algo.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string &Controller::getTarget() const
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
|
||||
const Controller::HardwareConfig &Controller::getHardwareConfig() const
|
||||
{
|
||||
auto cfg = HardwareConfigMap.find(getTarget());
|
||||
|
||||
/*
|
||||
* This really should not happen, the IPA ought to validate the target
|
||||
* on initialisation.
|
||||
*/
|
||||
ASSERT(cfg != HardwareConfigMap.end());
|
||||
return cfg->second;
|
||||
}
|
||||
Reference in New Issue
Block a user