Patch Detail
Show a patch.
GET /api/1.1/patches/25174/?format=api
{ "id": 25174, "url": "https://patchwork.libcamera.org/api/1.1/patches/25174/?format=api", "web_url": "https://patchwork.libcamera.org/patch/25174/", "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": "<20251125000848.4103786-8-rui.wang@ideasonboard.com>", "date": "2025-11-25T00:08:44", "name": "[v1,07/11] ipa: rkisp1: algorithms: dpf: manage DPF mode transitions", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "85a729da7fd2461f7e5b27d8a28a3e77639e65c5", "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/25174/mbox/", "series": [ { "id": 5612, "url": "https://patchwork.libcamera.org/api/1.1/series/5612/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5612", "date": "2025-11-25T00:08:37", "name": "ipa: rkisp1: DPF refactor and tuning improvements", "version": 1, "mbox": "https://patchwork.libcamera.org/series/5612/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/25174/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/25174/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 E20F6C32EF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 25 Nov 2025 00:09:19 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5B56E60A8B;\n\tTue, 25 Nov 2025 01:09:19 +0100 (CET)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9FD9E60A8B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 25 Nov 2025 01:09:15 +0100 (CET)", "from rui-Precision-7560.local (unknown\n\t[IPv6:2607:fea8:935b:7220:cb34:a7b8:53d:5466])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D25731785;\n\tTue, 25 Nov 2025 01:07:06 +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=\"tJdhfQXv\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1764029227;\n\tbh=llQFiwM+wwa3hU9mE860NtaMHskSZpg7bThCsF1SPeA=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=tJdhfQXv7IC1jtF5dSNovpAgWQQauohBK6/uD/uTfVDEvqn33ZaSYLvChCJxdyr6h\n\tVTZPuKuVxgNYfYbT/ycYtMRNqP0u4AT3dVCo4sFbctGZG/BUUe742j+HLncZz03OlB\n\tvgz1KSz2c1wVRcxrRF7y0FpBZbuiyhsjxBfUvX4M=", "From": "Rui Wang <rui.wang@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Rui Wang <rui.wang@ideasonboard.com>", "Subject": "[PATCH v1 07/11] ipa: rkisp1: algorithms: dpf: manage DPF mode\n\ttransitions", "Date": "Mon, 24 Nov 2025 19:08:44 -0500", "Message-ID": "<20251125000848.4103786-8-rui.wang@ideasonboard.com>", "X-Mailer": "git-send-email 2.43.0", "In-Reply-To": "<20251125000848.4103786-1-rui.wang@ideasonboard.com>", "References": "<20251125000848.4103786-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 hysteresis-aware mode switching via processModeChange(), snapshot\nthe current configuration when entering manual mode, and restore base tuning\nwhen returning to auto mode.\n\nThe implementation includes:\n- processModeChange(): Detects DpfMode control changes with hysteresis to\n prevent rapid mode toggling\n- snapshotCurrentToOverrides(): Captures current config when entering manual\n mode so users can continue from current state\n- restoreAutoConfig(): Restores base or exposure gain config when returning to\n auto mode, clearing all manual overrides\n\nUpdates queueRequest() to handle mode transitions with appropriate logging\nand config restoration.\n\nSigned-off-by: Rui Wang <rui.wang@ideasonboard.com>\n---\n src/ipa/rkisp1/algorithms/denoise.h | 15 ++++\n src/ipa/rkisp1/algorithms/dpf.cpp | 121 +++++++++++++++++++++++++++-\n src/ipa/rkisp1/algorithms/dpf.h | 8 ++\n 3 files changed, 140 insertions(+), 4 deletions(-)", "diff": "diff --git a/src/ipa/rkisp1/algorithms/denoise.h b/src/ipa/rkisp1/algorithms/denoise.h\nindex ffe27af8..4c917c1a 100644\n--- a/src/ipa/rkisp1/algorithms/denoise.h\n+++ b/src/ipa/rkisp1/algorithms/denoise.h\n@@ -35,12 +35,27 @@ protected:\n \tvirtual void collectManualOverrides([[maybe_unused]] const ControlList &controls)\n \t{\n \t}\n+\tvirtual bool processModeChange([[maybe_unused]] const ControlList &controls,\n+\t\t\t\t [[maybe_unused]] uint32_t currentFrame)\n+\t{\n+\t\treturn false;\n+\t}\n+\tvirtual void snapshotCurrentToOverrides()\n+\t{\n+\t}\n+\tvirtual void restoreAutoConfig([[maybe_unused]] IPAContext &context, [[maybe_unused]] IPAFrameContext &frameContext)\n+\t{\n+\t}\n \tvirtual void handleReductionModeControl([[maybe_unused]] const ControlList &controls,\n \t\t\t\t\t\t[[maybe_unused]] IPAFrameContext &frameContext,\n \t\t\t\t\t\t[[maybe_unused]] IPAContext &context,\n \t\t\t\t\t\t[[maybe_unused]] uint32_t frame)\n \t{\n \t}\n+\tvirtual void handleDisableMode([[maybe_unused]] IPAFrameContext &frameContext,\n+\t\t\t\t [[maybe_unused]] IPAContext &context)\n+\t{\n+\t}\n \tvirtual int32_t getRunningMode() const { return currentRunMode_; }\n \tvirtual void setRunningMode(int32_t mode) { currentRunMode_ = mode; }\n private:\ndiff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\nindex 0b070206..91bcd503 100644\n--- a/src/ipa/rkisp1/algorithms/dpf.cpp\n+++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n@@ -339,6 +339,17 @@ void Dpf::handleReductionModeControl(const ControlList &controls,\n \tframeContext.dpf.denoise = true;\n \tframeContext.dpf.update = true;\n }\n+\n+void Dpf::handleDisableMode(IPAFrameContext &frameContext, IPAContext &context)\n+{\n+\t/* Reset reduction mode to Off when DPF is disabled */\n+\tcurrentReductionMode_ = controls::draft::NoiseReductionModeOff;\n+\n+\t/* Ensure denoise is disabled */\n+\tcontext.activeState.dpf.denoise = false;\n+\tframeContext.dpf.denoise = false;\n+}\n+\n void Dpf::loadReductionModeConfig(IPAFrameContext &frameContext)\n {\n \t/* Find mode config */\n@@ -474,6 +485,76 @@ bool Dpf::checkOverridesChanged()\n \treturn false;\n }\n \n+void Dpf::snapshotCurrentToOverrides()\n+{\n+\t/* clear previous overrides */\n+\toverrides_.clear();\n+\toverrides_.strength = DpfStrengthSettings{\n+\t\tstrengthConfig_.r,\n+\t\tstrengthConfig_.g,\n+\t\tstrengthConfig_.b\n+\t};\n+\tif (!isDevMode())\n+\t\treturn;\n+\t/* Snapshot current config to overrides */\n+\tDpfSpatialGreenSettings green;\n+\tstd::copy_n(std::begin(config_.g_flt.spatial_coeff),\n+\t\t RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS,\n+\t\t green.coeffs.begin());\n+\toverrides_.spatialGreen = green;\n+\tDpfSpatialRbSettings rb;\n+\tstd::copy_n(std::begin(config_.rb_flt.spatial_coeff),\n+\t\t RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS,\n+\t\t rb.coeffs.begin());\n+\trb.size = (config_.rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9)\n+\t\t\t ? 1\n+\t\t\t : 0;\n+\toverrides_.spatialRb = rb;\n+\toverrides_.rbSize = rb.size;\n+\tDpfNllSettings nll;\n+\tstd::copy_n(std::begin(config_.nll.coeff),\n+\t\t RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS,\n+\t\t nll.coeffs.begin());\n+\tnll.scaleMode = (config_.nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC)\n+\t\t\t\t? 1\n+\t\t\t\t: 0;\n+\toverrides_.nll = nll;\n+}\n+\n+void Dpf::restoreAutoConfig(IPAContext &context, IPAFrameContext &frameContext)\n+{\n+\t/* clear previous overrides */\n+\toverrides_.clear();\n+\tif (useExposureIndexLevels_) {\n+\t\tuint32_t exposureIndex = computeExposureIndex(context, frameContext);\n+\t\tint32_t idx =\n+\t\t\tDenoiseBaseAlgorithm::selectExposureIndexBand(exposureIndex,\n+\t\t\t\t\t\t\t\t exposureIndexLevels_);\n+\t\tif (idx >= 0) {\n+\t\t\tconfig_ = exposureIndexLevels_[idx].dpf;\n+\t\t\tstrengthConfig_ = exposureIndexLevels_[idx].strength;\n+\t\t\tlastExposureGainIndex_ = idx;\n+\t\t}\n+\t} else {\n+\t\tconfig_ = baseConfig_;\n+\t\tstrengthConfig_ = baseStrengthConfig_;\n+\t\tlastExposureGainIndex_ = -1;\n+\t}\n+\tframeContext.dpf.update = true;\n+}\n+\n+bool Dpf::processModeChange(const ControlList &controls, [[maybe_unused]] uint32_t currentFrame)\n+{\n+\tconst auto &cMode = controls.get(controls::rkisp1::DenoiseMode);\n+\tif (!cMode)\n+\t\treturn false;\n+\tint32_t requestedMode = static_cast<int32_t>(*cMode);\n+\tauto currentMode = getRunningMode();\n+\n+\tsetRunningMode(requestedMode);\n+\treturn (currentMode != getRunningMode());\n+}\n+\n /**\n * \\copydoc libcamera::ipa::Algorithm::queueRequest\n */\n@@ -483,13 +564,45 @@ void Dpf::queueRequest(IPAContext &context,\n \t\t const ControlList &controls)\n {\n \tframeContext.dpf.update = false;\n-\tauto currentRunnungMode = getRunningMode();\n-\thandleReductionModeControl(controls, frameContext, context, frame);\n \n-\tif (currentRunnungMode == controls::rkisp1::DenoiseModeReduction && currentReductionMode_ != controls::draft::NoiseReductionModeOff) {\n-\t\tloadReductionModeConfig(frameContext);\n+\tauto modeChanged = processModeChange(controls, frame);\n+\tswitch (getRunningMode()) {\n+\tcase controls::rkisp1::DenoiseModeManual:\n+\t\tsnapshotCurrentToOverrides();\n+\t\tcollectManualOverrides(controls);\n+\t\tif (checkOverridesChanged()) {\n+\t\t\tframeContext.dpf.update = true;\n+\t\t}\n+\t\tLOG(RkISP1Dpf, Debug) << \"DPF mode=Manual (snapshot captured)\";\n+\t\tbreak;\n+\tcase controls::rkisp1::DenoiseModeAuto:\n+\t\trestoreAutoConfig(context, frameContext);\n+\t\tLOG(RkISP1Dpf, Debug) << \"DPF mode=Auto (restored auto config)\";\n+\t\tbreak;\n+\tcase controls::rkisp1::DenoiseModeReduction:\n+\t\thandleReductionModeControl(controls,\n+\t\t\t\t\t frameContext,\n+\t\t\t\t\t context,\n+\t\t\t\t\t frame); /* Check reduction mode first */\n+\t\tif (currentReductionMode_ != controls::draft::NoiseReductionModeOff) {\n+\t\t\tloadReductionModeConfig(frameContext);\n+\t\t}\n+\t\tLOG(RkISP1Dpf, Debug) << \"DPF mode=Reduction (config loaded)\";\n+\t\tbreak;\n+\tcase controls::rkisp1::DenoiseModeDisabled:\n+\t\thandleDisableMode(frameContext, context);\n+\t\tbreak;\n+\tdefault:\n+\t\tLOG(RkISP1Dpf, Warning) << \"DPF mode=Disabled\";\n \t\treturn;\n \t}\n+\t/* Set denoise based on mode */\n+\n+\tif (modeChanged)\n+\t\tframeContext.dpf.update = true;\n+\tbool denoise = (getRunningMode() != controls::rkisp1::DenoiseModeDisabled);\n+\tcontext.activeState.dpf.denoise = denoise;\n+\tframeContext.dpf.denoise = denoise;\n }\n \n /**\ndiff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\nindex d6707d34..c63d1558 100644\n--- a/src/ipa/rkisp1/algorithms/dpf.h\n+++ b/src/ipa/rkisp1/algorithms/dpf.h\n@@ -71,12 +71,14 @@ private:\n \tstd::vector<ExposureIndexLevelConfig> exposureIndexLevels_;\n \tstd::vector<ModeConfig> modes_;\n \tbool useExposureIndexLevels_ = false;\n+\tint32_t lastExposureGainIndex_ = -1;\n \tint32_t currentReductionMode_ = controls::draft::NoiseReductionModeOff;\n \n \tvoid handleReductionModeControl(const ControlList &controls,\n \t\t\t\t\tIPAFrameContext &frameContext,\n \t\t\t\t\tIPAContext &context,\n \t\t\t\t\tuint32_t frame) override;\n+\tvoid handleDisableMode(IPAFrameContext &frameContext, IPAContext &context) override;\n \tvoid loadReductionModeConfig(IPAFrameContext &frameContext);\n \tvoid collectManualOverrides(const ControlList &controls) override;\n \tbool checkOverridesChanged();\n@@ -84,6 +86,12 @@ private:\n \tbool 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+\tbool processModeChange(const ControlList &controls, uint32_t currentFrame) override;\n+\n+\tvoid snapshotCurrentToOverrides() override;\n+\n+\tvoid restoreAutoConfig(IPAContext &context, IPAFrameContext &frameContext) override;\n };\n \n } /* namespace ipa::rkisp1::algorithms */\n", "prefixes": [ "v1", "07/11" ] }