ipa: rpi: pisp: Add decompand support using PiSP hardware block
This patch integrates a new decompand algorithm that utilizes the PiSP FE hardware block available on Raspberry Pi 5. The implementation enables conversion of companded sensor data into linear format prior to ISP processing. Changes include: - Implementation of decompand logic for controller and pipe interfaces - Enabling decompand block by "rpi.decompand" in tuning.json Signed-off-by: Sena Asotani <aso.fam429@gmail.com> Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Tested-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com> Reviewed-by: David Plowman <david.plowman@raspberrypi.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
committed by
Kieran Bingham
parent
f0f2aca566
commit
bfd09aa474
8
src/ipa/rpi/controller/decompand_status.h
Normal file
8
src/ipa/rpi/controller/decompand_status.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "libipa/pwl.h"
|
||||
|
||||
struct DecompandStatus {
|
||||
uint32_t bitdepth;
|
||||
libcamera::ipa::Pwl decompandCurve;
|
||||
};
|
||||
@@ -14,6 +14,7 @@ rpi_ipa_controller_sources = files([
|
||||
'rpi/cac.cpp',
|
||||
'rpi/ccm.cpp',
|
||||
'rpi/contrast.cpp',
|
||||
'rpi/decompand.cpp',
|
||||
'rpi/denoise.cpp',
|
||||
'rpi/dpc.cpp',
|
||||
'rpi/geq.cpp',
|
||||
|
||||
58
src/ipa/rpi/controller/rpi/decompand.cpp
Normal file
58
src/ipa/rpi/controller/rpi/decompand.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "decompand.h"
|
||||
|
||||
#include <libcamera/base/log.h>
|
||||
|
||||
#include "../decompand_status.h"
|
||||
#include "../histogram.h"
|
||||
|
||||
using namespace RPiController;
|
||||
using namespace libcamera;
|
||||
|
||||
LOG_DEFINE_CATEGORY(RPiDecompand)
|
||||
|
||||
#define NAME "rpi.decompand"
|
||||
|
||||
Decompand::Decompand(Controller *controller)
|
||||
: Algorithm(controller)
|
||||
{
|
||||
}
|
||||
|
||||
char const *Decompand::name() const
|
||||
{
|
||||
return NAME;
|
||||
}
|
||||
|
||||
int Decompand::read(const libcamera::YamlObject ¶ms)
|
||||
{
|
||||
config_.bitdepth = params["bitdepth"].get<uint32_t>(0);
|
||||
config_.decompandCurve = params["decompand_curve"].get<ipa::Pwl>(ipa::Pwl{});
|
||||
return config_.decompandCurve.empty() ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
void Decompand::initialise()
|
||||
{
|
||||
}
|
||||
|
||||
void Decompand::switchMode(CameraMode const &cameraMode,
|
||||
[[maybe_unused]] Metadata *metadata)
|
||||
{
|
||||
mode_ = cameraMode;
|
||||
}
|
||||
|
||||
void Decompand::prepare(Metadata *imageMetadata)
|
||||
{
|
||||
DecompandStatus decompandStatus;
|
||||
|
||||
if (config_.bitdepth == 0 || mode_.bitdepth == config_.bitdepth) {
|
||||
decompandStatus.decompandCurve = config_.decompandCurve;
|
||||
imageMetadata->set("decompand.status", decompandStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register algorithm with the system. */
|
||||
static Algorithm *create(Controller *controller)
|
||||
{
|
||||
return new Decompand(controller);
|
||||
}
|
||||
|
||||
static RegisterAlgorithm reg(NAME, &create);
|
||||
31
src/ipa/rpi/controller/rpi/decompand.h
Normal file
31
src/ipa/rpi/controller/rpi/decompand.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <libipa/pwl.h>
|
||||
|
||||
#include "../decompand_status.h"
|
||||
|
||||
#include "algorithm.h"
|
||||
|
||||
namespace RPiController {
|
||||
|
||||
struct DecompandConfig {
|
||||
uint32_t bitdepth;
|
||||
libcamera::ipa::Pwl decompandCurve;
|
||||
};
|
||||
|
||||
class Decompand : public Algorithm
|
||||
{
|
||||
public:
|
||||
Decompand(Controller *controller = nullptr);
|
||||
char const *name() const override;
|
||||
int read(const libcamera::YamlObject ¶ms) override;
|
||||
void initialise() override;
|
||||
void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
|
||||
void prepare(Metadata *imageMetadata) override;
|
||||
|
||||
private:
|
||||
CameraMode mode_;
|
||||
DecompandConfig config_;
|
||||
};
|
||||
|
||||
} /* namespace RPiController */
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "controller/cac_status.h"
|
||||
#include "controller/ccm_status.h"
|
||||
#include "controller/contrast_status.h"
|
||||
#include "controller/decompand_status.h"
|
||||
#include "controller/denoise_algorithm.h"
|
||||
#include "controller/denoise_status.h"
|
||||
#include "controller/dpc_status.h"
|
||||
@@ -113,6 +114,25 @@ int generateLut(const ipa::Pwl &pwl, uint32_t *lut, std::size_t lutSize,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateDecompandLut(const ipa::Pwl &pwl, Span<uint16_t> lut)
|
||||
{
|
||||
if (pwl.empty())
|
||||
return -EINVAL;
|
||||
|
||||
constexpr int step = 1024;
|
||||
for (std::size_t i = 0; i < lut.size(); ++i) {
|
||||
int x = i * step;
|
||||
|
||||
int y = pwl.eval(x);
|
||||
if (y < 0)
|
||||
return -1;
|
||||
|
||||
lut[i] = static_cast<uint16_t>(std::min(y, 65535));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void packLscLut(uint32_t packed[NumLscVertexes][NumLscVertexes],
|
||||
double const rgb[3][NumLscVertexes][NumLscVertexes])
|
||||
{
|
||||
@@ -236,6 +256,7 @@ private:
|
||||
void applyLensShading(const AlscStatus *alscStatus,
|
||||
pisp_be_global_config &global);
|
||||
void applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global);
|
||||
void applyDecompand(const DecompandStatus *decompandStatus);
|
||||
void applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global);
|
||||
void applyTdn(const TdnStatus *tdnStatus, const DeviceStatus *deviceStatus,
|
||||
pisp_be_global_config &global);
|
||||
@@ -351,6 +372,11 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms,
|
||||
if (noiseStatus)
|
||||
applyFocusStats(noiseStatus);
|
||||
|
||||
DecompandStatus *decompandStatus =
|
||||
rpiMetadata.getLocked<DecompandStatus>("decompand.status");
|
||||
if (decompandStatus)
|
||||
applyDecompand(decompandStatus);
|
||||
|
||||
BlackLevelStatus *blackLevelStatus =
|
||||
rpiMetadata.getLocked<BlackLevelStatus>("black_level.status");
|
||||
if (blackLevelStatus)
|
||||
@@ -702,6 +728,18 @@ void IpaPiSP::applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global
|
||||
be_->SetDpc(dpc);
|
||||
}
|
||||
|
||||
void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus)
|
||||
{
|
||||
pisp_fe_global_config feGlobal;
|
||||
pisp_fe_decompand_config decompand = {};
|
||||
|
||||
if (!generateDecompandLut(decompandStatus->decompandCurve, decompand.lut)) {
|
||||
fe_->SetDecompand(decompand);
|
||||
feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND;
|
||||
fe_->SetGlobal(feGlobal);
|
||||
}
|
||||
}
|
||||
|
||||
void IpaPiSP::applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global)
|
||||
{
|
||||
pisp_be_sdn_config sdn = {};
|
||||
|
||||
Reference in New Issue
Block a user