From patchwork Mon Jun 3 14:06:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20193 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B9AA1BD87C for ; Mon, 3 Jun 2024 14:08:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6BC99634CD; Mon, 3 Jun 2024 16:08:44 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="H3FIKxTb"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 54DBA634B2 for ; Mon, 3 Jun 2024 16:08:43 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6067:153a:95aa:2e07]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 55E43BC0; Mon, 3 Jun 2024 16:08:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1717423716; bh=sdNvzbOEJC0veHQ5FTjS/q4Opfi5ToQeXw7PVHyzrm4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=H3FIKxTbHg1bXR9bqcX9gLzPmrJFfE4b/TQcsSB9K3ZzG3fMCo5dw406+gc1SXRrE KMF8EPMpKxLxzRgThNVFoY7ZLFVANH0bUgmizbDRtS0QypP+Gj5NM3bAjc+F8tNfiM Dk5VutvOBjGPB5oNe/7tpgBIXdislSCYhNbSifyg= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Daniel Scally , Kieran Bingham Subject: [PATCH v3 1/3] libcamera: Add gamma control id Date: Mon, 3 Jun 2024 16:06:28 +0200 Message-ID: <20240603140806.90045-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240603140806.90045-1-stefan.klug@ideasonboard.com> References: <20240603140806.90045-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" A camera gamma of roughly 2.2 is necessary to produce correct output images on a standard monitor. Add a control for that. Further information is available here: https://en.wikipedia.org/wiki/SRGB https://www.cambridgeincolour.com/tutorials/gamma-correction.htm Signed-off-by: Stefan Klug Reviewed-by: Daniel Scally Reviewed-by: Kieran Bingham --- v2 -> v3: - no changes v1 -> v2: - small change in description src/libcamera/control_ids_core.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index bf1f1a83..303b0d32 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -243,6 +243,13 @@ controls: Specify a fixed contrast parameter. Normal contrast is given by the value 1.0; larger values produce images with more contrast. + - Gamma: + type: float + description: | + Specify a fixed gamma value. Default must be 2.2 which closely mimics + sRGB gamma. Note that this is camera gamma, so it is applied as + 1.0/gamma + - Lux: type: float description: | From patchwork Mon Jun 3 14:06:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20194 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id BAB1BBD87C for ; Mon, 3 Jun 2024 14:08:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 735A3634C5; Mon, 3 Jun 2024 16:08:49 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="SfZq6OIR"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DE8A1634B2 for ; Mon, 3 Jun 2024 16:08:47 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6067:153a:95aa:2e07]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DE132BC0; Mon, 3 Jun 2024 16:08:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1717423721; bh=wkiqljmx4xrVI90ZK9ikSSauOUITOi0m37Q9z699oVU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SfZq6OIRNdSqPKy5lheJGFhbTG9te9oJqkouJt5rqAlHGFEf2htxJVTQp/rEd190x YhQ2BvRCYq3ZvmegXQEcqr7H7as9uvRkjmlE1NVHHAJY3S/IlkXl49A/r52z8Wn7VC dQ9qjaIf1/0LjZO44kKlr0gQWXQtNeTfiowqzyNQ= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Kieran Bingham Subject: [PATCH v3 2/3] ipa: rkisp1: Fix algorithm controls vanish after configure Date: Mon, 3 Jun 2024 16:06:29 +0200 Message-ID: <20240603140806.90045-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240603140806.90045-1-stefan.klug@ideasonboard.com> References: <20240603140806.90045-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" std::unordered_map::merge(source) has the side effect of actually moving items from source to target. In this case the controls were removed from the source maps on the first call to updateControls() and on the second call to updateControls() they were missing in the source maps and therefore also removed from the camera. Fix this by using insert() instead of merge(). This is most likely cheaper than copy-contructing the source map. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham --- v2 -> v3: - fixed typos in commit message. src/ipa/rkisp1/rkisp1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 6687c91e..17474408 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -427,7 +427,7 @@ void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo, frameDurations[1], frameDurations[2]); - ctrlMap.merge(context_.ctrlMap); + ctrlMap.insert(context_.ctrlMap.begin(), context_.ctrlMap.end()); *ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls); } From patchwork Mon Jun 3 14:06:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20195 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 49BFABD87C for ; Mon, 3 Jun 2024 14:08:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 049DE634CA; Mon, 3 Jun 2024 16:08:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Dd42fWpJ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8D720634CA for ; Mon, 3 Jun 2024 16:08:51 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6067:153a:95aa:2e07]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8D2D0BC0; Mon, 3 Jun 2024 16:08:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1717423724; bh=FoPfA8pz6SeybmeBzZnxWEYHeCauLwujNrCcrFak5KU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dd42fWpJWUaLet0bzbrGPcI36u9g8yYMxj2QxWFOdzubua35r6yX3UR5oSWP60zkr sNL47LzpJAmFJXbNbmfNGDUGG6ypALPu79Mwe8aeWUPiTg+TafBLfsY7KElsUvzPRe gM79lW7ikXy6S4pYez4A6a0NDtyDvFKnkV5ZuILs= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v3 3/3] ipa: rkisp1: Add GammaOutCorrection algorithm Date: Mon, 3 Jun 2024 16:06:30 +0200 Message-ID: <20240603140806.90045-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240603140806.90045-1-stefan.klug@ideasonboard.com> References: <20240603140806.90045-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 Reviewed-by: Kieran Bingham --- v2 -> v3: - Squashed with patch 1/4 from previous series - Renamed from Gamma to GammaOutCorrection - Read default gamma value from tuning file - Some stylistic fixes from review src/ipa/rkisp1/algorithms/goc.cpp | 161 ++++++++++++++++++++++++++ src/ipa/rkisp1/algorithms/goc.h | 48 ++++++++ src/ipa/rkisp1/algorithms/meson.build | 1 + src/ipa/rkisp1/ipa_context.h | 4 + 4 files changed, 214 insertions(+) create mode 100644 src/ipa/rkisp1/algorithms/goc.cpp create mode 100644 src/ipa/rkisp1/algorithms/goc.h diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp new file mode 100644 index 00000000..875c82e5 --- /dev/null +++ b/src/ipa/rkisp1/algorithms/goc.cpp @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * + * RkISP1 Gamma out control + */ +#include "goc.h" + +#include + +#include +#include + +#include + +#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 double kDefaultGamma = 2.2; + +GammaOutCorrection::GammaOutCorrection() + : gamma_(0) +{ +} + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int GammaOutCorrection::init([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const YamlObject &tuningData) +{ + context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, 2.2f); + defaultGamma_ = tuningData["gamma"].get(kDefaultGamma); + + if (context.hw->numGammaOutSamples != + RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10) { + LOG(RkISP1Gamma, Error) + << "Gamma is not implemented for RkISP1 V12"; + return -EINVAL; + } + + 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.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) +{ + const auto &gamma = controls.get(controls::Gamma); + if (gamma) { + /* + * \todo This is not correct as it updates the current state with a + * future value. But it does no harm at the moment an allows us to + * track the last active gamma + */ + context.activeState.gamma = *gamma; + LOG(RkISP1Gamma, Debug) << "Set gamma to " << *gamma; + } + + frameContext.gamma = context.activeState.gamma; +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void GammaOutCorrection::prepare([[maybe_unused]] IPAContext &context, + 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 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 (frame > 0 && std::fabs(frameContext.gamma - gamma_) < 0.001) + return; + + gamma_ = frameContext.gamma; + + unsigned x = 0; + for (auto [i, size] : utils::enumerate(segments)) { + gamma_y[i] = std::pow(x / 4096.0, 1.0 / 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.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..d45e4194 --- /dev/null +++ b/src/ipa/rkisp1/algorithms/goc.h @@ -0,0 +1,48 @@ +/* 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(); + ~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: + /* + * \todo: gamma_ holds the current state of the hardware. context.activeState + * can not be used as that holds the "future state" after applying all known + * requests. The intended usage of activeState needs to be clarified. + */ + double gamma_; + + double 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.h b/src/ipa/rkisp1/ipa_context.h index bd02a7a2..5252e222 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -104,6 +104,8 @@ struct IPAActiveState { uint8_t denoise; uint8_t sharpness; } filter; + + double gamma; }; struct IPAFrameContext : public FrameContext { @@ -146,6 +148,8 @@ struct IPAFrameContext : public FrameContext { uint32_t exposure; double gain; } sensor; + + double gamma; }; struct IPAContext {