From patchwork Mon Dec 8 00:48:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 25383 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 C818EC3257 for ; Mon, 8 Dec 2025 00:48:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7B9BD613FA; Mon, 8 Dec 2025 01:48:50 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="t6JSnqqr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 877C9613F2 for ; Mon, 8 Dec 2025 01:48:48 +0100 (CET) Received: from localhost.localdomain (unknown [209.216.103.65]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 25DD51E29; Mon, 8 Dec 2025 01:46:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1765154790; bh=TIx7IiB0QruV3c19NCJutrJAVQRu3rhDUppRcubS3eE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t6JSnqqrMQzdGydF4rrpgeh/rEeSlyc/GhQKKt5AjqQR13aBoPQ4dKgP94rQrrPez l7HGSrsjIrlU4KCMl0nEg9dShAkyeRj9ntlYXsjz/G5hed/x9aaHfikTwrUoC+Q9FU CjxEGGMlTnGUY9kfsrHNKfmTFKduG79TSRUTyoMM= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v4 5/7] ipa: rkisp1: algorithms: dpf: Use YamlObject::Getter for parsing Date: Sun, 7 Dec 2025 19:48:06 -0500 Message-ID: <20251208004808.1274417-6-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251208004808.1274417-1-rui.wang@ideasonboard.com> References: <20251208004808.1274417-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 DPF configuration parsing to use YamlObject::Getter specializations, similar to the approach used in pwl.cpp. This simplifies parseSingleConfig() by delegating the parsing logic to dedicated getter specializations. Implement two YamlObject::Getter specializations: - rkisp1_cif_isp_dpf_config: Parses filter and nll parameters - rkisp1_cif_isp_dpf_strength_config: Parses strength parameters The specializations are defined at the top of the file in the libcamera namespace. Remove LOG statements from the getter specializations to avoid namespace visibility issues, as the LOG macro requires access to the log category which is defined in a nested namespace. Signed-off-by: Rui Wang --- src/ipa/rkisp1/algorithms/dpf.cpp | 240 ++++++++++++++++-------------- 1 file changed, 125 insertions(+), 115 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp index dea04cc3..68a94afe 100644 --- a/src/ipa/rkisp1/algorithms/dpf.cpp +++ b/src/ipa/rkisp1/algorithms/dpf.cpp @@ -23,107 +23,31 @@ namespace libcamera { -namespace ipa::rkisp1::algorithms { - -/** - * \class Dpf - * \brief RkISP1 Denoise Pre-Filter control - * - * The denoise pre-filter algorithm is a bilateral filter which combines a - * range filter and a domain filter. The denoise pre-filter is applied before - * demosaicing. - */ - -LOG_DEFINE_CATEGORY(RkISP1Dpf) - -Dpf::Dpf() - : config_({}), strengthConfig_({}), - noiseReductionModes_({}), - runningMode_(controls::draft::NoiseReductionModeOff) -{ -} - -/** - * \copydoc libcamera::ipa::Algorithm::init - */ -int Dpf::init([[maybe_unused]] IPAContext &context, - const YamlObject &tuningData) -{ - /* Parse tuning block. */ - if (!parseConfig(tuningData)) { - return -EINVAL; - } - - return 0; -} - -bool Dpf::parseConfig(const YamlObject &tuningData) +template<> +std::optional +YamlObject::Getter::get(const YamlObject &obj) const { - /* Parse base config. */ - if (!parseSingleConfig(tuningData, config_, strengthConfig_)) { - return false; - } + rkisp1_cif_isp_dpf_strength_config config = {}; - /* Parse modes. */ - if (!parseModes(tuningData)) { - return false; - } + config.r = obj["r"].get().value_or(64); + config.g = obj["g"].get().value_or(64); + config.b = obj["b"].get().value_or(64); - return true; + return config; } -bool Dpf::parseModes(const YamlObject &tuningData) -{ - /* Parse noise reduction modes. */ - if (!tuningData.contains("modes")) { - return true; - } - - noiseReductionModes_.clear(); - for (const auto &entry : tuningData["modes"].asList()) { - std::optional typeOpt = - entry["type"].get(); - if (!typeOpt) { - LOG(RkISP1Dpf, Error) << "Modes entry missing type"; - return false; - } - - int32_t modeValue = controls::draft::NoiseReductionModeOff; - if (*typeOpt == "minimal") { - modeValue = controls::draft::NoiseReductionModeMinimal; - } else if (*typeOpt == "fast") { - modeValue = controls::draft::NoiseReductionModeFast; - } else if (*typeOpt == "highquality") { - modeValue = controls::draft::NoiseReductionModeHighQuality; - } else if (*typeOpt == "zsl") { - modeValue = controls::draft::NoiseReductionModeZSL; - } else { - LOG(RkISP1Dpf, Error) << "Unknown mode type: " << *typeOpt; - return false; - } - - ModeConfig mode{}; - mode.modeValue = modeValue; - if (!parseSingleConfig(entry, mode.dpf, mode.strength)) { - return false; - } - noiseReductionModes_.push_back(mode); - } - - return true; -} - -bool Dpf::parseSingleConfig(const YamlObject &tuningData, - rkisp1_cif_isp_dpf_config &config, - rkisp1_cif_isp_dpf_strength_config &strengthConfig) +template<> +std::optional +YamlObject::Getter::get(const YamlObject &obj) const { + rkisp1_cif_isp_dpf_config config = {}; std::vector values; /* * The domain kernel is configured with a 9x9 kernel for the green * pixels, and a 13x9 or 9x9 kernel for red and blue pixels. */ - const YamlObject &dFObject = tuningData["filter"]; + const YamlObject &dFObject = obj["filter"]; /* * For the green component, we have the 9x9 kernel specified @@ -144,11 +68,7 @@ bool Dpf::parseSingleConfig(const YamlObject &tuningData, */ values = dFObject["g"].getList().value_or(std::vector{}); if (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) { - LOG(RkISP1Dpf, Error) - << "Invalid 'filter:g': expected " - << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - << " elements, got " << values.size(); - return false; + return std::nullopt; } std::copy_n(values.begin(), values.size(), @@ -181,12 +101,7 @@ bool Dpf::parseSingleConfig(const YamlObject &tuningData, values = dFObject["rb"].getList().value_or(std::vector{}); if (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS && values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1) { - LOG(RkISP1Dpf, Error) - << "Invalid 'filter:rb': expected " - << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1 - << " or " << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - << " elements, got " << values.size(); - return false; + return std::nullopt; } config.rb_flt.fltsize = values.size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS @@ -204,39 +119,134 @@ bool Dpf::parseSingleConfig(const YamlObject &tuningData, * which stores a piecewise linear function that characterizes the * sensor noise profile as a noise level function curve (NLF). */ - const YamlObject &rFObject = tuningData["nll"]; + const YamlObject &rFObject = obj["nll"]; std::vector nllValues; nllValues = rFObject["coeff"].getList().value_or(std::vector{}); if (nllValues.size() != RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS) { - LOG(RkISP1Dpf, Error) - << "Invalid 'nll:coeff': expected " - << RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS - << " elements, got " << nllValues.size(); - return false; + return std::nullopt; } std::copy_n(nllValues.begin(), nllValues.size(), std::begin(config.nll.coeff)); - std::string scaleMode = rFObject["scale-mode"].get(""); + std::string scaleMode = rFObject["scale-mode"].get().value_or(""); if (scaleMode == "linear") { config.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LINEAR; } else if (scaleMode == "logarithmic") { config.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC; } else { - LOG(RkISP1Dpf, Error) - << "Invalid 'nll:scale-mode': expected " - << "'linear' or 'logarithmic' value, got " - << scaleMode; + return std::nullopt; + } + + return config; +} + +namespace ipa::rkisp1::algorithms { + +/** + * \class Dpf + * \brief RkISP1 Denoise Pre-Filter control + * + * The denoise pre-filter algorithm is a bilateral filter which combines a + * range filter and a domain filter. The denoise pre-filter is applied before + * demosaicing. + */ + +LOG_DEFINE_CATEGORY(RkISP1Dpf) + +Dpf::Dpf() + : config_({}), strengthConfig_({}), + noiseReductionModes_({}), + runningMode_(controls::draft::NoiseReductionModeOff) +{ +} + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Dpf::init([[maybe_unused]] IPAContext &context, + const YamlObject &tuningData) +{ + /* Parse tuning block. */ + if (!parseConfig(tuningData)) { + return -EINVAL; + } + + return 0; +} + +bool Dpf::parseConfig(const YamlObject &tuningData) +{ + /* Parse base config. */ + if (!parseSingleConfig(tuningData, config_, strengthConfig_)) { + return false; + } + + /* Parse modes. */ + if (!parseModes(tuningData)) { return false; } - const YamlObject &fSObject = tuningData["strength"]; + return true; +} + +bool Dpf::parseModes(const YamlObject &tuningData) +{ + /* Parse noise reduction modes. */ + if (!tuningData.contains("modes")) { + return true; + } + + noiseReductionModes_.clear(); + for (const auto &entry : tuningData["modes"].asList()) { + std::optional typeOpt = + entry["type"].get(); + if (!typeOpt) { + LOG(RkISP1Dpf, Error) << "Modes entry missing type"; + return false; + } + + int32_t modeValue = controls::draft::NoiseReductionModeOff; + if (*typeOpt == "minimal") { + modeValue = controls::draft::NoiseReductionModeMinimal; + } else if (*typeOpt == "fast") { + modeValue = controls::draft::NoiseReductionModeFast; + } else if (*typeOpt == "highquality") { + modeValue = controls::draft::NoiseReductionModeHighQuality; + } else if (*typeOpt == "zsl") { + modeValue = controls::draft::NoiseReductionModeZSL; + } else { + LOG(RkISP1Dpf, Error) << "Unknown mode type: " << *typeOpt; + return false; + } + + ModeConfig mode{}; + mode.modeValue = modeValue; + if (!parseSingleConfig(entry, mode.dpf, mode.strength)) { + return false; + } + noiseReductionModes_.push_back(mode); + } + + return true; +} + +bool Dpf::parseSingleConfig(const YamlObject &tuningData, + rkisp1_cif_isp_dpf_config &config, + rkisp1_cif_isp_dpf_strength_config &strengthConfig) +{ + auto dpfConfig = tuningData.get(); + if (!dpfConfig) + return false; + + config = *dpfConfig; + + auto strength = tuningData["strength"].get(); + if (!strength) + return false; - strengthConfig.r = fSObject["r"].get().value_or(64); - strengthConfig.g = fSObject["g"].get().value_or(64); - strengthConfig.b = fSObject["b"].get().value_or(64); + strengthConfig = *strength; return true; }