From patchwork Sun Jan 18 20:31:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 25832 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 9456FBDCBE for ; Sun, 18 Jan 2026 20:31:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 595B061FCF; Sun, 18 Jan 2026 21:31:40 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Dccc8gll"; 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 01C4A61FCF for ; Sun, 18 Jan 2026 21:31:39 +0100 (CET) Received: from rui-Precision-7560.local (unknown [209.216.103.65]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CACD61BA; Sun, 18 Jan 2026 21:31:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1768768269; bh=8XKCsaL/+vHXI33ytQwEAQa6r0YRtWe2b3wihBta65k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dccc8gllVrmt0tORalCivbXzLxvUSjAaGWxqNznM3dS2XerIjgx/kVnpgrvJp0pvG dxGxmPnL6gmbo/vUsqLsaHfUjhPcVsZ7j7aI4UTVMOTo1kvKlot8GrG64yUKDtq3cL ZiCg2a8DzZ5uedilPqQTYmNEg9ScmFy9nxs8MIrU= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v9 2/6] ipa: rkisp1: algorithms: dpf: Implement mode switching Date: Sun, 18 Jan 2026 15:31:14 -0500 Message-ID: <20260118203119.1554962-3-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260118203119.1554962-1-rui.wang@ideasonboard.com> References: <20260118203119.1554962-1-rui.wang@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" Implement support for switching between different noise reduction modes. This allows the DPF algorithm to be configured with different parameters based on the requested noise reduction level (e.g., minimal, fast, high quality). Mode configurations are stored in the tuning data as a list of modes, with each mode specifying its 'type' and corresponding DPF parameters. An optional 'ActiveMode' setting allows defining the default mode at startup, defaulting to "ReductionOff" if not specified. The Dpf class is refactored to store configurations in a vector and track the current mode using an iterator, which avoids data copying during runtime. Signed-off-by: Rui Wang --- changelog since v5: - Update log verbos from Info to Debug in loadReductionConfig - Update log mode value to string to in loadReductionConfig - improving the return value changed like : if (ret != 0) -> if (ret) Reviewed-by tags from v5 are carried over (no function changes). changelog since v6: - add { controls::draft::NoiseReductionModeOff, "off" }, to fix out_of_range issue changelog since v7: - Delete base config parse from parseConfig changelog since v8: - remove config_ strengthConfig_ by replacing activeMode_ iterator to avoiding data copy during config loading - Update kModesMap from std::map std::map for quick search improvement - add ActiveMode as Stefan and Jacopo's review comments - update type : auto -> int for ret value - name change loadRecuctionConfig -> loadConfig - delete parseMode --- src/ipa/rkisp1/algorithms/dpf.cpp | 118 +++++++++++++++++++++++++++--- src/ipa/rkisp1/algorithms/dpf.h | 12 ++- 2 files changed, 117 insertions(+), 13 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp index dd3effa1..d79cc5ff 100644 --- a/src/ipa/rkisp1/algorithms/dpf.cpp +++ b/src/ipa/rkisp1/algorithms/dpf.cpp @@ -8,6 +8,7 @@ #include "dpf.h" #include +#include #include #include @@ -36,8 +37,32 @@ namespace ipa::rkisp1::algorithms { LOG_DEFINE_CATEGORY(RkISP1Dpf) +namespace { + +const std::map kModesMap = { + { "ReductionMinimal", controls::draft::NoiseReductionModeMinimal }, + { "ReductionFast", controls::draft::NoiseReductionModeFast }, + { "ReductionHighQuality", controls::draft::NoiseReductionModeHighQuality }, + { "ReductionZSL", controls::draft::NoiseReductionModeZSL }, + { "ReductionOff", controls::draft::NoiseReductionModeOff }, +}; + +std::string modeName(int32_t mode) +{ + auto it = std::find_if(kModesMap.begin(), kModesMap.end(), + [mode](const auto &pair) { + return pair.second == mode; + }); + + if (it != kModesMap.end()) + return it->first; + + return "ReductionUnknown"; +} +} /* namespace */ + Dpf::Dpf() - : config_({}), strengthConfig_({}) + : noiseReductionModes_({}), activeMode_(noiseReductionModes_.end()) { } @@ -57,10 +82,57 @@ int Dpf::init([[maybe_unused]] IPAContext &context, int Dpf::parseConfig(const YamlObject &tuningData) { - /* Parse base config. */ - int ret = parseSingleConfig(tuningData, config_, strengthConfig_); - if (ret) - return ret; + /* Parse noise reduction modes. */ + if (!tuningData.contains("NoiseReductionModes")) { + LOG(RkISP1Dpf, Error) << "Missing modes in DPF tuning data"; + return -EINVAL; + } + + noiseReductionModes_.clear(); + for (const auto &entry : tuningData["NoiseReductionModes"].asList()) { + std::optional typeOpt = + entry["type"].get(); + if (!typeOpt) { + LOG(RkISP1Dpf, Error) << "Modes entry missing type"; + return -EINVAL; + } + + ModeConfig mode; + auto it = kModesMap.find(*typeOpt); + if (it == kModesMap.end()) { + LOG(RkISP1Dpf, Error) << "Unknown mode type: " << *typeOpt; + return -EINVAL; + } + + mode.modeValue = it->second; + int ret = parseSingleConfig(entry, mode.dpf, mode.strength); + if (ret) { + LOG(RkISP1Dpf, Error) << "Failed to parse mode: " << *typeOpt; + return ret; + } + + noiseReductionModes_.push_back(mode); + } + + /* + * Parse the optional ActiveMode. + * If not present, default to "ReductionOff". + */ + std::string activeMode = tuningData["ActiveMode"].get().value_or("ReductionOff"); + auto it = kModesMap.find(activeMode); + if (it == kModesMap.end()) { + LOG(RkISP1Dpf, Warning) << "Invalid ActiveMode: " << activeMode; + activeMode_ = noiseReductionModes_.end(); + return 0; + } + + if (!loadConfig(it->second)) { + /* If the default "ReductionOff" mode is requested but not configured, disable DPF. */ + if (it->second == controls::draft::NoiseReductionModeOff) + activeMode_ = noiseReductionModes_.end(); + else + return -EINVAL; + } return 0; } @@ -193,6 +265,27 @@ int Dpf::parseSingleConfig(const YamlObject &tuningData, return 0; } +bool Dpf::loadConfig(int32_t mode) +{ + auto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(), + [mode](const ModeConfig &m) { + return m.modeValue == mode; + }); + if (it == noiseReductionModes_.end()) { + LOG(RkISP1Dpf, Warning) + << "No DPF config for reduction mode: " << modeName(mode); + return false; + } + + activeMode_ = it; + + LOG(RkISP1Dpf, Debug) + << "DPF mode=Reduction (config loaded)" + << " mode= " << modeName(mode); + + return true; +} + /** * \copydoc libcamera::ipa::Algorithm::queueRequest */ @@ -206,8 +299,6 @@ void Dpf::queueRequest(IPAContext &context, const auto &denoise = controls.get(controls::draft::NoiseReductionMode); if (denoise) { - LOG(RkISP1Dpf, Debug) << "Set denoise to " << *denoise; - switch (*denoise) { case controls::draft::NoiseReductionModeOff: if (dpf.denoise) { @@ -218,9 +309,10 @@ void Dpf::queueRequest(IPAContext &context, case controls::draft::NoiseReductionModeMinimal: case controls::draft::NoiseReductionModeHighQuality: case controls::draft::NoiseReductionModeFast: - if (!dpf.denoise) { - dpf.denoise = true; + case controls::draft::NoiseReductionModeZSL: + if (loadConfig(*denoise)) { update = true; + dpf.denoise = true; } break; default: @@ -229,6 +321,8 @@ void Dpf::queueRequest(IPAContext &context, << *denoise; break; } + if (update) + LOG(RkISP1Dpf, Debug) << "Set denoise to " << modeName(*denoise); } frameContext.dpf.denoise = dpf.denoise; @@ -251,8 +345,10 @@ void Dpf::prepare(IPAContext &context, const uint32_t frame, strengthConfig.setEnabled(frameContext.dpf.denoise); if (frameContext.dpf.denoise) { - *config = config_; - *strengthConfig = strengthConfig_; + const ModeConfig &modeConfig = *activeMode_; + + *config = modeConfig.dpf; + *strengthConfig = modeConfig.strength; const auto &awb = context.configuration.awb; const auto &lsc = context.configuration.lsc; diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h index 39186c55..11fc88e4 100644 --- a/src/ipa/rkisp1/algorithms/dpf.h +++ b/src/ipa/rkisp1/algorithms/dpf.h @@ -30,13 +30,21 @@ public: RkISP1Params *params) override; private: + struct ModeConfig { + int32_t modeValue; + rkisp1_cif_isp_dpf_config dpf; + rkisp1_cif_isp_dpf_strength_config strength; + }; + int parseConfig(const YamlObject &tuningData); int parseSingleConfig(const YamlObject &tuningData, rkisp1_cif_isp_dpf_config &config, rkisp1_cif_isp_dpf_strength_config &strengthConfig); - struct rkisp1_cif_isp_dpf_config config_; - struct rkisp1_cif_isp_dpf_strength_config strengthConfig_; + bool loadConfig(int32_t mode); + + std::vector noiseReductionModes_; + std::vector::const_iterator activeMode_; }; } /* namespace ipa::rkisp1::algorithms */