Show a patch.

GET /api/1.1/patches/26122/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 26122,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/26122/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/26122/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20260210141925.547284-3-rui.wang@ideasonboard.com>",
    "date": "2026-02-10T14:19:20",
    "name": "[v14,2/7] ipa: rkisp1: algorithms: dpf: Implement mode switching",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "15271e51a754ebabaa4bcb402b9c240034b87282",
    "submitter": {
        "id": 241,
        "url": "https://patchwork.libcamera.org/api/1.1/people/241/?format=api",
        "name": "Rui Wang",
        "email": "rui.wang@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/26122/mbox/",
    "series": [
        {
            "id": 5781,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5781/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5781",
            "date": "2026-02-10T14:19:18",
            "name": "refactor DPF parsing and initialization",
            "version": 14,
            "mbox": "https://patchwork.libcamera.org/series/5781/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/26122/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/26122/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id B9037BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 10 Feb 2026 14:19:47 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D908A620FA;\n\tTue, 10 Feb 2026 15:19:45 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 45FFA620FA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 10 Feb 2026 15:19:43 +0100 (CET)",
            "from rui-Precision-7560.tail5b760b.ts.net (unknown\n\t[209.216.103.65])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 59B30E47;\n\tTue, 10 Feb 2026 15:18:56 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"CKXr9xRQ\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1770733136;\n\tbh=wKM0oKA1+wKD1l6DPaaDahXS+i9npn6oT+/F/N5wLDM=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=CKXr9xRQ73XrAhbKUwxPFQWiLKqcN7uFRzfo6RmmNcNVraaNgE2cxzVZfRHrm+HCi\n\t6YHj7jlvNFAjsBzr6OlI92mSBmOf2Sz+PB50aIMCUQwbARh8MmqCJJ/pstAtQMeu7k\n\tLAOU0d+rjKjxX7iJkY2aXakrLP5/+ZxcLTWNucuI=",
        "From": "Rui Wang <rui.wang@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Rui Wang <rui.wang@ideasonboard.com>,\n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>",
        "Subject": "[PATCH v14 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching",
        "Date": "Tue, 10 Feb 2026 09:19:20 -0500",
        "Message-ID": "<20260210141925.547284-3-rui.wang@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20260210141925.547284-1-rui.wang@ideasonboard.com>",
        "References": "<20260210141925.547284-1-rui.wang@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "libcamera-devel@lists.libcamera.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "<libcamera-devel.lists.libcamera.org>",
        "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>",
        "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>",
        "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>",
        "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Implement support for switching between different noise reduction modes.\nThis allows the DPF algorithm to be configured with different parameters\nbased on the requested noise reduction level (e.g., minimal, fast, high\nquality).\n\nMode configurations are stored in the tuning data as a list of modes,\nwith each mode specifying its 'type' and corresponding DPF parameters.\nAn optional 'ActiveMode' setting allows defining the default mode at\nstartup, defaulting to \"ReductionOff\" if not specified.\n\nThe Dpf class is refactored to store configurations in a vector and\ntrack the current mode using an iterator, which avoids data copying\nduring runtime.\n\nSigned-off-by: Rui Wang <rui.wang@ideasonboard.com>\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\n---\nchangelog since v5:\n - Update log verbos from Info to Debug in loadReductionConfig\n - Update log mode value to string to in loadReductionConfig\n - improving the return value changed like :\n       if (ret != 0)  -> if (ret)\n\n Reviewed-by tags from v5 are carried over (no function changes).\nchangelog since v6:\n - add { controls::draft::NoiseReductionModeOff, \"off\" }, to fix\n   out_of_range issue\n\nchangelog since v7:\n - Delete base config parse from parseConfig\n\nchangelog since v8:\n - remove config_ strengthConfig_ by replacing activeMode_ iterator\n   to avoiding data copy during config loading\n - Update kModesMap from std::map<int32_t, std:string>\n    std::map<std::string, int32_t> for quick search improvement\n - add ActiveMode as Stefan and Jacopo's review comments\n - update type : auto -> int for ret value\n - name change loadRecuctionConfig -> loadConfig\n - delete parseMode\n\nchangelog since v9: As Stefan's suggestion\n  - Update dpf reduction mode config structure format\n    from  list to dictionary :\n     NoiseReductionMode:\n       NoiseReductionMinimal:\n        ***\n       NoiseReductionZSL:\n        ***\n\nchangelog since v10:\n  - replace kModeMap with NoiseReductionModeNameValueMap and other\n    accordinglychangelog since v10:\n\nchangelog since v11:\n  - Change \"ActiveMode\" to active mode as Jacopo suggestion\n  - Add \"Off\" to noiseReductionMode_ as init and it can reduce on time\n    one loop\n  - Simple Debug log\n\nchangelog since v13:\n  - fix build issue :\n    -LOG(RkISP1Dpf, Debug) << \"Set denoise to \" << modeName(*denoise);\n    +LOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n---\n src/ipa/rkisp1/algorithms/dpf.cpp | 96 +++++++++++++++++++++++++++----\n src/ipa/rkisp1/algorithms/dpf.h   | 12 +++-\n 2 files changed, 95 insertions(+), 13 deletions(-)",
    "diff": "diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\nindex 3c970171..dd4234b5 100644\n--- a/src/ipa/rkisp1/algorithms/dpf.cpp\n+++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n@@ -37,7 +37,7 @@ namespace ipa::rkisp1::algorithms {\n LOG_DEFINE_CATEGORY(RkISP1Dpf)\n \n Dpf::Dpf()\n-\t: config_({}), strengthConfig_({})\n+\t: noiseReductionModes_({}), activeMode_(noiseReductionModes_.end())\n {\n }\n \n@@ -57,10 +57,62 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n \n int Dpf::parseConfig(const YamlObject &tuningData)\n {\n-\t/* Parse base config. */\n-\tint ret = parseSingleConfig(tuningData, config_, strengthConfig_);\n-\tif (ret)\n-\t\treturn ret;\n+\t/* Parse noise reduction modes. */\n+\tif (!tuningData.contains(\"NoiseReductionModes\")) {\n+\t\tLOG(RkISP1Dpf, Error) << \"Missing modes in DPF tuning data\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tconst YamlObject &modesObject = tuningData[\"NoiseReductionModes\"];\n+\tif (!modesObject.isDictionary()) {\n+\t\tLOG(RkISP1Dpf, Error) << \"NoiseReductionModes must be a dictionary\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tnoiseReductionModes_.clear();\n+\n+\t/*\n+\t * Always enable the Off mode, and ensure it is the first one.\n+\t * It may be overridden by the tuning data.\n+\t */\n+\tModeConfig offMode{};\n+\toffMode.modeValue = controls::draft::NoiseReductionModeOff;\n+\tnoiseReductionModes_.push_back(offMode);\n+\n+\tfor (const auto &[modeName, modeData] : modesObject.asDict()) {\n+\t\tauto it = controls::draft::NoiseReductionModeNameValueMap.find(modeName);\n+\t\tif (it == controls::draft::NoiseReductionModeNameValueMap.end()) {\n+\t\t\tLOG(RkISP1Dpf, Error) << \"Unknown mode type: \" << modeName;\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tModeConfig mode;\n+\t\tmode.modeValue = it->second;\n+\t\tint ret = parseSingleConfig(modeData, mode.dpf, mode.strength);\n+\t\tif (ret) {\n+\t\t\tLOG(RkISP1Dpf, Error) << \"Failed to parse mode: \" << modeName;\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tnoiseReductionModes_.push_back(mode);\n+\t}\n+\n+\t/*\n+\t * Parse the optional activeMode.\n+\t * If not present, default to \"NoiseReductionModeOff\".\n+\t */\n+\tstd::string activeMode =\n+\t\ttuningData[\"activeMode\"].get<std::string>().value_or(\"NoiseReductionModeOff\");\n+\n+\tauto it = controls::draft::NoiseReductionModeNameValueMap.find(activeMode);\n+\tif (it == controls::draft::NoiseReductionModeNameValueMap.end() || it->second == controls::draft::NoiseReductionModeOff) {\n+\t\tLOG(RkISP1Dpf, Warning) << \"Invalid activeMode: \" << activeMode;\n+\t\tactiveMode_ = noiseReductionModes_.end();\n+\t\treturn 0;\n+\t}\n+\n+\tif (!loadConfig(it->second))\n+\t\treturn -EINVAL;\n \n \treturn 0;\n }\n@@ -193,6 +245,25 @@ int Dpf::parseSingleConfig(const YamlObject &tuningData,\n \treturn 0;\n }\n \n+bool Dpf::loadConfig(int32_t mode)\n+{\n+\tauto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(),\n+\t\t\t       [mode](const ModeConfig &m) {\n+\t\t\t\t       return m.modeValue == mode;\n+\t\t\t       });\n+\tif (it == noiseReductionModes_.end()) {\n+\t\tLOG(RkISP1Dpf, Warning)\n+\t\t\t<< \"No DPF config for reduction mode: \" << mode;\n+\t\treturn false;\n+\t}\n+\n+\tactiveMode_ = it;\n+\n+\tLOG(RkISP1Dpf, Debug) << \"DPF mode = \" << mode;\n+\n+\treturn true;\n+}\n+\n /**\n  * \\copydoc libcamera::ipa::Algorithm::queueRequest\n  */\n@@ -206,8 +277,6 @@ void Dpf::queueRequest(IPAContext &context,\n \n \tconst auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n \tif (denoise) {\n-\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n-\n \t\tswitch (*denoise) {\n \t\tcase controls::draft::NoiseReductionModeOff:\n \t\t\tif (dpf.denoise) {\n@@ -218,9 +287,10 @@ void Dpf::queueRequest(IPAContext &context,\n \t\tcase controls::draft::NoiseReductionModeMinimal:\n \t\tcase controls::draft::NoiseReductionModeHighQuality:\n \t\tcase controls::draft::NoiseReductionModeFast:\n-\t\t\tif (!dpf.denoise) {\n-\t\t\t\tdpf.denoise = true;\n+\t\tcase controls::draft::NoiseReductionModeZSL:\n+\t\t\tif (loadConfig(*denoise)) {\n \t\t\t\tupdate = true;\n+\t\t\t\tdpf.denoise = true;\n \t\t\t}\n \t\t\tbreak;\n \t\tdefault:\n@@ -229,6 +299,8 @@ void Dpf::queueRequest(IPAContext &context,\n \t\t\t\t<< *denoise;\n \t\t\tbreak;\n \t\t}\n+\t\tif (update)\n+\t\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n \t}\n \n \tframeContext.dpf.denoise = dpf.denoise;\n@@ -251,8 +323,10 @@ void Dpf::prepare(IPAContext &context, const uint32_t frame,\n \tstrengthConfig.setEnabled(frameContext.dpf.denoise);\n \n \tif (frameContext.dpf.denoise) {\n-\t\t*config = config_;\n-\t\t*strengthConfig = strengthConfig_;\n+\t\tconst ModeConfig &modeConfig = *activeMode_;\n+\n+\t\t*config = modeConfig.dpf;\n+\t\t*strengthConfig = modeConfig.strength;\n \n \t\tconst auto &awb = context.configuration.awb;\n \t\tconst auto &lsc = context.activeState.lsc;\ndiff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\nindex 39186c55..11fc88e4 100644\n--- a/src/ipa/rkisp1/algorithms/dpf.h\n+++ b/src/ipa/rkisp1/algorithms/dpf.h\n@@ -30,13 +30,21 @@ public:\n \t\t     RkISP1Params *params) override;\n \n private:\n+\tstruct ModeConfig {\n+\t\tint32_t modeValue;\n+\t\trkisp1_cif_isp_dpf_config dpf;\n+\t\trkisp1_cif_isp_dpf_strength_config strength;\n+\t};\n+\n \tint parseConfig(const YamlObject &tuningData);\n \tint parseSingleConfig(const YamlObject &tuningData,\n \t\t\t      rkisp1_cif_isp_dpf_config &config,\n \t\t\t      rkisp1_cif_isp_dpf_strength_config &strengthConfig);\n \n-\tstruct rkisp1_cif_isp_dpf_config config_;\n-\tstruct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n+\tbool loadConfig(int32_t mode);\n+\n+\tstd::vector<ModeConfig> noiseReductionModes_;\n+\tstd::vector<ModeConfig>::const_iterator activeMode_;\n };\n \n } /* namespace ipa::rkisp1::algorithms */\n",
    "prefixes": [
        "v14",
        "2/7"
    ]
}