diff options
author | Stefan Klug <stefan.klug@ideasonboard.com> | 2024-05-16 08:22:20 +0200 |
---|---|---|
committer | Stefan Klug <stefan.klug@ideasonboard.com> | 2024-06-11 15:11:11 +0200 |
commit | eb41f636941e13a92ddce7893d25abd747e23c45 (patch) | |
tree | 9059043854f3255696714733cd51508680ad557c /src/ipa/rkisp1 | |
parent | acfd602767638aa6ce19fd831d5221bdf233195c (diff) |
ipa: rkisp1: Add GammaOutCorrection algorithm
Add a gamma algorithm for the rkisp1. It defaults to a gamma of 2.2 which
closely resembles sRGB. No seperate sRGB mode was implemented because the pwl
that models the gamma curve is so coarse that there is basically no difference
between srgb and gamma=2.2. The default can be overridden within the tuning
file or set at runtime using the gamma control.
The gamma algorithm is not enabled by default. This will be done in future
tuning file updates.
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Diffstat (limited to 'src/ipa/rkisp1')
-rw-r--r-- | src/ipa/rkisp1/algorithms/goc.cpp | 153 | ||||
-rw-r--r-- | src/ipa/rkisp1/algorithms/goc.h | 42 | ||||
-rw-r--r-- | src/ipa/rkisp1/algorithms/meson.build | 1 | ||||
-rw-r--r-- | src/ipa/rkisp1/ipa_context.cpp | 20 | ||||
-rw-r--r-- | src/ipa/rkisp1/ipa_context.h | 9 |
5 files changed, 225 insertions, 0 deletions
diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp new file mode 100644 index 00000000..0201a59d --- /dev/null +++ b/src/ipa/rkisp1/algorithms/goc.cpp @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * + * RkISP1 Gamma out control + */ +#include "goc.h" + +#include <cmath> + +#include <libcamera/base/log.h> +#include <libcamera/base/utils.h> + +#include <libcamera/control_ids.h> + +#include "libcamera/internal/yaml_parser.h" + +#include "linux/rkisp1-config.h" + +/** + * \file goc.h + */ + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +/** + * \class GammaOutCorrection + * \brief RkISP1 Gamma out correction + * + * This algorithm implements the gamma out curve for the RkISP1. + * It defaults to a gamma value of 2.2 + * As gamma is internally represented as a piecewise linear function with only + * 17 knots, the difference between gamma=2.2 and sRGB gamma is minimal. + * Therefore sRGB gamma was not implemented as special case. + * + * Useful links: + * https://www.cambridgeincolour.com/tutorials/gamma-correction.htm + * https://en.wikipedia.org/wiki/SRGB + */ + +LOG_DEFINE_CATEGORY(RkISP1Gamma) + +const float kDefaultGamma = 2.2f; + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int GammaOutCorrection::init([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const YamlObject &tuningData) +{ + if (context.hw->numGammaOutSamples != + RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10) { + LOG(RkISP1Gamma, Error) + << "Gamma is not implemented for RkISP1 V12"; + return -EINVAL; + } + + defaultGamma_ = tuningData["gamma"].get<double>(kDefaultGamma); + context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, defaultGamma_); + + return 0; +} + +/** + * \brief Configure the Gamma given a configInfo + * \param[in] context The shared IPA context + * \param[in] configInfo The IPA configuration data + * + * \return 0 + */ +int GammaOutCorrection::configure(IPAContext &context, + [[maybe_unused]] const IPACameraSensorInfo &configInfo) +{ + context.activeState.goc.gamma = defaultGamma_; + return 0; +} + +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void GammaOutCorrection::queueRequest([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + if (frame == 0) + frameContext.goc.update = true; + + const auto &gamma = controls.get(controls::Gamma); + if (gamma) { + context.activeState.goc.gamma = *gamma; + frameContext.goc.update = true; + LOG(RkISP1Gamma, Debug) << "Set gamma to " << *gamma; + } + + frameContext.goc.gamma = context.activeState.goc.gamma; +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void GammaOutCorrection::prepare([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + rkisp1_params_cfg *params) +{ + ASSERT(context.hw->numGammaOutSamples == + RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10); + + /* + * The logarithmic segments as specified in the reference. + * Plus an additional 0 to make the loop easier + */ + std::array<unsigned, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10> segments = { + 64, 64, 64, 64, 128, 128, 128, 128, 256, + 256, 256, 512, 512, 512, 512, 512, 0 + }; + auto gamma_y = params->others.goc_config.gamma_y; + + if (!frameContext.goc.update) + return; + + unsigned x = 0; + for (const auto [i, size] : utils::enumerate(segments)) { + gamma_y[i] = std::pow(x / 4096.0, 1.0 / frameContext.goc.gamma) * 1023.0; + x += size; + } + + params->others.goc_config.mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_GOC; + params->module_en_update |= RKISP1_CIF_ISP_MODULE_GOC; + params->module_ens |= RKISP1_CIF_ISP_MODULE_GOC; +} + +/** + * \copydoc libcamera::ipa::Algorithm::process + */ +void GammaOutCorrection::process([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + [[maybe_unused]] const rkisp1_stat_buffer *stats, + ControlList &metadata) +{ + metadata.set(controls::Gamma, frameContext.goc.gamma); +} + +REGISTER_IPA_ALGORITHM(GammaOutCorrection, "GammaOutCorrection") + +} /* namespace ipa::rkisp1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/goc.h b/src/ipa/rkisp1/algorithms/goc.h new file mode 100644 index 00000000..0e05d7ce --- /dev/null +++ b/src/ipa/rkisp1/algorithms/goc.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * + * RkISP1 Gamma out control + */ + +#pragma once + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +class GammaOutCorrection : public Algorithm +{ +public: + GammaOutCorrection() = default; + ~GammaOutCorrection() = default; + + int init(IPAContext &context, const YamlObject &tuningData) override; + int configure(IPAContext &context, + const IPACameraSensorInfo &configInfo) override; + void queueRequest(IPAContext &context, + const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) override; + void prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + rkisp1_params_cfg *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const rkisp1_stat_buffer *stats, + ControlList &metadata) override; + +private: + float defaultGamma_; +}; + +} /* namespace ipa::rkisp1::algorithms */ +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build index 93a48329..6ee71a9b 100644 --- a/src/ipa/rkisp1/algorithms/meson.build +++ b/src/ipa/rkisp1/algorithms/meson.build @@ -8,6 +8,7 @@ rkisp1_ipa_algorithms = files([ 'dpcc.cpp', 'dpf.cpp', 'filter.cpp', + 'goc.cpp', 'gsl.cpp', 'lsc.cpp', ]) diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 283bc131..65e0c58c 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -218,6 +218,14 @@ namespace libcamera::ipa::rkisp1 { */ /** + * \var IPAActiveState::goc + * \brief State for the goc algorithm + * + * \var IPAActiveState::goc.gamma + * \brief Gamma value applied as 1.0/gamma + */ + +/** * \struct IPAFrameContext * \brief Per-frame context for algorithms * @@ -334,6 +342,18 @@ namespace libcamera::ipa::rkisp1 { */ /** + * \var IPAFrameContext::goc + * \brief Gamma out correction parameters for this frame + * + * \var IPAFrameContext::goc.gamma + * \brief Gamma value applied as 1.0/gamma + * + * \var IPAFrameContext::goc.update + * \brief Indicates if the goc parameters have been updated compared to the + * previous frame + */ + +/** * \var IPAFrameContext::sensor * \brief Sensor configuration that used been used for this frame * diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index bd02a7a2..2a994d81 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -104,6 +104,10 @@ struct IPAActiveState { uint8_t denoise; uint8_t sharpness; } filter; + + struct { + double gamma; + } goc; }; struct IPAFrameContext : public FrameContext { @@ -143,6 +147,11 @@ struct IPAFrameContext : public FrameContext { } filter; struct { + double gamma; + bool update; + } goc; + + struct { uint32_t exposure; double gain; } sensor; |