From c85c7a3423df71064f355f4f50932ee777867b21 Mon Sep 17 00:00:00 2001 From: Sena Asotani Date: Tue, 15 Jul 2025 14:52:53 +0900 Subject: [PATCH 1/6] ipa: rpi: pisp: Add decompand support using PiSP hardware block This patch integrates a new decompand algorithm that utilizes the PiSP 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 --- src/ipa/rpi/controller/decompand_algorithm.h | 31 + src/ipa/rpi/controller/decompand_status.h | 8 + src/ipa/rpi/controller/meson.build | 1 + src/ipa/rpi/controller/rpi/decompand.cpp | 71 ++ src/ipa/rpi/controller/rpi/decompand.h | 22 + src/ipa/rpi/pisp/data/imx585.json | 983 +++++++++++++++++++ src/ipa/rpi/pisp/pisp.cpp | 36 + 7 files changed, 1152 insertions(+) create mode 100644 src/ipa/rpi/controller/decompand_algorithm.h create mode 100644 src/ipa/rpi/controller/decompand_status.h create mode 100644 src/ipa/rpi/controller/rpi/decompand.cpp create mode 100644 src/ipa/rpi/controller/rpi/decompand.h create mode 100644 src/ipa/rpi/pisp/data/imx585.json diff --git a/src/ipa/rpi/controller/decompand_algorithm.h b/src/ipa/rpi/controller/decompand_algorithm.h new file mode 100644 index 000000000..a722ef07b --- /dev/null +++ b/src/ipa/rpi/controller/decompand_algorithm.h @@ -0,0 +1,31 @@ +#pragma once + +#include "algorithm.h" + +namespace RPiController { + +class DecompandAlgorithm : public Algorithm +{ +public: + DecompandAlgorithm(Controller *controller) : Algorithm(controller) {} + virtual void initialValues(uint16_t lut[], uint16_t &pad) + { + static const uint16_t defaultLut[] = { + 3072, 3072, 3072, 3072, 3136, 3200, 3264, 3328, + 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, + 3904, 3968, 4032, 4096, 4608, 5120, 5632, 6144, + 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, + 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, + 14848, 15360, 17408, 19456, 21504, 23552, 25600, 27648, + 29696, 31744, 33792, 35840, 37888, 39936, 41984, 44032, + 46080, 48128, 50176, 52224, 54272, 56320, 58368, 60416, + 62464 + }; + + for (size_t i = 0; i < sizeof(defaultLut) / sizeof(defaultLut[0]); ++i) + lut[i] = defaultLut[i]; + + pad = 1; + } +}; +} /* namespace RPiController */ diff --git a/src/ipa/rpi/controller/decompand_status.h b/src/ipa/rpi/controller/decompand_status.h new file mode 100644 index 000000000..23880f3db --- /dev/null +++ b/src/ipa/rpi/controller/decompand_status.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +struct DecompandStatus { + uint16_t lut[65]; + uint16_t pad; +}; diff --git a/src/ipa/rpi/controller/meson.build b/src/ipa/rpi/controller/meson.build index dde4ac127..bdc53e3b9 100644 --- a/src/ipa/rpi/controller/meson.build +++ b/src/ipa/rpi/controller/meson.build @@ -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', diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp new file mode 100644 index 000000000..3e5485f45 --- /dev/null +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -0,0 +1,71 @@ +#include + +#include "../decompand_status.h" + +#include "decompand.h" + +using namespace RPiController; +using namespace libcamera; + +LOG_DEFINE_CATEGORY(RPiDecompand) + +#define NAME "rpi.decompand" + +Decompand::Decompand(Controller *controller) + : DecompandAlgorithm(controller) +{ +} + +char const *Decompand::name() const +{ + return NAME; +} + +int Decompand::read(const libcamera::YamlObject ¶ms) +{ + if (!params.contains("lut") || !params["lut"].isList() || params["lut"].size() != 65) { + LOG(RPiDecompand, Error) << "Expected LUT with 65 elements"; + return -EINVAL; + } + + for (unsigned int i = 0; i < 65; ++i) { + std::optional value = params["lut"][i].get(); + if (!value.has_value()) { + LOG(RPiDecompand, Error) << "Invalid LUT value at index " << i; + return -EINVAL; + } + decompandLUT_[i] = value.value(); + } + decompandpad_ = params["pad"].get(0); + + return 0; +} + +void Decompand::initialValues(uint16_t LUT[], uint16_t &pad) +{ + for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) + { + LUT[i] = decompandLUT_[i]; + } + pad = decompandpad_; +} + +void Decompand::prepare(Metadata *imageMetadata) +{ + struct DecompandStatus status; + for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) + { + status.lut[i] = decompandLUT_[i]; + } + status.pad = decompandpad_; + + imageMetadata->set("decompand.status", status); +} + +/* Register algorithm with the system. */ +static Algorithm *create(Controller *controller) +{ + return new Decompand(controller); +} + +static RegisterAlgorithm reg(NAME, &create); diff --git a/src/ipa/rpi/controller/rpi/decompand.h b/src/ipa/rpi/controller/rpi/decompand.h new file mode 100644 index 000000000..70b006b5c --- /dev/null +++ b/src/ipa/rpi/controller/rpi/decompand.h @@ -0,0 +1,22 @@ +#pragma once + +#include "../decompand_algorithm.h" +#include "../decompand_status.h" + +namespace RPiController { + +class Decompand : public DecompandAlgorithm +{ +public: + Decompand(Controller *controller); + char const *name() const override; + int read(const libcamera::YamlObject ¶ms) override; + void initialValues(uint16_t LUT[], uint16_t &pad) override; + void prepare(Metadata *imageMetadata) override; + +private: + uint16_t decompandLUT_[65]; + uint16_t decompandpad_; +}; + +} /* namespace RPiController */ diff --git a/src/ipa/rpi/pisp/data/imx585.json b/src/ipa/rpi/pisp/data/imx585.json new file mode 100644 index 000000000..6ecdee7dd --- /dev/null +++ b/src/ipa/rpi/pisp/data/imx585.json @@ -0,0 +1,983 @@ +{ + "version": 2.0, + "target": "pisp", + "algorithms": [ + { + "rpi.black_level": + { + "black_level": 3072 + } + }, + { + "rpi.decompand": + { + "lut": [ + 3072, 3072, 3072, 3072, 3136, 3200, 3264, 3328, + 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, + 3904, 3968, 4032, 4096, 4608, 5120, 5632, 6144, + 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, + 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, + 14848, 15360, 17408, 19456, 21504, 23552, 25600, 27648, + 29696, 31744, 33792, 35840, 37888, 39936, 41984, 44032, + 46080, 48128, 50176, 52224, 54272, 56320, 58368, 60416, + 62464 + ], + "pad": 1 + } + }, + { + "rpi.lux": + { + "reference_shutter_speed": 6384, + "reference_gain": 1.0, + "reference_aperture": 1.0, + "reference_lux": 935, + "reference_Y": 11637 + } + }, + { + "rpi.dpc": + { + "strength": 1 + } + }, + { + "rpi.noise": + { + "reference_constant": 12, + "reference_slope": 3.568 + } + }, + { + "rpi.geq": + { + "offset": 192, + "slope": 0.00812 + } + }, + { + "rpi.denoise": + { + "normal": + { + "sdn": + { + "deviation": 1.6, + "strength": 0.5, + "deviation2": 3.2, + "deviation_no_tdn": 3.2, + "strength_no_tdn": 0.75 + }, + "cdn": + { + "deviation": 200, + "strength": 0.3 + }, + "tdn": + { + "deviation": 0.8, + "threshold": 0.05 + } + }, + "hdr": + { + "sdn": + { + "deviation": 1.6, + "strength": 0.5, + "deviation2": 3.2, + "deviation_no_tdn": 3.2, + "strength_no_tdn": 0.75 + }, + "cdn": + { + "deviation": 200, + "strength": 0.3 + }, + "tdn": + { + "deviation": 1.3, + "threshold": 0.1 + } + }, + "night": + { + "sdn": + { + "deviation": 1.6, + "strength": 0.5, + "deviation2": 3.2, + "deviation_no_tdn": 3.2, + "strength_no_tdn": 0.75 + }, + "cdn": + { + "deviation": 200, + "strength": 0.3 + }, + "tdn": + { + "deviation": 1.3, + "threshold": 0.1 + } + } + } + }, + { + "rpi.awb": + { + "priors": [ + { + "lux": 0, + "prior": + [ + 2000, 1.0, + 3000, 0.0, + 13000, 0.0 + ] + }, + { + "lux": 800, + "prior": + [ + 2000, 0.0, + 6000, 2.0, + 13000, 2.0 + ] + }, + { + "lux": 1500, + "prior": + [ + 2000, 0.0, + 4000, 1.0, + 6000, 6.0, + 6500, 7.0, + 7000, 1.0, + 13000, 1.0 + ] + } + ], + "modes": + { + "auto": + { + "lo": 2500, + "hi": 7700 + }, + "incandescent": + { + "lo": 2500, + "hi": 3000 + }, + "tungsten": + { + "lo": 3000, + "hi": 3500 + }, + "fluorescent": + { + "lo": 4000, + "hi": 4700 + }, + "indoor": + { + "lo": 3000, + "hi": 5000 + }, + "daylight": + { + "lo": 5500, + "hi": 6500 + }, + "cloudy": + { + "lo": 7000, + "hi": 8000 + } + }, + "bayes": 1, + "ct_curve": + [ + 2187.0, 1.1114, 0.1026, + 2258.0, 1.1063, 0.1147, + 5225.0, 0.6631, 0.5507, + 5289.0, 0.5769, 0.5731, + 6532.0, 0.5259, 0.5801 + ], + "sensitivity_r": 1.0, + "sensitivity_b": 1.0, + "transverse_pos": 0.13694, + "transverse_neg": 0.08426 + } + }, + { + "rpi.agc": + { + "channels": [ + { + "comment": "Channel 0 is normal AGC", + "metering_modes": + { + "centre-weighted": + { + "weights": + [ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 + ] + }, + "spot": + { + "weights": + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + }, + "matrix": + { + "weights": + [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + ] + } + }, + "exposure_modes": + { + "normal": + { + "shutter": [ 100, 10000, 30000, 60000, 66666 ], + "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ] + }, + "short": + { + "shutter": [ 100, 5000, 10000, 20000, 60000 ], + "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ] + }, + "long": + { + "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ], + "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ] + } + }, + "constraint_modes": + { + "normal": [ + { + "bound": "LOWER", + "q_lo": 0.98, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + } + ], + "highlight": [ + { + "bound": "LOWER", + "q_lo": 0.98, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + }, + { + "bound": "UPPER", + "q_lo": 0.98, + "q_hi": 1.0, + "y_target": + [ + 0, 0.8, + 1000, 0.8 + ] + } + ], + "shadows": [ + { + "bound": "LOWER", + "q_lo": 0.0, + "q_hi": 0.5, + "y_target": + [ + 0, 0.17, + 1000, 0.17 + ] + } + ] + }, + "y_target": + [ + 0, 0.16, + 1000, 0.165, + 10000, 0.17 + ] + }, + { + "comment": "Channel 1 is the HDR short channel", + "desaturate": 0, + "metering_modes": + { + "centre-weighted": + { + "weights": + [ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 + ] + }, + "spot": + { + "weights": + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + }, + "matrix": + { + "weights": + [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + ] + } + }, + "exposure_modes": + { + "normal": + { + "shutter": [ 100, 20000, 60000 ], + "gain": [ 1.0, 1.0, 1.0 ] + }, + "short": + { + "shutter": [ 100, 20000, 60000 ], + "gain": [ 1.0, 1.0, 1.0 ] + }, + "long": + { + "shutter": [ 100, 20000, 60000 ], + "gain": [ 1.0, 1.0, 1.0 ] + } + }, + "constraint_modes": + { + "normal": [ + { + "bound": "LOWER", + "q_lo": 0.95, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + }, + { + "bound": "UPPER", + "q_lo": 0.95, + "q_hi": 1.0, + "y_target": + [ + 0, 0.7, + 1000, 0.7 + ] + }, + { + "bound": "LOWER", + "q_lo": 0.0, + "q_hi": 0.2, + "y_target": + [ + 0, 0.002, + 1000, 0.002 + ] + } + ], + "highlight": [ + { + "bound": "LOWER", + "q_lo": 0.95, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + }, + { + "bound": "UPPER", + "q_lo": 0.95, + "q_hi": 1.0, + "y_target": + [ + 0, 0.7, + 1000, 0.7 + ] + }, + { + "bound": "LOWER", + "q_lo": 0.0, + "q_hi": 0.2, + "y_target": + [ + 0, 0.002, + 1000, 0.002 + ] + } + ], + "shadows": [ + { + "bound": "LOWER", + "q_lo": 0.95, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + }, + { + "bound": "UPPER", + "q_lo": 0.95, + "q_hi": 1.0, + "y_target": + [ + 0, 0.7, + 1000, 0.7 + ] + }, + { + "bound": "LOWER", + "q_lo": 0.0, + "q_hi": 0.2, + "y_target": + [ + 0, 0.002, + 1000, 0.002 + ] + } + ] + }, + "y_target": + [ + 0, 0.16, + 1000, 0.165, + 10000, 0.17 + ] + }, + { + "comment": "Channel 2 is the HDR long channel", + "desaturate": 0, + "metering_modes": + { + "centre-weighted": + { + "weights": + [ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 + ] + }, + "spot": + { + "weights": + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + }, + "matrix": + { + "weights": + [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + ] + } + }, + "exposure_modes": + { + "normal": + { + "shutter": [ 100, 20000, 30000, 60000 ], + "gain": [ 1.0, 2.0, 4.0, 8.0 ] + }, + "short": + { + "shutter": [ 100, 20000, 30000, 60000 ], + "gain": [ 1.0, 2.0, 4.0, 8.0 ] + }, + "long": + { + "shutter": [ 100, 20000, 30000, 60000 ], + "gain": [ 1.0, 2.0, 4.0, 8.0 ] + } + }, + "constraint_modes": + { + "normal": [ ], + "highlight": [ ], + "shadows": [ ] + }, + "channel_constraints": [ + { + "bound": "UPPER", + "channel": 4, + "factor": 8 + }, + { + "bound": "LOWER", + "channel": 4, + "factor": 2 + } + ], + "y_target": + [ + 0, 0.16, + 1000, 0.165, + 10000, 0.17 + ] + }, + { + "comment": "Channel 3 is the night mode channel", + "base_ev": 0.33, + "metering_modes": + { + "centre-weighted": + { + "weights": + [ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 + ] + }, + "spot": + { + "weights": + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + }, + "matrix": + { + "weights": + [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + ] + } + }, + "exposure_modes": + { + "normal": + { + "shutter": [ 100, 20000, 66666 ], + "gain": [ 1.0, 2.0, 4.0 ] + }, + "short": + { + "shutter": [ 100, 20000, 33333 ], + "gain": [ 1.0, 2.0, 4.0 ] + }, + "long": + { + "shutter": [ 100, 20000, 66666, 120000 ], + "gain": [ 1.0, 2.0, 4.0, 4.0 ] + } + }, + "constraint_modes": + { + "normal": [ + { + "bound": "LOWER", + "q_lo": 0.98, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + } + ], + "highlight": [ + { + "bound": "LOWER", + "q_lo": 0.98, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + }, + { + "bound": "UPPER", + "q_lo": 0.98, + "q_hi": 1.0, + "y_target": + [ + 0, 0.8, + 1000, 0.8 + ] + } + ], + "shadows": [ + { + "bound": "LOWER", + "q_lo": 0.98, + "q_hi": 1.0, + "y_target": + [ + 0, 0.5, + 1000, 0.5 + ] + } + ] + }, + "y_target": + [ + 0, 0.16, + 1000, 0.16, + 10000, 0.17 + ] + } + ] + } + }, + { + "rpi.alsc": + { + "omega": 1.3, + "n_iter": 100, + "luminance_strength": 0.8 + } + }, + { + "rpi.contrast": + { + "ce_enable": 1, + "gamma_curve": + [ + 0, 0, + 1024, 5040, + 2048, 9338, + 3072, 12356, + 4096, 15312, + 5120, 18051, + 6144, 20790, + 7168, 23193, + 8192, 25744, + 9216, 27942, + 10240, 30035, + 11264, 32005, + 12288, 33975, + 13312, 35815, + 14336, 37600, + 15360, 39168, + 16384, 40642, + 18432, 43379, + 20480, 45749, + 22528, 47753, + 24576, 49621, + 26624, 51253, + 28672, 52698, + 30720, 53796, + 32768, 54876, + 36864, 57012, + 40960, 58656, + 45056, 59954, + 49152, 61183, + 53248, 62355, + 57344, 63419, + 61440, 64476, + 65535, 65535 + ] + } + }, + { + "rpi.ccm": + { + "ccms": [ + { + "ct": 2187, + "ccm": + [ + 1.91049, -0.78523, -0.12525, + -0.69541, 1.68995, 0.00546, + -0.47685, 0.89308, 0.58376 + ] + }, + { + "ct": 2258, + "ccm": + [ + 1.78809, -0.66968, -0.11841, + -0.67083, 1.69256, -0.02173, + -0.53371, 1.05827, 0.47545 + ] + }, + { + "ct": 5225, + "ccm": + [ + 1.41687, -0.26811, -0.14877, + -0.37784, 1.28381, 0.09403, + 0.04629, -0.42973, 1.38344 + ] + }, + { + "ct": 5289, + "ccm": + [ + 1.42939, -0.40792, -0.02147, + -0.27719, 1.46177, -0.18458, + 0.08958, -0.63362, 1.54404 + ] + }, + { + "ct": 6532, + "ccm": + [ + 1.46551, -0.24251, -0.22301, + -0.42242, 1.64605, -0.22363, + 0.02631, -0.42478, 1.39847 + ] + } + ] + } + }, + { + "rpi.cac": { } + }, + { + "rpi.sharpen": + { + "threshold": 0.25, + "limit": 1.0, + "strength": 1.0 + } + }, + { + "rpi.hdr": + { + "Off": + { + "cadence": [ 0 ] + }, + "MultiExposureUnmerged": + { + "cadence": [ 1, 2 ], + "channel_map": + { + "short": 1, + "long": 2 + } + }, + "SingleExposure": + { + "cadence": [ 1 ], + "channel_map": + { + "short": 1 + }, + "spatial_gain": 2.0, + "tonemap_enable": 1 + }, + "MultiExposure": + { + "cadence": [ 1, 2 ], + "channel_map": + { + "short": 1, + "long": 2 + }, + "stitch_enable": 1, + "spatial_gain": 2.0, + "tonemap_enable": 1 + }, + "Night": + { + "cadence": [ 3 ], + "channel_map": + { + "night": 3 + }, + "tonemap_enable": 1, + "tonemap": + [ + 0, 0, + 5000, 20000, + 10000, 30000, + 20000, 47000, + 30000, 55000, + 65535, 65535 + ] + } + } + } + ] +} \ No newline at end of file diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index bb50a9e05..347377d94 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -34,6 +34,8 @@ #include "controller/denoise_algorithm.h" #include "controller/denoise_status.h" #include "controller/dpc_status.h" +#include "controller/decompand_algorithm.h" +#include "controller/decompand_status.h" #include "controller/geq_status.h" #include "controller/hdr_status.h" #include "controller/lux_status.h" @@ -234,6 +236,7 @@ class IpaPiSP final : public IpaBase 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); @@ -668,6 +671,22 @@ void IpaPiSP::applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global be_->SetDpc(dpc); } +void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus) +{ + if (!decompandStatus || !decompandStatus->pad) + return; + + pisp_fe_decompand_config config = {}; + config.pad = decompandStatus->pad; + + ASSERT(decompandStatus->lut != nullptr); + std::copy(decompandStatus->lut, + decompandStatus->lut + PISP_FE_DECOMPAND_LUT_SIZE, + config.lut); + + fe_->SetDecompand(config); +} + void IpaPiSP::applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global) { pisp_be_sdn_config sdn = {}; @@ -936,6 +955,23 @@ void IpaPiSP::setDefaultConfig() fe_->SetRGBY(rgby); feGlobal.enables |= PISP_FE_ENABLE_RGBY; + RPiController::DecompandAlgorithm *decompand = dynamic_cast( + controller_.getAlgorithm("decompand")); + if (decompand) { + uint16_t decompandLUT[65]; + uint16_t pad; + DecompandStatus decompandStatus; + + decompand->initialValues(decompandLUT, pad); + for (size_t i = 0; i < sizeof(decompandLUT) / sizeof(decompandLUT[0]); ++i) + { + decompandStatus.lut[i] = decompandLUT[i]; + } + decompandStatus.pad = pad; + applyDecompand(&decompandStatus); + feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND; + } + /* Also get sensible front end black level defaults, for the same reason. */ RPiController::BlackLevelAlgorithm *blackLevel = dynamic_cast( controller_.getAlgorithm("black_level")); From 0f5370872fe10e4c75eef5294da6756f3a0c1613 Mon Sep 17 00:00:00 2001 From: Sena Asotani Date: Wed, 16 Jul 2025 16:35:25 +0900 Subject: [PATCH 2/6] ipa: rpi: pisp: Remove 'pad' field from decompand config path This patch removes it from the tuning file, DecompandStatus, and related code. As per reviewer feedback, the 'pad' field is unnecessary outside the PiSP hardware config structure. Signed-off-by: Sena Asotani --- src/ipa/rpi/controller/decompand_algorithm.h | 4 +--- src/ipa/rpi/controller/decompand_status.h | 1 - src/ipa/rpi/controller/rpi/decompand.cpp | 5 +---- src/ipa/rpi/controller/rpi/decompand.h | 3 +-- src/ipa/rpi/pisp/data/imx585.json | 3 +-- src/ipa/rpi/pisp/pisp.cpp | 8 +------- 6 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/ipa/rpi/controller/decompand_algorithm.h b/src/ipa/rpi/controller/decompand_algorithm.h index a722ef07b..0c873752f 100644 --- a/src/ipa/rpi/controller/decompand_algorithm.h +++ b/src/ipa/rpi/controller/decompand_algorithm.h @@ -8,7 +8,7 @@ class DecompandAlgorithm : public Algorithm { public: DecompandAlgorithm(Controller *controller) : Algorithm(controller) {} - virtual void initialValues(uint16_t lut[], uint16_t &pad) + virtual void initialValues(uint16_t lut[]) { static const uint16_t defaultLut[] = { 3072, 3072, 3072, 3072, 3136, 3200, 3264, 3328, @@ -24,8 +24,6 @@ class DecompandAlgorithm : public Algorithm for (size_t i = 0; i < sizeof(defaultLut) / sizeof(defaultLut[0]); ++i) lut[i] = defaultLut[i]; - - pad = 1; } }; } /* namespace RPiController */ diff --git a/src/ipa/rpi/controller/decompand_status.h b/src/ipa/rpi/controller/decompand_status.h index 23880f3db..bec197694 100644 --- a/src/ipa/rpi/controller/decompand_status.h +++ b/src/ipa/rpi/controller/decompand_status.h @@ -4,5 +4,4 @@ struct DecompandStatus { uint16_t lut[65]; - uint16_t pad; }; diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp index 3e5485f45..57e65698d 100644 --- a/src/ipa/rpi/controller/rpi/decompand.cpp +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -36,18 +36,16 @@ int Decompand::read(const libcamera::YamlObject ¶ms) } decompandLUT_[i] = value.value(); } - decompandpad_ = params["pad"].get(0); return 0; } -void Decompand::initialValues(uint16_t LUT[], uint16_t &pad) +void Decompand::initialValues(uint16_t LUT[]) { for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) { LUT[i] = decompandLUT_[i]; } - pad = decompandpad_; } void Decompand::prepare(Metadata *imageMetadata) @@ -57,7 +55,6 @@ void Decompand::prepare(Metadata *imageMetadata) { status.lut[i] = decompandLUT_[i]; } - status.pad = decompandpad_; imageMetadata->set("decompand.status", status); } diff --git a/src/ipa/rpi/controller/rpi/decompand.h b/src/ipa/rpi/controller/rpi/decompand.h index 70b006b5c..44e214f2b 100644 --- a/src/ipa/rpi/controller/rpi/decompand.h +++ b/src/ipa/rpi/controller/rpi/decompand.h @@ -11,12 +11,11 @@ class Decompand : public DecompandAlgorithm Decompand(Controller *controller); char const *name() const override; int read(const libcamera::YamlObject ¶ms) override; - void initialValues(uint16_t LUT[], uint16_t &pad) override; + void initialValues(uint16_t LUT[]) override; void prepare(Metadata *imageMetadata) override; private: uint16_t decompandLUT_[65]; - uint16_t decompandpad_; }; } /* namespace RPiController */ diff --git a/src/ipa/rpi/pisp/data/imx585.json b/src/ipa/rpi/pisp/data/imx585.json index 6ecdee7dd..610cedf45 100644 --- a/src/ipa/rpi/pisp/data/imx585.json +++ b/src/ipa/rpi/pisp/data/imx585.json @@ -21,8 +21,7 @@ 29696, 31744, 33792, 35840, 37888, 39936, 41984, 44032, 46080, 48128, 50176, 52224, 54272, 56320, 58368, 60416, 62464 - ], - "pad": 1 + ] } }, { diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index 347377d94..7c1a04cef 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -673,11 +673,7 @@ void IpaPiSP::applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus) { - if (!decompandStatus || !decompandStatus->pad) - return; - pisp_fe_decompand_config config = {}; - config.pad = decompandStatus->pad; ASSERT(decompandStatus->lut != nullptr); std::copy(decompandStatus->lut, @@ -959,15 +955,13 @@ void IpaPiSP::setDefaultConfig() controller_.getAlgorithm("decompand")); if (decompand) { uint16_t decompandLUT[65]; - uint16_t pad; DecompandStatus decompandStatus; - decompand->initialValues(decompandLUT, pad); + decompand->initialValues(decompandLUT); for (size_t i = 0; i < sizeof(decompandLUT) / sizeof(decompandLUT[0]); ++i) { decompandStatus.lut[i] = decompandLUT[i]; } - decompandStatus.pad = pad; applyDecompand(&decompandStatus); feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND; } From 7545d1643f3d338156410ff704f562066a4c4a7b Mon Sep 17 00:00:00 2001 From: Sena Asotani Date: Thu, 17 Jul 2025 13:15:28 +0900 Subject: [PATCH 3/6] ipa: rpi: pisp: Fix formatting issues in decompand Adjusted indentation and formatting to comply with project style guidelines,as reported by checkstyle.py. Signed-off-by: Sena Asotani --- src/ipa/rpi/controller/decompand_algorithm.h | 31 ++++++++++---------- src/ipa/rpi/controller/rpi/decompand.cpp | 15 +++++----- src/ipa/rpi/pisp/pisp.cpp | 11 ++++--- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/ipa/rpi/controller/decompand_algorithm.h b/src/ipa/rpi/controller/decompand_algorithm.h index 0c873752f..a1178a786 100644 --- a/src/ipa/rpi/controller/decompand_algorithm.h +++ b/src/ipa/rpi/controller/decompand_algorithm.h @@ -7,23 +7,24 @@ namespace RPiController { class DecompandAlgorithm : public Algorithm { public: - DecompandAlgorithm(Controller *controller) : Algorithm(controller) {} + DecompandAlgorithm(Controller *controller) + : Algorithm(controller) {} virtual void initialValues(uint16_t lut[]) { - static const uint16_t defaultLut[] = { - 3072, 3072, 3072, 3072, 3136, 3200, 3264, 3328, - 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, - 3904, 3968, 4032, 4096, 4608, 5120, 5632, 6144, - 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, - 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, - 14848, 15360, 17408, 19456, 21504, 23552, 25600, 27648, - 29696, 31744, 33792, 35840, 37888, 39936, 41984, 44032, - 46080, 48128, 50176, 52224, 54272, 56320, 58368, 60416, - 62464 - }; + static const uint16_t defaultLut[] = { + 3072, 3072, 3072, 3072, 3136, 3200, 3264, 3328, + 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, + 3904, 3968, 4032, 4096, 4608, 5120, 5632, 6144, + 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, + 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, + 14848, 15360, 17408, 19456, 21504, 23552, 25600, 27648, + 29696, 31744, 33792, 35840, 37888, 39936, 41984, 44032, + 46080, 48128, 50176, 52224, 54272, 56320, 58368, 60416, + 62464 + }; - for (size_t i = 0; i < sizeof(defaultLut) / sizeof(defaultLut[0]); ++i) - lut[i] = defaultLut[i]; - } + for (size_t i = 0; i < sizeof(defaultLut) / sizeof(defaultLut[0]); ++i) + lut[i] = defaultLut[i]; + } }; } /* namespace RPiController */ diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp index 57e65698d..fffe85d66 100644 --- a/src/ipa/rpi/controller/rpi/decompand.cpp +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -1,9 +1,9 @@ +#include "decompand.h" + #include #include "../decompand_status.h" -#include "decompand.h" - using namespace RPiController; using namespace libcamera; @@ -42,18 +42,17 @@ int Decompand::read(const libcamera::YamlObject ¶ms) void Decompand::initialValues(uint16_t LUT[]) { - for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) - { - LUT[i] = decompandLUT_[i]; + for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) { + LUT[i] = decompandLUT_[i]; } } void Decompand::prepare(Metadata *imageMetadata) { struct DecompandStatus status; - for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) - { - status.lut[i] = decompandLUT_[i]; + + for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) { + status.lut[i] = decompandLUT_[i]; } imageMetadata->set("decompand.status", status); diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index 7c1a04cef..fc6abc226 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -31,11 +31,11 @@ #include "controller/cac_status.h" #include "controller/ccm_status.h" #include "controller/contrast_status.h" +#include "controller/decompand_algorithm.h" +#include "controller/decompand_status.h" #include "controller/denoise_algorithm.h" #include "controller/denoise_status.h" #include "controller/dpc_status.h" -#include "controller/decompand_algorithm.h" -#include "controller/decompand_status.h" #include "controller/geq_status.h" #include "controller/hdr_status.h" #include "controller/lux_status.h" @@ -677,8 +677,8 @@ void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus) ASSERT(decompandStatus->lut != nullptr); std::copy(decompandStatus->lut, - decompandStatus->lut + PISP_FE_DECOMPAND_LUT_SIZE, - config.lut); + decompandStatus->lut + PISP_FE_DECOMPAND_LUT_SIZE, + config.lut); fe_->SetDecompand(config); } @@ -958,8 +958,7 @@ void IpaPiSP::setDefaultConfig() DecompandStatus decompandStatus; decompand->initialValues(decompandLUT); - for (size_t i = 0; i < sizeof(decompandLUT) / sizeof(decompandLUT[0]); ++i) - { + for (size_t i = 0; i < sizeof(decompandLUT) / sizeof(decompandLUT[0]); ++i) { decompandStatus.lut[i] = decompandLUT[i]; } applyDecompand(&decompandStatus); From 4254d34f4626273f12be95e527271687f123cba6 Mon Sep 17 00:00:00 2001 From: Sena Asotani Date: Mon, 25 Aug 2025 17:06:28 +0900 Subject: [PATCH 4/6] ipa: rpi: pisp: Remove initialValues() from decompand algorithm The initialValues() method is no longer needed, as the decompanding LUT should be provided explicitly for each sensor and tuning configuration. Relying on a hardcoded default LUT may lead to incorrect behavior and reduce flexibility. This patch removes the method and associated code. Signed-off-by: Sena Asotani --- src/ipa/rpi/controller/decompand_algorithm.h | 30 -------------------- src/ipa/rpi/controller/rpi/decompand.cpp | 15 +++------- src/ipa/rpi/controller/rpi/decompand.h | 12 +++++--- src/ipa/rpi/pisp/pisp.cpp | 19 +++---------- 4 files changed, 16 insertions(+), 60 deletions(-) delete mode 100644 src/ipa/rpi/controller/decompand_algorithm.h diff --git a/src/ipa/rpi/controller/decompand_algorithm.h b/src/ipa/rpi/controller/decompand_algorithm.h deleted file mode 100644 index a1178a786..000000000 --- a/src/ipa/rpi/controller/decompand_algorithm.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "algorithm.h" - -namespace RPiController { - -class DecompandAlgorithm : public Algorithm -{ -public: - DecompandAlgorithm(Controller *controller) - : Algorithm(controller) {} - virtual void initialValues(uint16_t lut[]) - { - static const uint16_t defaultLut[] = { - 3072, 3072, 3072, 3072, 3136, 3200, 3264, 3328, - 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, - 3904, 3968, 4032, 4096, 4608, 5120, 5632, 6144, - 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, - 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, - 14848, 15360, 17408, 19456, 21504, 23552, 25600, 27648, - 29696, 31744, 33792, 35840, 37888, 39936, 41984, 44032, - 46080, 48128, 50176, 52224, 54272, 56320, 58368, 60416, - 62464 - }; - - for (size_t i = 0; i < sizeof(defaultLut) / sizeof(defaultLut[0]); ++i) - lut[i] = defaultLut[i]; - } -}; -} /* namespace RPiController */ diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp index fffe85d66..556a596f2 100644 --- a/src/ipa/rpi/controller/rpi/decompand.cpp +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -12,7 +12,7 @@ LOG_DEFINE_CATEGORY(RPiDecompand) #define NAME "rpi.decompand" Decompand::Decompand(Controller *controller) - : DecompandAlgorithm(controller) + : Algorithm(controller) { } @@ -34,25 +34,18 @@ int Decompand::read(const libcamera::YamlObject ¶ms) LOG(RPiDecompand, Error) << "Invalid LUT value at index " << i; return -EINVAL; } - decompandLUT_[i] = value.value(); + config_.decompandLUT_[i] = value.value(); } return 0; } -void Decompand::initialValues(uint16_t LUT[]) -{ - for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) { - LUT[i] = decompandLUT_[i]; - } -} - void Decompand::prepare(Metadata *imageMetadata) { struct DecompandStatus status; - for (size_t i = 0; i < sizeof(decompandLUT_) / sizeof(decompandLUT_[0]); ++i) { - status.lut[i] = decompandLUT_[i]; + for (size_t i = 0; i < sizeof(config_.decompandLUT_) / sizeof(config_.decompandLUT_[0]); ++i) { + status.lut[i] = config_.decompandLUT_[i]; } imageMetadata->set("decompand.status", status); diff --git a/src/ipa/rpi/controller/rpi/decompand.h b/src/ipa/rpi/controller/rpi/decompand.h index 44e214f2b..d13d90fa8 100644 --- a/src/ipa/rpi/controller/rpi/decompand.h +++ b/src/ipa/rpi/controller/rpi/decompand.h @@ -1,21 +1,25 @@ #pragma once -#include "../decompand_algorithm.h" #include "../decompand_status.h" +#include "algorithm.h" + namespace RPiController { -class Decompand : public DecompandAlgorithm +struct DecompandConfig { + uint16_t decompandLUT_[65]; +}; + +class Decompand : public Algorithm { public: Decompand(Controller *controller); char const *name() const override; int read(const libcamera::YamlObject ¶ms) override; - void initialValues(uint16_t LUT[]) override; void prepare(Metadata *imageMetadata) override; private: - uint16_t decompandLUT_[65]; + DecompandConfig config_; }; } /* namespace RPiController */ diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index fc6abc226..8c5e21724 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -31,7 +31,6 @@ #include "controller/cac_status.h" #include "controller/ccm_status.h" #include "controller/contrast_status.h" -#include "controller/decompand_algorithm.h" #include "controller/decompand_status.h" #include "controller/denoise_algorithm.h" #include "controller/denoise_status.h" @@ -385,6 +384,10 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, if (alscStatus) applyLensShading(alscStatus, global); + DecompandStatus *decompandStatus = rpiMetadata.getLocked("decompand.status"); + if (decompandStatus) + applyDecompand(decompandStatus); + DpcStatus *dpcStatus = rpiMetadata.getLocked("dpc.status"); if (dpcStatus) applyDPC(dpcStatus, global); @@ -951,20 +954,6 @@ void IpaPiSP::setDefaultConfig() fe_->SetRGBY(rgby); feGlobal.enables |= PISP_FE_ENABLE_RGBY; - RPiController::DecompandAlgorithm *decompand = dynamic_cast( - controller_.getAlgorithm("decompand")); - if (decompand) { - uint16_t decompandLUT[65]; - DecompandStatus decompandStatus; - - decompand->initialValues(decompandLUT); - for (size_t i = 0; i < sizeof(decompandLUT) / sizeof(decompandLUT[0]); ++i) { - decompandStatus.lut[i] = decompandLUT[i]; - } - applyDecompand(&decompandStatus); - feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND; - } - /* Also get sensible front end black level defaults, for the same reason. */ RPiController::BlackLevelAlgorithm *blackLevel = dynamic_cast( controller_.getAlgorithm("black_level")); From 6261e5d4b789680c5097f985e83693a6bf776c33 Mon Sep 17 00:00:00 2001 From: Sena Asotani Date: Tue, 26 Aug 2025 10:34:21 +0900 Subject: [PATCH 5/6] ipa: rpi: pisp: Use PWL representation for decompand instead of hardware LUT Switch the decompand block to use a piece-wise linear (PWL) curve in the tuning file, similar to the gamma block. The IPA translates the PWL into a hardware LUT at runtime before programming the registers. This improves readability and tunability of the decompand parameters for users, while maintaining compatibility with the hardware requirements. Signed-off-by: Sena Asotani --- src/ipa/rpi/controller/decompand_status.h | 4 +-- src/ipa/rpi/controller/rpi/decompand.cpp | 33 ++++++----------- src/ipa/rpi/controller/rpi/decompand.h | 10 +++--- src/ipa/rpi/pisp/data/imx585.json | 17 ++++----- src/ipa/rpi/pisp/pisp.cpp | 44 +++++++++++++++++------ 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/src/ipa/rpi/controller/decompand_status.h b/src/ipa/rpi/controller/decompand_status.h index bec197694..eb81da6a4 100644 --- a/src/ipa/rpi/controller/decompand_status.h +++ b/src/ipa/rpi/controller/decompand_status.h @@ -1,7 +1,7 @@ #pragma once -#include +#include "libipa/pwl.h" struct DecompandStatus { - uint16_t lut[65]; + libcamera::ipa::Pwl decompandCurve; }; diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp index 556a596f2..9bfc6867e 100644 --- a/src/ipa/rpi/controller/rpi/decompand.cpp +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -3,6 +3,7 @@ #include #include "../decompand_status.h" +#include "../histogram.h" using namespace RPiController; using namespace libcamera; @@ -23,38 +24,26 @@ char const *Decompand::name() const int Decompand::read(const libcamera::YamlObject ¶ms) { - if (!params.contains("lut") || !params["lut"].isList() || params["lut"].size() != 65) { - LOG(RPiDecompand, Error) << "Expected LUT with 65 elements"; - return -EINVAL; - } - - for (unsigned int i = 0; i < 65; ++i) { - std::optional value = params["lut"][i].get(); - if (!value.has_value()) { - LOG(RPiDecompand, Error) << "Invalid LUT value at index " << i; - return -EINVAL; - } - config_.decompandLUT_[i] = value.value(); - } - - return 0; + config_.decompandCurve = params["decompand_curve"].get(ipa::Pwl{}); + return config_.decompandCurve.empty() ? -EINVAL : 0; } -void Decompand::prepare(Metadata *imageMetadata) +void Decompand::initialise() { - struct DecompandStatus status; +} - for (size_t i = 0; i < sizeof(config_.decompandLUT_) / sizeof(config_.decompandLUT_[0]); ++i) { - status.lut[i] = config_.decompandLUT_[i]; - } +void Decompand::prepare(Metadata *imageMetadata) +{ + DecompandStatus decompandStatus; - imageMetadata->set("decompand.status", status); + decompandStatus.decompandCurve = config_.decompandCurve; + imageMetadata->set("decompand.status", decompandStatus); } /* Register algorithm with the system. */ static Algorithm *create(Controller *controller) { - return new Decompand(controller); + return (Algorithm *)new Decompand(controller); } static RegisterAlgorithm reg(NAME, &create); diff --git a/src/ipa/rpi/controller/rpi/decompand.h b/src/ipa/rpi/controller/rpi/decompand.h index d13d90fa8..e27fbd627 100644 --- a/src/ipa/rpi/controller/rpi/decompand.h +++ b/src/ipa/rpi/controller/rpi/decompand.h @@ -1,21 +1,23 @@ #pragma once -#include "../decompand_status.h" - +#include #include "algorithm.h" +#include "../decompand_status.h" + namespace RPiController { struct DecompandConfig { - uint16_t decompandLUT_[65]; + libcamera::ipa::Pwl decompandCurve; }; class Decompand : public Algorithm { public: - Decompand(Controller *controller); + Decompand(Controller *controller = NULL); char const *name() const override; int read(const libcamera::YamlObject ¶ms) override; + void initialise() override; void prepare(Metadata *imageMetadata) override; private: diff --git a/src/ipa/rpi/pisp/data/imx585.json b/src/ipa/rpi/pisp/data/imx585.json index 610cedf45..b1a3ec17a 100644 --- a/src/ipa/rpi/pisp/data/imx585.json +++ b/src/ipa/rpi/pisp/data/imx585.json @@ -11,16 +11,13 @@ { "rpi.decompand": { - "lut": [ - 3072, 3072, 3072, 3072, 3136, 3200, 3264, 3328, - 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, - 3904, 3968, 4032, 4096, 4608, 5120, 5632, 6144, - 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, - 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, - 14848, 15360, 17408, 19456, 21504, 23552, 25600, 27648, - 29696, 31744, 33792, 35840, 37888, 39936, 41984, 44032, - 46080, 48128, 50176, 52224, 54272, 56320, 58368, 60416, - 62464 + "decompand_curve": + [ + 0, 0, + 3072, 3072, + 19456, 4096, + 41984, 15360, + 43008, 17408 ] } }, diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index 8c5e21724..7378cb8b6 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -113,6 +113,27 @@ int generateLut(const ipa::Pwl &pwl, uint32_t *lut, std::size_t lutSize, return 0; } +int generateDecompandLut(const ipa::Pwl &pwl, uint16_t *lut, std::size_t lutSize = 65) +{ + if (pwl.empty()) + return -EINVAL; + + constexpr int step = 1024; + for (std::size_t i = 0; i < lutSize; ++i) { + int x = i * step; + if (x > 65535) + x = 65535; + + int y = pwl.eval(x); + if (y < 0) + return -1; + + lut[i] = static_cast(std::min(y, 65535)); + } + + return 0; +} + void packLscLut(uint32_t packed[NumLscVertexes][NumLscVertexes], double const rgb[3][NumLscVertexes][NumLscVertexes]) { @@ -352,6 +373,11 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, if (noiseStatus) applyFocusStats(noiseStatus); + DecompandStatus *decompandStatus = + rpiMetadata.getLocked("decompand.status"); + if (decompandStatus) + applyDecompand(decompandStatus); + BlackLevelStatus *blackLevelStatus = rpiMetadata.getLocked("black_level.status"); if (blackLevelStatus) @@ -384,10 +410,6 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, if (alscStatus) applyLensShading(alscStatus, global); - DecompandStatus *decompandStatus = rpiMetadata.getLocked("decompand.status"); - if (decompandStatus) - applyDecompand(decompandStatus); - DpcStatus *dpcStatus = rpiMetadata.getLocked("dpc.status"); if (dpcStatus) applyDPC(dpcStatus, global); @@ -676,14 +698,16 @@ void IpaPiSP::applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus) { - pisp_fe_decompand_config config = {}; + pisp_fe_global_config feGlobal; + pisp_fe_decompand_config decompand = {}; - ASSERT(decompandStatus->lut != nullptr); - std::copy(decompandStatus->lut, - decompandStatus->lut + PISP_FE_DECOMPAND_LUT_SIZE, - config.lut); + fe_->GetGlobal(feGlobal); - fe_->SetDecompand(config); + if (!generateDecompandLut(decompandStatus->decompandCurve, decompand.lut, PISP_FE_DECOMPAND_LUT_SIZE)) { + fe_->SetDecompand(decompand); + feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND; + fe_->SetGlobal(feGlobal); + } } void IpaPiSP::applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global) From 74f9aaa48a3e8441f1bbf0c4ea9dddf480beadb3 Mon Sep 17 00:00:00 2001 From: Sena Asotani Date: Tue, 26 Aug 2025 14:51:07 +0900 Subject: [PATCH 6/6] ipa: rpi: pisp: Enable decompand algorithm based on bit depth This patch adds support for a "bitdepth" parameter in the tuning JSON for the decompand block. When specified (e.g. "bitdepth": 12), the decompand algorithm will only be enabled if the camera's current bit depth matches the configured value. For all other bit depths, the algorithm is disabled. If the "bitdepth" parameter is not present in the JSON, which means the decompand algorithm is always enabled. Signed-off-by: Sena Asotani --- src/ipa/rpi/controller/decompand_status.h | 1 + src/ipa/rpi/controller/rpi/decompand.cpp | 13 +++++++++++-- src/ipa/rpi/controller/rpi/decompand.h | 3 +++ src/ipa/rpi/pisp/data/imx585.json | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ipa/rpi/controller/decompand_status.h b/src/ipa/rpi/controller/decompand_status.h index eb81da6a4..2d9888dca 100644 --- a/src/ipa/rpi/controller/decompand_status.h +++ b/src/ipa/rpi/controller/decompand_status.h @@ -3,5 +3,6 @@ #include "libipa/pwl.h" struct DecompandStatus { + uint32_t bitdepth; libcamera::ipa::Pwl decompandCurve; }; diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp index 9bfc6867e..911b04bc0 100644 --- a/src/ipa/rpi/controller/rpi/decompand.cpp +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -24,6 +24,7 @@ char const *Decompand::name() const int Decompand::read(const libcamera::YamlObject ¶ms) { + config_.bitdepth = params["bitdepth"].get(0); config_.decompandCurve = params["decompand_curve"].get(ipa::Pwl{}); return config_.decompandCurve.empty() ? -EINVAL : 0; } @@ -32,12 +33,20 @@ void Decompand::initialise() { } +void Decompand::switchMode([[maybe_unused]] CameraMode const &cameraMode, + [[maybe_unused]] Metadata *metadata) +{ + mode_ = cameraMode; +} + void Decompand::prepare(Metadata *imageMetadata) { DecompandStatus decompandStatus; - decompandStatus.decompandCurve = config_.decompandCurve; - imageMetadata->set("decompand.status", decompandStatus); + if (config_.bitdepth == 0 || mode_.bitdepth == config_.bitdepth) { + decompandStatus.decompandCurve = config_.decompandCurve; + imageMetadata->set("decompand.status", decompandStatus); + } } /* Register algorithm with the system. */ diff --git a/src/ipa/rpi/controller/rpi/decompand.h b/src/ipa/rpi/controller/rpi/decompand.h index e27fbd627..17a40e0b4 100644 --- a/src/ipa/rpi/controller/rpi/decompand.h +++ b/src/ipa/rpi/controller/rpi/decompand.h @@ -8,6 +8,7 @@ namespace RPiController { struct DecompandConfig { + uint32_t bitdepth; libcamera::ipa::Pwl decompandCurve; }; @@ -18,9 +19,11 @@ class Decompand : public Algorithm 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_; }; diff --git a/src/ipa/rpi/pisp/data/imx585.json b/src/ipa/rpi/pisp/data/imx585.json index b1a3ec17a..f2be20a3c 100644 --- a/src/ipa/rpi/pisp/data/imx585.json +++ b/src/ipa/rpi/pisp/data/imx585.json @@ -11,6 +11,7 @@ { "rpi.decompand": { + "bitdepth": 12, "decompand_curve": [ 0, 0,