From patchwork Fri Feb 20 22:16:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 26217 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 ABACEC31E9 for ; Fri, 20 Feb 2026 22:16:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9FF1562275; Fri, 20 Feb 2026 23:16:55 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="NTik3Bjr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8393161FBF for ; Fri, 20 Feb 2026 23:16:53 +0100 (CET) Received: from rui-Precision-7560.tail5b760b.ts.net (unknown [209.216.103.65]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 20637502; Fri, 20 Feb 2026 23:15:58 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1771625759; bh=GauuDHtv0Vz48pGtsUQv+Z1WpKO5Ya6jB6yxkg+1kRw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NTik3Bjrc/YyLdrCO9S6QSZkYWcFirh1AuN6AK7Z6Vyimh7uV+sWcJ2FDiJsO8PGs AgegbSnYSLw1LcHPag1xsSCtDlJRXzKo+KHxSAW9oefjl95hyyCXJ0xpotripk8Z8o Pm/k31uAjz9c4yucpfEKxJ+jvTwaR5COvwj8QVqI= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v2 1/7] ipa: rkisp1: filter: Parse tuning modes/sharpness from config Date: Fri, 20 Feb 2026 17:16:30 -0500 Message-ID: <20260220221636.216353-2-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260220221636.216353-1-rui.wang@ideasonboard.com> References: <20260220221636.216353-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 Filter tuning parsers for NoiseReductionModes and Sharpness, - Validate keys during parsing, and store parsed values in unordered_map/unordered_set-based containers for faster lookup and simpler key-based access. Sample format in YAML: - Filter: NoiseReductionModes: NoiseReductionModeFast: [thresh_sh0: 18, thresh_sh1: 33, thresh_bl0: 8, thresh_bl1: 2, mode: 1, lum_weight: 2, grn_stage1: 4, chr_v_mode: 3, chr_h_mode: 3, fac_sh0: 4, fac_sh1: 4, fac_mid: 4, fac_bl0: 2, fac_bl1:0] Sharpness: - [fac_sh0: 4, fac_sh1: 4, fac_mid: 4, fac_bl0: 2, fac_bl1: 0] Signed-off-by: Rui Wang --- src/ipa/rkisp1/algorithms/filter.cpp | 128 +++++++++++++++++++++++++++ src/ipa/rkisp1/algorithms/filter.h | 10 +++ 2 files changed, 138 insertions(+) diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp index 8ad79801..85963f8c 100644 --- a/src/ipa/rkisp1/algorithms/filter.cpp +++ b/src/ipa/rkisp1/algorithms/filter.cpp @@ -8,6 +8,7 @@ #include "filter.h" #include +#include #include @@ -39,6 +40,18 @@ LOG_DEFINE_CATEGORY(RkISP1Filter) static constexpr uint32_t kFiltLumWeightDefault = 0x00022040; static constexpr uint32_t kFiltModeDefault = 0x000004f2; +namespace { +const std::unordered_set kSharpnessKeyNames = { + "fac_sh0", "fac_sh1", "fac_mid", "fac_bl0", "fac_bl1" +}; + +const std::unordered_set kFilterKeyNames = { + "thresh_sh0", "thresh_sh1", "thresh_bl0", "thresh_bl1", + "mode", "lum_weight", "grn_stage1", "chr_v_mode", "chr_h_mode", + "fac_sh0", "fac_sh1", "fac_mid", "fac_bl0", "fac_bl1" +}; +} /* namespace */ + /** * \copydoc libcamera::ipa::Algorithm::init */ @@ -50,6 +63,121 @@ int Filter::init(IPAContext &context, return 0; } + +int Filter::parseConfig(const YamlObject &tuningData) +{ + if (!tuningData.contains("NoiseReductionModes")) { + LOG(RkISP1Filter, Error) << "Missing NoiseReductionModes in Filter tuning data"; + return -EINVAL; + } + + const YamlObject &modesObject = tuningData["NoiseReductionModes"]; + if (!modesObject.isDictionary()) { + LOG(RkISP1Filter, Error) << "NoiseReductionModes must be a dictionary"; + return -EINVAL; + } + + for (const auto &[modeName, modeData] : modesObject.asDict()) { + auto it = controls::draft::NoiseReductionModeNameValueMap.find(modeName); + if (it == controls::draft::NoiseReductionModeNameValueMap.end()) { + LOG(RkISP1Filter, Error) << "Unknown mode: " << modeName; + return -EINVAL; + } + + int ret = parseModeConfig(modeData, modes_[it->second]); + if (ret) + return ret; + } + + if (!tuningData.contains("Sharpness")) { + LOG(RkISP1Filter, Error) << "Missing Sharpness in Filter tuning data"; + return -EINVAL; + } + + const YamlObject &sharpnessObject = tuningData["Sharpness"]; + if (!sharpnessObject.isList()) { + LOG(RkISP1Filter, Error) << "Sharpness must be a list"; + return -EINVAL; + } + + const size_t sharpnessLevels = sharpnessObject.size(); + if (!sharpnessLevels) { + LOG(RkISP1Filter, Error) << "Sharpness must not be empty"; + return -EINVAL; + } + + sharpness_.assign(sharpnessLevels, {}); + + for (size_t i = 0; i < sharpnessLevels; i++) { + int ret = parseSharpnessConfig(sharpnessObject[i], sharpness_[i]); + if (ret) + return ret; + } + + return 0; +} + +int Filter::parseModeConfig(const YamlObject &modeData, + std::unordered_map &modeParams) +{ + if (!modeData.isList()) { + LOG(RkISP1Filter, Error) << "Mode config must be a list"; + return -EINVAL; + } + + for (const auto &entry : modeData.asList()) { + for (const auto &[key, val] : entry.asDict()) { + if (kFilterKeyNames.find(key) == kFilterKeyNames.end()) { + LOG(RkISP1Filter, Error) + << "Unknown mode key '" << key << "'"; + return -EINVAL; + } + + auto v = val.get(); + if (!v) { + LOG(RkISP1Filter, Error) + << "Invalid value for key '" << key << "'"; + return -EINVAL; + } + modeParams[key] = *v; + } + } + + return 0; +} + +int Filter::parseSharpnessConfig(const YamlObject &data, + std::unordered_map &sharpParams) +{ + if (!data.isList()) { + LOG(RkISP1Filter, Error) << "Sharpness entry must be a list"; + return -EINVAL; + } + + sharpParams.clear(); + + for (const auto &entry : data.asList()) { + for (const auto &[key, val] : entry.asDict()) { + if (kSharpnessKeyNames.find(key) == kSharpnessKeyNames.end()) { + LOG(RkISP1Filter, Error) + << "Unknown sharpness key '" << key << "'"; + return -EINVAL; + } + + auto v = val.get(); + if (!v) { + LOG(RkISP1Filter, Error) + << "Invalid value for key '" << key << "'"; + return -EINVAL; + } + + sharpParams[key] = *v; + } + } + + return 0; +} + /** * \copydoc libcamera::ipa::Algorithm::queueRequest */ diff --git a/src/ipa/rkisp1/algorithms/filter.h b/src/ipa/rkisp1/algorithms/filter.h index 37d8938d..83b90ef3 100644 --- a/src/ipa/rkisp1/algorithms/filter.h +++ b/src/ipa/rkisp1/algorithms/filter.h @@ -28,6 +28,16 @@ public: void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, RkISP1Params *params) override; + +private: + int parseConfig(const YamlObject &tuningData); + int parseModeConfig(const YamlObject &modeData, + std::unordered_map &modeParams); + int parseSharpnessConfig(const YamlObject &data, + std::unordered_map &sharpParams); + + std::unordered_map> modes_; + std::vector> sharpness_; }; } /* namespace ipa::rkisp1::algorithms */