From patchwork Wed Mar 19 16:11:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22989 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 E400DC32FE for ; Wed, 19 Mar 2025 16:12:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 94A386896C; Wed, 19 Mar 2025 17:12:30 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="LIdCnPre"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 57C3F68962 for ; Wed, 19 Mar 2025 17:12:29 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:760:e5ca:4814:99c7]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 777F455A; Wed, 19 Mar 2025 17:10:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1742400646; bh=96p0ZlNnEnooA92EeItd8ynm89pE3xwAD+FvHp4hNtc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LIdCnPre+r2CnJQAYNm/rmiaSGzmBzmPpK9XR1bTEH2bxOpVhdQZC+VuF/6KZO6Xi +JstepYqV4qOWGZhM6tG0P03wJ+lSQAefxL1buRmPl0nhza5MZTi0BUnrj4y4UWvT0 e1w3aw2nPCDQKBB2ZM0ocFBYZiLpyRtPgvKRumPI= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v2 11/17] ipa: rkisp1: Implement manual ColourCorrectionMatrix control Date: Wed, 19 Mar 2025 17:11:16 +0100 Message-ID: <20250319161152.63625-12-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250319161152.63625-1-stefan.klug@ideasonboard.com> References: <20250319161152.63625-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 manual ColourCorrectionMatrix control. This was already discussed while implementing manual colour temperature but was never implemented. The control allows to manually specify the CCM when AwbEnable is false. Signed-off-by: Stefan Klug --- Changes in v2: - None --- src/ipa/rkisp1/algorithms/ccm.cpp | 59 ++++++++++++++++++++++++++++--- src/ipa/rkisp1/algorithms/ccm.h | 6 ++++ src/ipa/rkisp1/ipa_context.h | 3 +- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/ccm.cpp b/src/ipa/rkisp1/algorithms/ccm.cpp index 2e5e91006b55..303ac3dd2fe2 100644 --- a/src/ipa/rkisp1/algorithms/ccm.cpp +++ b/src/ipa/rkisp1/algorithms/ccm.cpp @@ -36,17 +36,25 @@ namespace ipa::rkisp1::algorithms { LOG_DEFINE_CATEGORY(RkISP1Ccm) +constexpr Matrix kIdentity3x3 = Matrix::identity(); + /** * \copydoc libcamera::ipa::Algorithm::init */ int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) { + auto &cmap = context.ctrlMap; + cmap[&controls::ColourCorrectionMatrix] = ControlInfo( + ControlValue(-8.0f), + ControlValue(7.993f), + ControlValue(kIdentity3x3.data())); + int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm"); if (ret < 0) { LOG(RkISP1Ccm, Warning) << "Failed to parse 'ccm' " << "parameter from tuning file; falling back to unit matrix"; - ccm_.setData({ { 0, Matrix::identity() } }); + ccm_.setData({ { 0, kIdentity3x3 } }); } ret = offsets_.readYaml(tuningData["ccms"], "ct", "offsets"); @@ -61,13 +69,48 @@ int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData return 0; } +/** + * \copydoc libcamera::ipa::Algorithm::configure + */ +int Ccm::configure(IPAContext &context, + [[maybe_unused]] const IPACameraSensorInfo &configInfo) +{ + auto &as = context.activeState; + as.ccm.manual = kIdentity3x3; + as.ccm.automatic = ccm_.getInterpolated(as.awb.automatic.temperatureK); + LOG(RkISP1Ccm, Debug) << "init matrix " << as.ccm.manual; + return 0; +} + +void Ccm::queueRequest(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + /* Nothing to do here, the ccm will be calculated in prepare() */ + if (frameContext.awb.autoEnabled) + return; + + auto &ccm = context.activeState.ccm; + + const auto &colourTemperature = controls.get(controls::ColourTemperature); + const auto &ccmMatrix = controls.get(controls::ColourCorrectionMatrix); + if (ccmMatrix) + ccm.manual = Matrix(*ccmMatrix); + else if (colourTemperature) + ccm.manual = ccm_.getInterpolated(*colourTemperature); + + LOG(RkISP1Ccm, Debug) << "queueRequest matrix " << ccm.manual; + frameContext.ccm.ccm = ccm.manual; +} + void Ccm::setParameters(struct rkisp1_cif_isp_ctk_config &config, const Matrix &matrix, const Matrix &offsets) { /* * 4 bit integer and 7 bit fractional, ranging from -8 (0x400) to - * +7.992 (0x3ff) + * +7.9921875 (0x3ff) */ for (unsigned int i = 0; i < 3; i++) { for (unsigned int j = 0; j < 3; j++) @@ -88,14 +131,20 @@ void Ccm::setParameters(struct rkisp1_cif_isp_ctk_config &config, void Ccm::prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, RkISP1Params *params) { - uint32_t ct = frameContext.awb.temperatureK; + if (!frameContext.awb.autoEnabled) { + auto config = params->block(); + config.setEnabled(true); + setParameters(*config, frameContext.ccm.ccm, Matrix()); + return; + } + uint32_t ct = frameContext.awb.temperatureK; /* * \todo The colour temperature will likely be noisy, add filtering to * avoid updating the CCM matrix all the time. */ if (frame > 0 && ct == ct_) { - frameContext.ccm.ccm = context.activeState.ccm.ccm; + frameContext.ccm.ccm = context.activeState.ccm.automatic; return; } @@ -103,7 +152,7 @@ void Ccm::prepare(IPAContext &context, const uint32_t frame, Matrix ccm = ccm_.getInterpolated(ct); Matrix offsets = offsets_.getInterpolated(ct); - context.activeState.ccm.ccm = ccm; + context.activeState.ccm.automatic = ccm; frameContext.ccm.ccm = ccm; auto config = params->block(); diff --git a/src/ipa/rkisp1/algorithms/ccm.h b/src/ipa/rkisp1/algorithms/ccm.h index a5d9a9a45e5d..c301e6e531c8 100644 --- a/src/ipa/rkisp1/algorithms/ccm.h +++ b/src/ipa/rkisp1/algorithms/ccm.h @@ -26,6 +26,12 @@ public: ~Ccm() = 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, RkISP1Params *params) override; diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 769e9f114e23..f0d504215d34 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -101,7 +101,8 @@ struct IPAActiveState { } awb; struct { - Matrix ccm; + Matrix manual; + Matrix automatic; } ccm; struct {