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;