From patchwork Sun Jan 18 20:29:50 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 25826 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 0C92BBDCBE for ; Sun, 18 Jan 2026 20:30:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C8B0161FB9; Sun, 18 Jan 2026 21:30:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="skJ70AEK"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EEC3661FB9 for ; Sun, 18 Jan 2026 21:30:40 +0100 (CET) Received: from rui-Precision-7560.local (unknown [209.216.103.65]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BFEB51BA; Sun, 18 Jan 2026 21:30:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1768768211; bh=fY8F3AL+hPMykr4ZGbXKshuzs571yQFx8yt80SPlZeg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=skJ70AEKQKmaOQs/1BMCgHadLA6QScRe0dHzPixOAaAaPQIR5aM9HCvE1lVPncpWk Un/UYWqDxq39i6IBcBL6+rAdZrp91tBv+mt02t9csCXW1QkVg3noXeo6wTPISeawoS 6mIYRfh4gN1EPPzWfDzHtAXxC1JXI4/ln5GW+aw8= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v1 1/4] ipa: rkisp1: algorithms: filter: Implement noise reduction mode switching Date: Sun, 18 Jan 2026 15:29:50 -0500 Message-ID: <20260118202953.1554892-2-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260118202953.1554892-1-rui.wang@ideasonboard.com> References: <20260118202953.1554892-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" Add support for switching between different noise reduction modes in the Filter algorithm, mirroring the implementation approach used in the DPF algorithm. This allows the Filter to be configured with multiple mode-specific parameter sets, enabling runtime switching between different filtering strengths via the NoiseReductionMode control. Key changes: - Introduce ModeConfig structure to store mode-specific filter configurations. - Implement parseConfig() to parse NoiseReductionModes from tuning data. - Add parseSingleConfig() to parse individual mode configurations with inheritance support (modes can override base config values). - Implement loadConfig() to switch between configured modes at runtime. - Add kModesMap for string-to-int mode name mapping. - Support optional ActiveMode tuning parameter to set default mode. - Add modeName() helper for reverse lookup (int to string) for logging. The implementation follows the same pattern as the DPF algorithm, ensuring consistency across the rkisp1 IPA module. Example YAML configuration for Filter: - Filter: NoiseReductionModes: - type: "ReductionMinimal" mode: 1266 # 0x000004f2 in decimal lum_weight: 139328 # 0x00022040 in decimal grn_stage1: 6 chr_h_mode: 3 chr_v_mode: 3 thresh_bl0: 8 thresh_bl1: 2 thresh_sh0: 18 thresh_sh1: 33 fac_sh0: 4 fac_sh1: 4 fac_mid: 4 fac_bl0: 2 fac_bl1: 0 - type: "fast" ... ActiveMode: "ReductionMinimal" Signed-off-by: Rui Wang --- src/ipa/rkisp1/algorithms/filter.cpp | 149 ++++++++++++++++++++++++++- src/ipa/rkisp1/algorithms/filter.h | 16 ++- 2 files changed, 163 insertions(+), 2 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp index 8ad79801..321e4122 100644 --- a/src/ipa/rkisp1/algorithms/filter.cpp +++ b/src/ipa/rkisp1/algorithms/filter.cpp @@ -8,11 +8,17 @@ #include "filter.h" #include +#include +#include +#include +#include #include #include +#include "linux/rkisp1-config.h" + /** * \file filter.h */ @@ -36,20 +42,161 @@ namespace ipa::rkisp1::algorithms { LOG_DEFINE_CATEGORY(RkISP1Filter) +namespace { + static constexpr uint32_t kFiltLumWeightDefault = 0x00022040; static constexpr uint32_t kFiltModeDefault = 0x000004f2; +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 */ + +Filter::Filter() + : noiseReductionModes_({}), + activeMode_(noiseReductionModes_.end()) +{ +} + /** * \copydoc libcamera::ipa::Algorithm::init */ int Filter::init(IPAContext &context, - [[maybe_unused]] const YamlObject &tuningData) + const YamlObject &tuningData) { auto &cmap = context.ctrlMap; cmap[&controls::Sharpness] = ControlInfo(0.0f, 10.0f, 1.0f); + /* Parse tuning block. */ + int ret = parseConfig(tuningData); + if (ret) + return ret; + + return 0; +} + +int Filter::parseConfig(const YamlObject &tuningData) +{ + /* Parse noise reduction modes. */ + if (!tuningData.contains("NoiseReductionModes")) { + LOG(RkISP1Filter, Error) << "Missing modes in Filter tuning data"; + return -EINVAL; + } + + noiseReductionModes_.clear(); + for (const auto &entry : tuningData["NoiseReductionModes"].asList()) { + std::optional typeOpt = + entry["type"].get(); + if (!typeOpt) { + LOG(RkISP1Filter, Error) << "Modes entry missing type"; + return -EINVAL; + } + + ModeConfig mode; + auto it = kModesMap.find(*typeOpt); + if (it == kModesMap.end()) { + LOG(RkISP1Filter, Error) << "Unknown mode type: " << *typeOpt; + return -EINVAL; + } + + mode.modeValue = it->second; + int ret = parseSingleConfig(entry, mode.config); + if (ret) { + LOG(RkISP1Filter, 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(RkISP1Filter, Warning) << "Invalid ActiveMode: " << activeMode; + activeMode_ = noiseReductionModes_.end(); + return 0; + } + + if (!loadConfig(it->second)) { + /* If the default "ReductionOff" mode is requested but not configured, disable Filter. */ + if (it->second == controls::draft::NoiseReductionModeOff) + activeMode_ = noiseReductionModes_.end(); + else + return -EINVAL; + } + + return 0; +} +int Filter::parseSingleConfig(const YamlObject &tuningData, + struct rkisp1_cif_isp_flt_config &config) +{ + if (!tuningData.contains("mode") || !tuningData.contains("lum_weight")) { + LOG(RkISP1Filter, Error) << "Modes entry missing mode or lum_weight"; + return -EINVAL; + } + + config.mode = tuningData["mode"].get().value_or(kFiltModeDefault); + config.lum_weight = tuningData["lum_weight"].get().value_or(kFiltLumWeightDefault); + config.grn_stage1 = tuningData["grn_stage1"].get().value_or(config.grn_stage1); + config.chr_h_mode = tuningData["chr_h_mode"].get().value_or(config.chr_h_mode); + config.chr_v_mode = tuningData["chr_v_mode"].get().value_or(config.chr_v_mode); + + config.thresh_bl0 = tuningData["thresh_bl0"].get().value_or(config.thresh_bl0); + config.thresh_bl1 = tuningData["thresh_bl1"].get().value_or(config.thresh_bl1); + config.thresh_sh0 = tuningData["thresh_sh0"].get().value_or(config.thresh_sh0); + config.thresh_sh1 = tuningData["thresh_sh1"].get().value_or(config.thresh_sh1); + + config.fac_sh0 = tuningData["fac_sh0"].get().value_or(config.fac_sh0); + config.fac_sh1 = tuningData["fac_sh1"].get().value_or(config.fac_sh1); + config.fac_mid = tuningData["fac_mid"].get().value_or(config.fac_mid); + config.fac_bl0 = tuningData["fac_bl0"].get().value_or(config.fac_bl0); + config.fac_bl1 = tuningData["fac_bl1"].get().value_or(config.fac_bl1); + return 0; } + +bool Filter::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(RkISP1Filter, Warning) + << "No Filter config for reduction mode: " << modeName(mode); + return false; + } + + activeMode_ = it; + + LOG(RkISP1Filter, Debug) + << "Filter mode=Reduction (config loaded)" + << " mode= " << modeName(mode); + + return true; +} + /** * \copydoc libcamera::ipa::Algorithm::queueRequest */ diff --git a/src/ipa/rkisp1/algorithms/filter.h b/src/ipa/rkisp1/algorithms/filter.h index 37d8938d..3860adfd 100644 --- a/src/ipa/rkisp1/algorithms/filter.h +++ b/src/ipa/rkisp1/algorithms/filter.h @@ -18,7 +18,7 @@ namespace ipa::rkisp1::algorithms { class Filter : public Algorithm { public: - Filter() = default; + Filter(); ~Filter() = default; int init(IPAContext &context, const YamlObject &tuningData) override; @@ -28,6 +28,20 @@ public: void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, RkISP1Params *params) override; + +private: + struct ModeConfig { + int32_t modeValue; + rkisp1_cif_isp_flt_config config; + }; + + int parseConfig(const YamlObject &tuningData); + int parseSingleConfig(const YamlObject &tuningData, + struct rkisp1_cif_isp_flt_config &config); + + bool loadConfig(int32_t mode); + std::vector noiseReductionModes_; + std::vector::const_iterator activeMode_; }; } /* namespace ipa::rkisp1::algorithms */ From patchwork Sun Jan 18 20:29:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 25827 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 93910BDCBE for ; Sun, 18 Jan 2026 20:30:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4F4C861FC1; Sun, 18 Jan 2026 21:30:49 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BCFtaLs7"; 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 A144B61FB9 for ; Sun, 18 Jan 2026 21:30:47 +0100 (CET) Received: from rui-Precision-7560.local (unknown [209.216.103.65]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 65CCF1BA; Sun, 18 Jan 2026 21:30:17 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1768768217; bh=EN+gD+60+RQ71IAR2RSCziVEWdBfA3CuEyD0y+lE4Qc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BCFtaLs7LIjP+v40pOGmtlUyXsLfzgjXbFuCI+lWBI99in8Na2OEpmRCg75gfsCLm LnTQV9kC/EOrhs/iI7CLzrthu3BLOamw3WcRqjIhIfwSFDmB4TXtmVFWXFem/hmY/s zr9QstmpAJyL9T9y4wj1cz5vIzVOiY3AxZ9isxoE= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v1 2/4] pa: rkisp1: algorithms: filter: Add helper fun and sharpness presets Date: Sun, 18 Jan 2026 15:29:51 -0500 Message-ID: <20260118202953.1554892-3-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260118202953.1554892-1-rui.wang@ideasonboard.com> References: <20260118202953.1554892-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" Refactor the Filter algorithm to improve code organization and prepare for future sharpness control implementation. Add helper functions to separate concerns: - prepareDisabledMode(): Handle filter disable state - prepareEnabledMode(): Handle filter enable state with logging - logConfig(): Provide detailed filter configuration logging Introduce sharpness preset table (kSharpnessPresets) with 11 levels (0-10) defining sharpness factor combinations. These presets will be used in future commits to implement user-controllable sharpness levels. Move class documentation to follow the anonymous namespace for better code organization and consistency with other algorithms. No functional changes in this commit. Signed-off-by: Rui Wang --- src/ipa/rkisp1/algorithms/filter.cpp | 85 +++++++++++++++++++++++----- src/ipa/rkisp1/algorithms/filter.h | 7 +++ 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp index 321e4122..eb4049fd 100644 --- a/src/ipa/rkisp1/algorithms/filter.cpp +++ b/src/ipa/rkisp1/algorithms/filter.cpp @@ -27,19 +27,6 @@ namespace libcamera { namespace ipa::rkisp1::algorithms { -/** - * \class Filter - * \brief RkISP1 Filter control - * - * Denoise and Sharpness filters will be applied by RkISP1 during the - * demosaicing step. The denoise filter is responsible for removing noise from - * the image, while the sharpness filter will enhance its acutance. - * - * \todo In current version the denoise and sharpness control is based on user - * controls. In a future version it should be controlled automatically by the - * algorithm. - */ - LOG_DEFINE_CATEGORY(RkISP1Filter) namespace { @@ -67,8 +54,44 @@ std::string modeName(int32_t mode) return "ReductionUnknown"; } + +struct SharpnessPreset { + uint32_t fac_sh0; + uint32_t fac_sh1; + uint32_t fac_mid; + uint32_t fac_bl0; + uint32_t fac_bl1; +}; + +/* + * Sharpness presets + * The presets are based on the following table. + */ +static constexpr SharpnessPreset kSharpnessPresets[] = { + { 0x04, 0x04, 0x04, 0x02, 0x00 }, /* Level 0 */ + { 0x07, 0x08, 0x06, 0x02, 0x00 }, /* Level 1 */ + { 0x0a, 0x0c, 0x08, 0x04, 0x00 }, /* Level 2 */ + { 0x0c, 0x10, 0x0a, 0x06, 0x02 }, /* Level 3 */ + { 0x10, 0x16, 0x0c, 0x08, 0x04 }, /* Level 4 */ + { 0x14, 0x1b, 0x10, 0x0a, 0x04 }, /* Level 5 */ + { 0x1a, 0x20, 0x13, 0x0c, 0x06 }, /* Level 6 */ + { 0x1e, 0x26, 0x17, 0x10, 0x08 }, /* Level 7 */ + { 0x24, 0x2c, 0x1d, 0x15, 0x0d }, /* Level 8 */ + { 0x2a, 0x30, 0x22, 0x1a, 0x14 }, /* Level 9 */ + { 0x30, 0x3f, 0x28, 0x24, 0x20 }, /* Level 10 */ +}; } /* namespace */ + +/** + * \class Filter + * \brief RkISP1 Filter control + * + * Denoise and Sharpness filters will be applied by RkISP1 during the + * demosaicing step. The denoise filter is responsible for removing noise from + * the image, while the sharpness filter will enhance its acutance. + */ + Filter::Filter() : noiseReductionModes_({}), activeMode_(noiseReductionModes_.end()) @@ -365,6 +388,42 @@ void Filter::prepare([[maybe_unused]] IPAContext &context, } } +void Filter::prepareDisabledMode(RkISP1Params *params) +{ + auto config = params->block(); + config.setEnabled(false); +} + +void Filter::prepareEnabledMode(const uint32_t frame, + IPAFrameContext &frameContext, + RkISP1Params *params) +{ + auto config = params->block(); + config.setEnabled(true); + + if (frameContext.filter.update || frame == 0) + logConfig(*config); +} + +void Filter::logConfig(const struct rkisp1_cif_isp_flt_config &config) +{ + LOG(RkISP1Filter, Debug) + << "Filter config: mode=" << config.mode + << " lum_weight=" << config.lum_weight + << " grn_stage1=" << (int)config.grn_stage1 + << " chr_h_mode=" << (int)config.chr_h_mode + << " chr_v_mode=" << (int)config.chr_v_mode + << " thresh_bl0=" << config.thresh_bl0 + << " thresh_bl1=" << config.thresh_bl1 + << " thresh_sh0=" << config.thresh_sh0 + << " thresh_sh1=" << config.thresh_sh1 + << " fac_sh1=" << config.fac_sh1 + << " fac_sh0=" << config.fac_sh0 + << " fac_mid=" << config.fac_mid + << " fac_bl0=" << config.fac_bl0 + << " fac_bl1=" << config.fac_bl1; +} + REGISTER_IPA_ALGORITHM(Filter, "Filter") } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/algorithms/filter.h b/src/ipa/rkisp1/algorithms/filter.h index 3860adfd..19cf76d0 100644 --- a/src/ipa/rkisp1/algorithms/filter.h +++ b/src/ipa/rkisp1/algorithms/filter.h @@ -40,6 +40,13 @@ private: struct rkisp1_cif_isp_flt_config &config); bool loadConfig(int32_t mode); + + void logConfig(const struct rkisp1_cif_isp_flt_config &config); + void prepareDisabledMode(RkISP1Params *params); + void prepareEnabledMode(const uint32_t frame, + IPAFrameContext &frameContext, + RkISP1Params *params); + std::vector noiseReductionModes_; std::vector::const_iterator activeMode_; }; From patchwork Sun Jan 18 20:29:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 25828 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 06AEEBDCBE for ; Sun, 18 Jan 2026 20:30:52 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C5ED261FB9; Sun, 18 Jan 2026 21:30:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="lvucb774"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D5D7761FC9 for ; Sun, 18 Jan 2026 21:30:49 +0100 (CET) Received: from rui-Precision-7560.local (unknown [209.216.103.65]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A7CE41BA; Sun, 18 Jan 2026 21:30:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1768768220; bh=EaKrU4DDAVryp1VaFb9jsIVpm/dzFkU8FuDyKZsQ46E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lvucb7746qs/f3BaKpxqKi3WndFswOeVWZbscDPzmjVX6kPnJ5A6dBj4jHF7sPhPG J5MqKJhaMv0FymdD/zCLn6tsgplK3R7BJ+LuKN4bavXTgZQOzKCnNpuzcvndSwfmlC ye3cS/JMkIlK/R0YxXmB/4njY/jqHjSr0b+69hFE= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v1 3/4] ipa: rkisp1: algorithms: filter: Integrate mode switching with prepare() Date: Sun, 18 Jan 2026 15:29:52 -0500 Message-ID: <20260118202953.1554892-4-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260118202953.1554892-1-rui.wang@ideasonboard.com> References: <20260118202953.1554892-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" Refactor the Filter algorithm's prepare() function to use the new mode switching infrastructure instead of hardcoded lookup tables. Key changes: - Replace hardcoded denoise/sharpness lookup tables with mode-based configuration loaded from tuning data via loadConfig(). - Refactor prepare() to delegate to prepareDisabledMode() and prepareEnabledMode() helper functions for better code organization. - Change filter.denoise from uint8_t to bool in IPAFrameContext to reflect its actual usage as an enable/disable flag. - Update queueRequest() to call loadConfig() for noise reduction mode selection, enabling runtime mode switching. - Apply sharpness as an override on top of the base noise reduction mode configuration using kSharpnessPresets. - Add bounds checking for sharpness level to prevent array overflow. - Support sharpness-only operation when no noise reduction mode is configured (activeMode_ == end()). The new implementation allows filter parameters to be fully configured via YAML tuning files while maintaining backward compatibility through the sharpness preset system. Signed-off-by: Rui Wang --- src/ipa/rkisp1/algorithms/filter.cpp | 146 ++++++++------------------- src/ipa/rkisp1/ipa_context.h | 2 +- 2 files changed, 41 insertions(+), 107 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp index eb4049fd..404ecd90 100644 --- a/src/ipa/rkisp1/algorithms/filter.cpp +++ b/src/ipa/rkisp1/algorithms/filter.cpp @@ -82,7 +82,6 @@ static constexpr SharpnessPreset kSharpnessPresets[] = { }; } /* namespace */ - /** * \class Filter * \brief RkISP1 Filter control @@ -245,26 +244,20 @@ void Filter::queueRequest(IPAContext &context, const auto &denoise = controls.get(controls::draft::NoiseReductionMode); if (denoise) { - LOG(RkISP1Filter, Debug) << "Set denoise to " << *denoise; - switch (*denoise) { case controls::draft::NoiseReductionModeOff: - if (filter.denoise != 0) { - filter.denoise = 0; + if (filter.denoise) { + filter.denoise = false; update = true; } break; case controls::draft::NoiseReductionModeMinimal: - if (filter.denoise != 1) { - filter.denoise = 1; - update = true; - } - break; case controls::draft::NoiseReductionModeHighQuality: case controls::draft::NoiseReductionModeFast: - if (filter.denoise != 3) { - filter.denoise = 3; + case controls::draft::NoiseReductionModeZSL: + if (loadConfig(*denoise)) { update = true; + filter.denoise = true; } break; default: @@ -273,6 +266,8 @@ void Filter::queueRequest(IPAContext &context, << *denoise; break; } + if (update) + LOG(RkISP1Filter, Debug) << "Set denoise to " << modeName(*denoise); } frameContext.filter.denoise = filter.denoise; @@ -284,108 +279,19 @@ void Filter::queueRequest(IPAContext &context, * \copydoc libcamera::ipa::Algorithm::prepare */ void Filter::prepare([[maybe_unused]] IPAContext &context, - [[maybe_unused]] const uint32_t frame, + const uint32_t frame, IPAFrameContext &frameContext, RkISP1Params *params) { /* Check if the algorithm configuration has been updated. */ if (!frameContext.filter.update) return; - static constexpr uint16_t filt_fac_sh0[] = { - 0x04, 0x07, 0x0a, 0x0c, 0x10, 0x14, 0x1a, 0x1e, 0x24, 0x2a, 0x30 - }; - - static constexpr uint16_t filt_fac_sh1[] = { - 0x04, 0x08, 0x0c, 0x10, 0x16, 0x1b, 0x20, 0x26, 0x2c, 0x30, 0x3f - }; - - static constexpr uint16_t filt_fac_mid[] = { - 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x10, 0x13, 0x17, 0x1d, 0x22, 0x28 - }; - - static constexpr uint16_t filt_fac_bl0[] = { - 0x02, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x10, 0x15, 0x1a, 0x24 - }; - - static constexpr uint16_t filt_fac_bl1[] = { - 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x06, 0x08, 0x0d, 0x14, 0x20 - }; - - static constexpr uint16_t filt_thresh_sh0[] = { - 0, 18, 26, 36, 41, 75, 90, 120, 170, 250, 1023 - }; - - static constexpr uint16_t filt_thresh_sh1[] = { - 0, 33, 44, 51, 67, 100, 120, 150, 200, 300, 1023 - }; - - static constexpr uint16_t filt_thresh_bl0[] = { - 0, 8, 13, 23, 26, 50, 60, 80, 140, 180, 1023 - }; - - static constexpr uint16_t filt_thresh_bl1[] = { - 0, 2, 5, 10, 15, 20, 26, 51, 100, 150, 1023 - }; - - static constexpr uint16_t stage1_select[] = { - 6, 6, 4, 4, 3, 3, 2, 2, 2, 1, 0 - }; - - static constexpr uint16_t filt_chr_v_mode[] = { - 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - static constexpr uint16_t filt_chr_h_mode[] = { - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - uint8_t denoise = frameContext.filter.denoise; - uint8_t sharpness = frameContext.filter.sharpness; - - auto config = params->block(); - config.setEnabled(true); - - config->fac_sh0 = filt_fac_sh0[sharpness]; - config->fac_sh1 = filt_fac_sh1[sharpness]; - config->fac_mid = filt_fac_mid[sharpness]; - config->fac_bl0 = filt_fac_bl0[sharpness]; - config->fac_bl1 = filt_fac_bl1[sharpness]; - - config->lum_weight = kFiltLumWeightDefault; - config->mode = kFiltModeDefault; - config->thresh_sh0 = filt_thresh_sh0[denoise]; - config->thresh_sh1 = filt_thresh_sh1[denoise]; - config->thresh_bl0 = filt_thresh_bl0[denoise]; - config->thresh_bl1 = filt_thresh_bl1[denoise]; - config->grn_stage1 = stage1_select[denoise]; - config->chr_v_mode = filt_chr_v_mode[denoise]; - config->chr_h_mode = filt_chr_h_mode[denoise]; - - /* - * Combined high denoising and high sharpening requires some - * adjustments to the configuration of the filters. A first stage - * filter with a lower strength must be selected, and the blur factors - * must be decreased. - */ - if (denoise == 9) { - if (sharpness > 3) - config->grn_stage1 = 2; - } else if (denoise == 10) { - if (sharpness > 5) - config->grn_stage1 = 2; - else if (sharpness > 3) - config->grn_stage1 = 1; + if (!frameContext.filter.denoise && !frameContext.filter.sharpness) { + prepareDisabledMode(params); + return; } - if (denoise > 7) { - if (sharpness > 7) { - config->fac_bl0 /= 2; - config->fac_bl1 /= 4; - } else if (sharpness > 4) { - config->fac_bl0 = config->fac_bl0 * 3 / 4; - config->fac_bl1 /= 2; - } - } + prepareEnabledMode(frame, frameContext, params); } void Filter::prepareDisabledMode(RkISP1Params *params) @@ -398,9 +304,37 @@ void Filter::prepareEnabledMode(const uint32_t frame, IPAFrameContext &frameContext, RkISP1Params *params) { + /* Ensure we have a valid mode configuration */ + if (activeMode_ == noiseReductionModes_.end() && frameContext.filter.sharpness == 0) + return; + + const ModeConfig &modeConfig = *activeMode_; + auto config = params->block(); config.setEnabled(true); + /* Load the base configuration from the active noise reduction mode */ + *config = modeConfig.config; + + /* + * Apply sharpness override if configured. + * Sharpness control modulates the sharpening factors on top of + * the base noise reduction mode configuration. + */ + uint8_t sharpness = frameContext.filter.sharpness; + if (sharpness > 0 && sharpness < std::size(kSharpnessPresets)) { + const SharpnessPreset &preset = kSharpnessPresets[sharpness]; + config->fac_sh0 = preset.fac_sh0; + config->fac_sh1 = preset.fac_sh1; + config->fac_mid = preset.fac_mid; + config->fac_bl0 = preset.fac_bl0; + config->fac_bl1 = preset.fac_bl1; + + /* Set mode to default if no active mode is configured */ + if (activeMode_ == noiseReductionModes_.end()) + config->mode = kFiltModeDefault; + } + if (frameContext.filter.update || frame == 0) logConfig(*config); } diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index b257cee5..4554f69b 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -190,7 +190,7 @@ struct IPAFrameContext : public FrameContext { } dpf; struct { - uint8_t denoise; + bool denoise; uint8_t sharpness; bool update; } filter; From patchwork Sun Jan 18 20:29:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 25829 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 9153DBDCBE for ; Sun, 18 Jan 2026 20:30:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5129F61FC6; Sun, 18 Jan 2026 21:30:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="XY6d4nn3"; 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 E3C3B61FC4 for ; Sun, 18 Jan 2026 21:30:51 +0100 (CET) Received: from rui-Precision-7560.local (unknown [209.216.103.65]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AA96F1BA; Sun, 18 Jan 2026 21:30:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1768768222; bh=2tKHiCOXdI7XE8K/9Cjk2rsU6b/hAY8TCZtwDlVPGR0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XY6d4nn3RYI+zREM2acG5cPQEwMdnj7jyA3/N0k2zdE3UtW8YpAXY0OqFttML+tCC iCu3X4CRmN+zH8KTUW+fB99S9jxum2XXZswhQc1hZFE43ge/baJRlUOPEyj1WdYwJ2 7DR33Gk4QZVbZomIjV7BQt6FjoBGy4hJ7fQHbAXs= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v1 4/4] ipa: rkisp1: data: Add Filter tuning configuration for sensors Date: Sun, 18 Jan 2026 15:29:53 -0500 Message-ID: <20260118202953.1554892-5-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260118202953.1554892-1-rui.wang@ideasonboard.com> References: <20260118202953.1554892-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" Add initial Filter algorithm tuning parameters for IMX219/OV5640 sensor, enabling filter noise reduction mode switching support. Signed-off-by: Rui Wang --- src/ipa/rkisp1/data/imx219.yaml | 48 +++++++++++++++++++++++++++++++++ src/ipa/rkisp1/data/ov5640.yaml | 47 ++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/src/ipa/rkisp1/data/imx219.yaml b/src/ipa/rkisp1/data/imx219.yaml index 0d99cb52..ff02b273 100644 --- a/src/ipa/rkisp1/data/imx219.yaml +++ b/src/ipa/rkisp1/data/imx219.yaml @@ -111,4 +111,52 @@ algorithms: 1438, 1226, 1059, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1025, 1054, 1185, 1326, 1334, 1334, ] + - Filter: + NoiseReductionModes: + - type: "ReductionMinimal" + mode: 1266 # 0x000004f2 in decimal + lum_weight: 139328 # 0x00022040 in decimal + grn_stage1: 6 + chr_h_mode: 3 + chr_v_mode: 3 + thresh_bl0: 8 + thresh_bl1: 2 + thresh_sh0: 18 + thresh_sh1: 33 + fac_sh0: 4 + fac_sh1: 4 + fac_mid: 4 + fac_bl0: 2 + fac_bl1: 0 + - type: "ReductionHighQuality" + mode: 1266 # 0x000004f2 in decimal + lum_weight: 139328 # 0x00022040 in decimal + grn_stage1: 6 + chr_h_mode: 3 + chr_v_mode: 3 + thresh_bl0: 8 + thresh_bl1: 2 + thresh_sh0: 18 + thresh_sh1: 33 + fac_sh0: 4 + fac_sh1: 4 + fac_mid: 4 + fac_bl0: 2 + fac_bl1: 0 + - type: "ReductionMinimal" + mode: 1266 # 0x000004f2 in decimal + lum_weight: 139328 # 0x00022040 in decimal + grn_stage1: 6 + chr_h_mode: 3 + chr_v_mode: 3 + thresh_bl0: 8 + thresh_bl1: 2 + thresh_sh0: 18 + thresh_sh1: 33 + fac_sh0: 4 + fac_sh1: 4 + fac_mid: 4 + fac_bl0: 2 + fac_bl1: 0 + ActiveMode: "ReductionHighQuality" ... diff --git a/src/ipa/rkisp1/data/ov5640.yaml b/src/ipa/rkisp1/data/ov5640.yaml index 4b21d412..8613380a 100644 --- a/src/ipa/rkisp1/data/ov5640.yaml +++ b/src/ipa/rkisp1/data/ov5640.yaml @@ -247,4 +247,51 @@ algorithms: g: 64 b: 64 - Filter: + NoiseReductionModes: + - type: "ReductionMinimal" + mode: 1266 # 0x000004f2 in decimal + lum_weight: 139328 # 0x00022040 in decimal + grn_stage1: 6 + chr_h_mode: 3 + chr_v_mode: 3 + thresh_bl0: 8 + thresh_bl1: 2 + thresh_sh0: 18 + thresh_sh1: 33 + fac_sh0: 4 + fac_sh1: 4 + fac_mid: 4 + fac_bl0: 2 + fac_bl1: 0 + - type: "ReductionHighQuality" + mode: 1266 # 0x000004f2 in decimal + lum_weight: 139328 # 0x00022040 in decimal + grn_stage1: 6 + chr_h_mode: 3 + chr_v_mode: 3 + thresh_bl0: 8 + thresh_bl1: 2 + thresh_sh0: 18 + thresh_sh1: 33 + fac_sh0: 4 + fac_sh1: 4 + fac_mid: 4 + fac_bl0: 2 + fac_bl1: 0 + - type: "ReductionMinimal" + mode: 1266 # 0x000004f2 in decimal + lum_weight: 139328 # 0x00022040 in decimal + grn_stage1: 6 + chr_h_mode: 3 + chr_v_mode: 3 + thresh_bl0: 8 + thresh_bl1: 2 + thresh_sh0: 18 + thresh_sh1: 33 + fac_sh0: 4 + fac_sh1: 4 + fac_mid: 4 + fac_bl0: 2 + fac_bl1: 0 + ActiveMode: "ReductionHighQuality" ...