From patchwork Tue Oct 28 21:17:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Wang X-Patchwork-Id: 24877 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 A6031BE080 for ; Tue, 28 Oct 2025 21:18:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5DF1160859; Tue, 28 Oct 2025 22:18:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="k/oi66q7"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 10DB360810 for ; Tue, 28 Oct 2025 22:18:40 +0100 (CET) Received: from rui-Precision-7560.local (unknown [209.216.122.90]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E389CAD0; Tue, 28 Oct 2025 22:16:50 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1761686211; bh=FSFjx2+KBC3XX1PCsgKL4Mp1WBBisM+Ozsd5gNs4tsw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k/oi66q7V7joWNQ4OAUzluyjMJPuEthU7r/L575OtmnqlpLJmfJpUCflHVxt/sYY7 0kKknwrtz89BGmnYmUrD3M0lZuihZ+UkwBXg1jx+cjmhNFwAossu6jtRYUPlZQDom3 Lo2oPf8+u2o3JmgvK5isE39VwaxWNgVDkLSNJiDQ= From: Rui Wang To: libcamera-devel@lists.libcamera.org Cc: Rui Wang Subject: [PATCH v1 07/17] ipa: rkisp1: algorithms: dpf: refactor Dpf init for tuning Date: Tue, 28 Oct 2025 17:17:40 -0400 Message-ID: <20251028211751.2761420-7-rui.wang@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251028211751.2761420-1-rui.wang@ideasonboard.com> References: <20251028211751.2761420-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" Replace the inline parsing in init() with a call to parseConfig(). This simplifies init() and allows the parsing logic to be reused. The refactor also adds logging of the parsed base tuning and preserves the base config for manual mode restoration. The init method now: - Calls parseConfig() to load tuning data - Logs the parsed base configuration - Caches base config for manual mode restore - Logs ISO level count if present - Registers controls via getControlMap() Signed-off-by: Rui Wang --- src/ipa/rkisp1/algorithms/dpf.cpp | 141 +++++------------------------- 1 file changed, 24 insertions(+), 117 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp index d1b89691..a5059741 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 @@ -47,127 +48,33 @@ Dpf::Dpf() int Dpf::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) { - 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["DomainFilter"]; - - /* - * For the green component, we have the 9x9 kernel specified - * as 6 coefficients: - * Y - * ^ - * 4 | 6 5 4 5 6 - * 3 | 5 3 3 5 - * 2 | 5 3 2 3 5 - * 1 | 3 1 1 3 - * 0 - 4 2 0 2 4 - * -1 | 3 1 1 3 - * -2 | 5 3 2 3 5 - * -3 | 5 3 3 5 - * -4 | 6 5 4 5 6 - * +---------|--------> X - * -4....-1 0 1 2 3 4 - */ - values = dFObject["g"].getList().value_or(std::vector{}); - if (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) { - LOG(RkISP1Dpf, Error) - << "Invalid 'DomainFilter:g': expected " - << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - << " elements, got " << values.size(); + /* Parse tuning block */ + if (!parseConfig(tuningData)) return -EINVAL; - } - std::copy_n(values.begin(), values.size(), - std::begin(config_.g_flt.spatial_coeff)); - - config_.g_flt.gr_enable = true; - config_.g_flt.gb_enable = true; - - /* - * For the red and blue components, we have the 13x9 kernel specified - * as 6 coefficients: - * - * Y - * ^ - * 4 | 6 5 4 3 4 5 6 - * | - * 2 | 5 4 2 1 2 4 5 - * | - * 0 - 5 3 1 0 1 3 5 - * | - * -2 | 5 4 2 1 2 4 5 - * | - * -4 | 6 5 4 3 4 5 6 - * +-------------|------------> X - * -6 -4 -2 0 2 4 6 - * - * For a 9x9 kernel, columns -6 and 6 are dropped, so coefficient - * number 6 is not used. - */ - 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 'DomainFilter:rb': expected " - << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1 - << " or " << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - << " elements, got " << values.size(); - return -EINVAL; - } - - config_.rb_flt.fltsize = values.size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - ? RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9 - : RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9; - - std::copy_n(values.begin(), values.size(), - std::begin(config_.rb_flt.spatial_coeff)); - - config_.rb_flt.r_enable = true; - config_.rb_flt.b_enable = true; - - /* - * The range kernel is configured with a noise level lookup table (NLL) - * which stores a piecewise linear function that characterizes the - * sensor noise profile as a noise level function curve (NLF). - */ - const YamlObject &rFObject = tuningData["NoiseLevelFunction"]; - - 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 'RangeFilter:coeff': expected " - << RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS - << " elements, got " << nllValues.size(); - return -EINVAL; - } + /* Log parsed base tuning (counts are always full-sized for base). */ + LOG(RkISP1Dpf, Info) + << "DPF init: base tuning parsed, G coeffs=" + << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS + << ", RB fltsize=" + << (config_.rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9 ? "13x9" : "9x9") + << ", NLL coeffs=" << RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS + << ", NLL scale=" + << (config_.nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC ? "log" : "linear") + << ", Strength (r,g,b)=" + << (int)strengthConfig_.r << "," << (int)strengthConfig_.g + << "," << (int)strengthConfig_.b; + + /* Preserve base (non-ISO) YAML configuration for restoration after manual mode. */ + baseConfig_ = config_; + baseStrengthConfig_ = strengthConfig_; - std::copy_n(nllValues.begin(), nllValues.size(), - std::begin(config_.nll.coeff)); - - std::string scaleMode = rFObject["scale-mode"].get(""); - 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 'RangeFilter:scale-mode': expected " - << "'linear' or 'logarithmic' value, got " - << scaleMode; - return -EINVAL; + /* Optional ISO-banded tuning */ + if (useIsoLevels_) { + LOG(RkISP1Dpf, Info) + << "DPF init: loaded " << isoLevels_.size() + << " ISO level(s) from tuning"; } - - const YamlObject &fSObject = tuningData["FilterStrength"]; - - strengthConfig_.r = fSObject["r"].get(64); - strengthConfig_.g = fSObject["g"].get(64); - strengthConfig_.b = fSObject["b"].get(64); - return 0; }