[{"id":37805,"web_url":"https://patchwork.libcamera.org/comment/37805/","msgid":"<176901127352.23550.5669981077089400878@localhost>","date":"2026-01-21T16:01:13","subject":"Re: [PATCH v10 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","submitter":{"id":184,"url":"https://patchwork.libcamera.org/api/people/184/","name":"Stefan Klug","email":"stefan.klug@ideasonboard.com"},"content":"Hi Rui,\n\nThank you for the patch.\n\nQuoting Rui Wang (2026-01-20 16:30:52)\n> Implement support for switching between different noise reduction modes.\n> This allows the DPF algorithm to be configured with different parameters\n> based on the requested noise reduction level (e.g., minimal, fast, high\n> quality).\n> \n> Mode configurations are stored in the tuning data as a list of modes,\n> with each mode specifying its 'type' and corresponding DPF parameters.\n> An optional 'ActiveMode' setting allows defining the default mode at\n> startup, defaulting to \"ReductionOff\" if not specified.\n> \n> The Dpf class is refactored to store configurations in a vector and\n> track the current mode using an iterator, which avoids data copying\n> during runtime.\n> \n> Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>\n> \n> ---\n> changelog 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).\n> changelog since v6:\n>  - add { controls::draft::NoiseReductionModeOff, \"off\" }, to fix\n>    out_of_range issue\n> \n> changelog since v7:\n>  - Delete base config parse from parseConfig\n> \n> changelog 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> \n> changelog 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> ---\n>  src/ipa/rkisp1/algorithms/dpf.cpp | 117 +++++++++++++++++++++++++++---\n>  src/ipa/rkisp1/algorithms/dpf.h   |  12 ++-\n>  2 files changed, 116 insertions(+), 13 deletions(-)\n> \n> diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\n> index dd3effa1..659a1a82 100644\n> --- a/src/ipa/rkisp1/algorithms/dpf.cpp\n> +++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n> @@ -8,6 +8,7 @@\n>  #include \"dpf.h\"\n>  \n>  #include <algorithm>\n> +#include <map>\n>  #include <string>\n>  #include <vector>\n>  \n> @@ -36,8 +37,32 @@ namespace ipa::rkisp1::algorithms {\n>  \n>  LOG_DEFINE_CATEGORY(RkISP1Dpf)\n>  \n> +namespace {\n> +\n> +const std::map<std::string, int32_t> kModesMap = {\n> +       { \"ReductionMinimal\", controls::draft::NoiseReductionModeMinimal },\n> +       { \"ReductionFast\", controls::draft::NoiseReductionModeFast },\n> +       { \"ReductionHighQuality\", controls::draft::NoiseReductionModeHighQuality },\n> +       { \"ReductionZSL\", controls::draft::NoiseReductionModeZSL },\n> +       { \"ReductionOff\", controls::draft::NoiseReductionModeOff },\n> +};\n\nThe need to have this translation map doesn't seem right. If you look at\nthe AEGC implementation the lookup is done through\nAeConstraintModeNameValueMap. The names I proposed don't match the\nnaming scheme of the enum. So I see two options here: \n\n1. Renaming the enum entries\n\nI think this would be the right thing to do, but it will be difficult\nto upstream because the Rpi IPA already uses the old names. And the\nnaming on the control enums seems not to be fully consistent anyways.\n\n2. Change the names in the tuning file to be in sync with the enum\nentries\n\nThis is the easier option and as the tuning file format will change\nanyway it won't hurt anybody. Then you could drop this extra translation\nmap and rely on the enum names.\n\n\nMaybe I could have made it more clear that my naming was a idea but not\nfully checked - sorry for that.\n\nBest regards,\nStefan\n\n> +\n> +std::string modeName(int32_t mode)\n> +{\n> +       auto it = std::find_if(kModesMap.begin(), kModesMap.end(),\n> +                              [mode](const auto &pair) {\n> +                                      return pair.second == mode;\n> +                              });\n> +\n> +       if (it != kModesMap.end())\n> +               return it->first;\n> +\n> +       return \"ReductionUnknown\";\n> +}\n> +} /* namespace */\n> +\n>  Dpf::Dpf()\n> -       : config_({}), strengthConfig_({})\n> +       : noiseReductionModes_({}), activeMode_(noiseReductionModes_.end())\n>  {\n>  }\n>  \n> @@ -57,10 +82,56 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n>  \n>  int Dpf::parseConfig(const YamlObject &tuningData)\n>  {\n> -       /* Parse base config. */\n> -       int ret = parseSingleConfig(tuningData, config_, strengthConfig_);\n> -       if (ret)\n> -               return ret;\n> +       /* Parse noise reduction modes. */\n> +       if (!tuningData.contains(\"NoiseReductionModes\")) {\n> +               LOG(RkISP1Dpf, Error) << \"Missing modes in DPF tuning data\";\n> +               return -EINVAL;\n> +       }\n> +\n> +       const YamlObject &modesObject = tuningData[\"NoiseReductionModes\"];\n> +       if (!modesObject.isDictionary()) {\n> +               LOG(RkISP1Dpf, Error) << \"NoiseReductionModes must be a dictionary\";\n> +               return -EINVAL;\n> +       }\n> +\n> +       noiseReductionModes_.clear();\n> +       for (const auto &[modeName, modeData] : modesObject.asDict()) {\n> +               auto it = kModesMap.find(modeName);\n> +               if (it == kModesMap.end()) {\n> +                       LOG(RkISP1Dpf, Error) << \"Unknown mode type: \" << modeName;\n> +                       return -EINVAL;\n> +               }\n> +\n> +               ModeConfig mode;\n> +               mode.modeValue = it->second;\n> +               int ret = parseSingleConfig(modeData, mode.dpf, mode.strength);\n> +               if (ret) {\n> +                       LOG(RkISP1Dpf, Error) << \"Failed to parse mode: \" << modeName;\n> +                       return ret;\n> +               }\n> +\n> +               noiseReductionModes_.push_back(mode);\n> +       }\n> +\n> +       /*\n> +        * Parse the optional ActiveMode.\n> +        * If not present, default to \"ReductionOff\".\n> +        */\n> +       std::string activeMode = tuningData[\"ActiveMode\"].get<std::string>().value_or(\"ReductionOff\");\n> +       auto it = kModesMap.find(activeMode);\n> +       if (it == kModesMap.end()) {\n> +               LOG(RkISP1Dpf, Warning) << \"Invalid ActiveMode: \" << activeMode;\n> +               activeMode_ = noiseReductionModes_.end();\n> +               return 0;\n> +       }\n> +\n> +       if (!loadConfig(it->second)) {\n> +               /* If the default \"ReductionOff\" mode is requested but not configured, disable DPF. */\n> +               if (it->second == controls::draft::NoiseReductionModeOff)\n> +                       activeMode_ = noiseReductionModes_.end();\n> +               else\n> +                       return -EINVAL;\n> +       }\n>  \n>         return 0;\n>  }\n> @@ -193,6 +264,27 @@ int Dpf::parseSingleConfig(const YamlObject &tuningData,\n>         return 0;\n>  }\n>  \n> +bool Dpf::loadConfig(int32_t mode)\n> +{\n> +       auto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(),\n> +                              [mode](const ModeConfig &m) {\n> +                                      return m.modeValue == mode;\n> +                              });\n> +       if (it == noiseReductionModes_.end()) {\n> +               LOG(RkISP1Dpf, Warning)\n> +                       << \"No DPF config for reduction mode: \" << modeName(mode);\n> +               return false;\n> +       }\n> +\n> +       activeMode_ = it;\n> +\n> +       LOG(RkISP1Dpf, Debug)\n> +               << \"DPF mode=Reduction (config loaded)\"\n> +               << \" mode= \" << modeName(mode);\n> +\n> +       return true;\n> +}\n> +\n>  /**\n>   * \\copydoc libcamera::ipa::Algorithm::queueRequest\n>   */\n> @@ -206,8 +298,6 @@ void Dpf::queueRequest(IPAContext &context,\n>  \n>         const auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n>         if (denoise) {\n> -               LOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n> -\n>                 switch (*denoise) {\n>                 case controls::draft::NoiseReductionModeOff:\n>                         if (dpf.denoise) {\n> @@ -218,9 +308,10 @@ void Dpf::queueRequest(IPAContext &context,\n>                 case controls::draft::NoiseReductionModeMinimal:\n>                 case controls::draft::NoiseReductionModeHighQuality:\n>                 case controls::draft::NoiseReductionModeFast:\n> -                       if (!dpf.denoise) {\n> -                               dpf.denoise = true;\n> +               case controls::draft::NoiseReductionModeZSL:\n> +                       if (loadConfig(*denoise)) {\n>                                 update = true;\n> +                               dpf.denoise = true;\n>                         }\n>                         break;\n>                 default:\n> @@ -229,6 +320,8 @@ void Dpf::queueRequest(IPAContext &context,\n>                                 << *denoise;\n>                         break;\n>                 }\n> +               if (update)\n> +                       LOG(RkISP1Dpf, Debug) << \"Set denoise to \" << modeName(*denoise);\n>         }\n>  \n>         frameContext.dpf.denoise = dpf.denoise;\n> @@ -251,8 +344,10 @@ void Dpf::prepare(IPAContext &context, const uint32_t frame,\n>         strengthConfig.setEnabled(frameContext.dpf.denoise);\n>  \n>         if (frameContext.dpf.denoise) {\n> -               *config = config_;\n> -               *strengthConfig = strengthConfig_;\n> +               const ModeConfig &modeConfig = *activeMode_;\n> +\n> +               *config = modeConfig.dpf;\n> +               *strengthConfig = modeConfig.strength;\n>  \n>                 const auto &awb = context.configuration.awb;\n>                 const auto &lsc = context.configuration.lsc;\n> diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\n> index 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>                      RkISP1Params *params) override;\n>  \n>  private:\n> +       struct ModeConfig {\n> +               int32_t modeValue;\n> +               rkisp1_cif_isp_dpf_config dpf;\n> +               rkisp1_cif_isp_dpf_strength_config strength;\n> +       };\n> +\n>         int parseConfig(const YamlObject &tuningData);\n>         int parseSingleConfig(const YamlObject &tuningData,\n>                               rkisp1_cif_isp_dpf_config &config,\n>                               rkisp1_cif_isp_dpf_strength_config &strengthConfig);\n>  \n> -       struct rkisp1_cif_isp_dpf_config config_;\n> -       struct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n> +       bool loadConfig(int32_t mode);\n> +\n> +       std::vector<ModeConfig> noiseReductionModes_;\n> +       std::vector<ModeConfig>::const_iterator activeMode_;\n>  };\n>  \n>  } /* namespace ipa::rkisp1::algorithms */\n> -- \n> 2.43.0\n>","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 15252C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 16:01:20 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 24C2961FC9;\n\tWed, 21 Jan 2026 17:01:19 +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 E94EA61F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 17:01:16 +0100 (CET)","from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:d17c:7c69:53da:19e5])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id C7FAF741;\n\tWed, 21 Jan 2026 17:00:44 +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=\"oLdQeeUo\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769011244;\n\tbh=9JFGIRsE8JD5VS564Zw2/ZQ3D4ozGd6smdjco2934Yg=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=oLdQeeUoLxSMxCXmXJiScb8duI19yM9k6pdCLgsU3A7zhH+pwJHOF9D4+PwSYAXGz\n\tak7VdRL9VETMZhedxB9vAD2g4jA9hVnVL/J+uoZ930j+YWAJQC1AtwRyNyAV+GX4Sh\n\tUiIGjvXCmLaqt3hffHIyO9ZfWCoVwRrH/bGNMJMw=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20260120153057.1703714-3-rui.wang@ideasonboard.com>","References":"<20260120153057.1703714-1-rui.wang@ideasonboard.com>\n\t<20260120153057.1703714-3-rui.wang@ideasonboard.com>","Subject":"Re: [PATCH v10 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","From":"Stefan Klug <stefan.klug@ideasonboard.com>","Cc":"Rui Wang <rui.wang@ideasonboard.com>","To":"Rui Wang <rui.wang@ideasonboard.com>, libcamera-devel@lists.libcamera.org","Date":"Wed, 21 Jan 2026 17:01:13 +0100","Message-ID":"<176901127352.23550.5669981077089400878@localhost>","User-Agent":"alot/0.12.dev8+g2c003385c862.d20250602","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>"}},{"id":37883,"web_url":"https://patchwork.libcamera.org/comment/37883/","msgid":"<176909742253.2020199.15885697052828733684@rui-Precision-7560.local>","date":"2026-01-22T15:57:02","subject":"Re: [PATCH v10 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","submitter":{"id":241,"url":"https://patchwork.libcamera.org/api/people/241/","name":"Rui Wang","email":"rui.wang@ideasonboard.com"},"content":"Quoting Stefan Klug (2026-01-21 11:01:13)\n> Hi Rui,\n> \n> Thank you for the patch.\n> \n> Quoting Rui Wang (2026-01-20 16:30:52)\n> > Implement support for switching between different noise reduction modes.\n> > This allows the DPF algorithm to be configured with different parameters\n> > based on the requested noise reduction level (e.g., minimal, fast, high\n> > quality).\n> > \n> > Mode configurations are stored in the tuning data as a list of modes,\n> > with each mode specifying its 'type' and corresponding DPF parameters.\n> > An optional 'ActiveMode' setting allows defining the default mode at\n> > startup, defaulting to \"ReductionOff\" if not specified.\n> > \n> > The Dpf class is refactored to store configurations in a vector and\n> > track the current mode using an iterator, which avoids data copying\n> > during runtime.\n> > \n> > Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>\n> > \n> > ---\n> > changelog 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).\n> > changelog since v6:\n> >  - add { controls::draft::NoiseReductionModeOff, \"off\" }, to fix\n> >    out_of_range issue\n> > \n> > changelog since v7:\n> >  - Delete base config parse from parseConfig\n> > \n> > changelog 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> > \n> > changelog 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> > ---\n> >  src/ipa/rkisp1/algorithms/dpf.cpp | 117 +++++++++++++++++++++++++++---\n> >  src/ipa/rkisp1/algorithms/dpf.h   |  12 ++-\n> >  2 files changed, 116 insertions(+), 13 deletions(-)\n> > \n> > diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\n> > index dd3effa1..659a1a82 100644\n> > --- a/src/ipa/rkisp1/algorithms/dpf.cpp\n> > +++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n> > @@ -8,6 +8,7 @@\n> >  #include \"dpf.h\"\n> >  \n> >  #include <algorithm>\n> > +#include <map>\n> >  #include <string>\n> >  #include <vector>\n> >  \n> > @@ -36,8 +37,32 @@ namespace ipa::rkisp1::algorithms {\n> >  \n> >  LOG_DEFINE_CATEGORY(RkISP1Dpf)\n> >  \n> > +namespace {\n> > +\n> > +const std::map<std::string, int32_t> kModesMap = {\n> > +       { \"ReductionMinimal\", controls::draft::NoiseReductionModeMinimal },\n> > +       { \"ReductionFast\", controls::draft::NoiseReductionModeFast },\n> > +       { \"ReductionHighQuality\", controls::draft::NoiseReductionModeHighQuality },\n> > +       { \"ReductionZSL\", controls::draft::NoiseReductionModeZSL },\n> > +       { \"ReductionOff\", controls::draft::NoiseReductionModeOff },\n> > +};\n> \n> The need to have this translation map doesn't seem right. If you look at\n> the AEGC implementation the lookup is done through\n> AeConstraintModeNameValueMap. The names I proposed don't match the\n> naming scheme of the enum. So I see two options here: \n> \n> 1. Renaming the enum entries\n> \n> I think this would be the right thing to do, but it will be difficult\n> to upstream because the Rpi IPA already uses the old names. And the\n> naming on the control enums seems not to be fully consistent anyways.\n> \n> 2. Change the names in the tuning file to be in sync with the enum\n> entries\n> \n> This is the easier option and as the tuning file format will change\n> anyway it won't hurt anybody. Then you could drop this extra translation\n> map and rely on the enum names.\n> \n> \n> Maybe I could have made it more clear that my naming was a idea but not\n> fully checked - sorry for that.\n> \n> Best regards,\n> Stefan\n>\nThanks Stefan ,\n\nI was not aware of controls::draft::NoiseReductionModeNameValueMap already defined\nit is generated folder . I will adopt it like  AeConstraintModeNameValueMap\nit is as same as kModeMap,  and make code more clean.\nwill submit v10 to do this\n\nRui\n> > +\n> > +std::string modeName(int32_t mode)\n> > +{\n> > +       auto it = std::find_if(kModesMap.begin(), kModesMap.end(),\n> > +                              [mode](const auto &pair) {\n> > +                                      return pair.second == mode;\n> > +                              });\n> > +\n> > +       if (it != kModesMap.end())\n> > +               return it->first;\n> > +\n> > +       return \"ReductionUnknown\";\n> > +}\n> > +} /* namespace */\n> > +\n> >  Dpf::Dpf()\n> > -       : config_({}), strengthConfig_({})\n> > +       : noiseReductionModes_({}), activeMode_(noiseReductionModes_.end())\n> >  {\n> >  }\n> >  \n> > @@ -57,10 +82,56 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n> >  \n> >  int Dpf::parseConfig(const YamlObject &tuningData)\n> >  {\n> > -       /* Parse base config. */\n> > -       int ret = parseSingleConfig(tuningData, config_, strengthConfig_);\n> > -       if (ret)\n> > -               return ret;\n> > +       /* Parse noise reduction modes. */\n> > +       if (!tuningData.contains(\"NoiseReductionModes\")) {\n> > +               LOG(RkISP1Dpf, Error) << \"Missing modes in DPF tuning data\";\n> > +               return -EINVAL;\n> > +       }\n> > +\n> > +       const YamlObject &modesObject = tuningData[\"NoiseReductionModes\"];\n> > +       if (!modesObject.isDictionary()) {\n> > +               LOG(RkISP1Dpf, Error) << \"NoiseReductionModes must be a dictionary\";\n> > +               return -EINVAL;\n> > +       }\n> > +\n> > +       noiseReductionModes_.clear();\n> > +       for (const auto &[modeName, modeData] : modesObject.asDict()) {\n> > +               auto it = kModesMap.find(modeName);\n> > +               if (it == kModesMap.end()) {\n> > +                       LOG(RkISP1Dpf, Error) << \"Unknown mode type: \" << modeName;\n> > +                       return -EINVAL;\n> > +               }\n> > +\n> > +               ModeConfig mode;\n> > +               mode.modeValue = it->second;\n> > +               int ret = parseSingleConfig(modeData, mode.dpf, mode.strength);\n> > +               if (ret) {\n> > +                       LOG(RkISP1Dpf, Error) << \"Failed to parse mode: \" << modeName;\n> > +                       return ret;\n> > +               }\n> > +\n> > +               noiseReductionModes_.push_back(mode);\n> > +       }\n> > +\n> > +       /*\n> > +        * Parse the optional ActiveMode.\n> > +        * If not present, default to \"ReductionOff\".\n> > +        */\n> > +       std::string activeMode = tuningData[\"ActiveMode\"].get<std::string>().value_or(\"ReductionOff\");\n> > +       auto it = kModesMap.find(activeMode);\n> > +       if (it == kModesMap.end()) {\n> > +               LOG(RkISP1Dpf, Warning) << \"Invalid ActiveMode: \" << activeMode;\n> > +               activeMode_ = noiseReductionModes_.end();\n> > +               return 0;\n> > +       }\n> > +\n> > +       if (!loadConfig(it->second)) {\n> > +               /* If the default \"ReductionOff\" mode is requested but not configured, disable DPF. */\n> > +               if (it->second == controls::draft::NoiseReductionModeOff)\n> > +                       activeMode_ = noiseReductionModes_.end();\n> > +               else\n> > +                       return -EINVAL;\n> > +       }\n> >  \n> >         return 0;\n> >  }\n> > @@ -193,6 +264,27 @@ int Dpf::parseSingleConfig(const YamlObject &tuningData,\n> >         return 0;\n> >  }\n> >  \n> > +bool Dpf::loadConfig(int32_t mode)\n> > +{\n> > +       auto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(),\n> > +                              [mode](const ModeConfig &m) {\n> > +                                      return m.modeValue == mode;\n> > +                              });\n> > +       if (it == noiseReductionModes_.end()) {\n> > +               LOG(RkISP1Dpf, Warning)\n> > +                       << \"No DPF config for reduction mode: \" << modeName(mode);\n> > +               return false;\n> > +       }\n> > +\n> > +       activeMode_ = it;\n> > +\n> > +       LOG(RkISP1Dpf, Debug)\n> > +               << \"DPF mode=Reduction (config loaded)\"\n> > +               << \" mode= \" << modeName(mode);\n> > +\n> > +       return true;\n> > +}\n> > +\n> >  /**\n> >   * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> >   */\n> > @@ -206,8 +298,6 @@ void Dpf::queueRequest(IPAContext &context,\n> >  \n> >         const auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n> >         if (denoise) {\n> > -               LOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n> > -\n> >                 switch (*denoise) {\n> >                 case controls::draft::NoiseReductionModeOff:\n> >                         if (dpf.denoise) {\n> > @@ -218,9 +308,10 @@ void Dpf::queueRequest(IPAContext &context,\n> >                 case controls::draft::NoiseReductionModeMinimal:\n> >                 case controls::draft::NoiseReductionModeHighQuality:\n> >                 case controls::draft::NoiseReductionModeFast:\n> > -                       if (!dpf.denoise) {\n> > -                               dpf.denoise = true;\n> > +               case controls::draft::NoiseReductionModeZSL:\n> > +                       if (loadConfig(*denoise)) {\n> >                                 update = true;\n> > +                               dpf.denoise = true;\n> >                         }\n> >                         break;\n> >                 default:\n> > @@ -229,6 +320,8 @@ void Dpf::queueRequest(IPAContext &context,\n> >                                 << *denoise;\n> >                         break;\n> >                 }\n> > +               if (update)\n> > +                       LOG(RkISP1Dpf, Debug) << \"Set denoise to \" << modeName(*denoise);\n> >         }\n> >  \n> >         frameContext.dpf.denoise = dpf.denoise;\n> > @@ -251,8 +344,10 @@ void Dpf::prepare(IPAContext &context, const uint32_t frame,\n> >         strengthConfig.setEnabled(frameContext.dpf.denoise);\n> >  \n> >         if (frameContext.dpf.denoise) {\n> > -               *config = config_;\n> > -               *strengthConfig = strengthConfig_;\n> > +               const ModeConfig &modeConfig = *activeMode_;\n> > +\n> > +               *config = modeConfig.dpf;\n> > +               *strengthConfig = modeConfig.strength;\n> >  \n> >                 const auto &awb = context.configuration.awb;\n> >                 const auto &lsc = context.configuration.lsc;\n> > diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\n> > index 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> >                      RkISP1Params *params) override;\n> >  \n> >  private:\n> > +       struct ModeConfig {\n> > +               int32_t modeValue;\n> > +               rkisp1_cif_isp_dpf_config dpf;\n> > +               rkisp1_cif_isp_dpf_strength_config strength;\n> > +       };\n> > +\n> >         int parseConfig(const YamlObject &tuningData);\n> >         int parseSingleConfig(const YamlObject &tuningData,\n> >                               rkisp1_cif_isp_dpf_config &config,\n> >                               rkisp1_cif_isp_dpf_strength_config &strengthConfig);\n> >  \n> > -       struct rkisp1_cif_isp_dpf_config config_;\n> > -       struct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n> > +       bool loadConfig(int32_t mode);\n> > +\n> > +       std::vector<ModeConfig> noiseReductionModes_;\n> > +       std::vector<ModeConfig>::const_iterator activeMode_;\n> >  };\n> >  \n> >  } /* namespace ipa::rkisp1::algorithms */\n> > -- \n> > 2.43.0\n> >","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 E6EDDC3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 22 Jan 2026 15:57:18 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 37A3161FC6;\n\tThu, 22 Jan 2026 16:57:18 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9AB2361FBB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 22 Jan 2026 16:57:16 +0100 (CET)","from pyrite.rasen.tech (unknown [209.216.103.65])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9E425460;\n\tThu, 22 Jan 2026 16:56:43 +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=\"wdsxITVa\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769097403;\n\tbh=j+w3Wc0xIc+xhHlpgyCJabOKX0MRvdFrX+FDhnLSrzg=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=wdsxITVaCnl9fLHZLG9+Qw9VffGWWqxn22BFmRhQX8hvcoeL79c5b8Nm7YnGisX5D\n\tLnoHe6TRPfqrodGVa2G2wHhgSFlA36FYLDC02WZfJDh2ViNXrNvutow7WdAEFMABeX\n\tS660eMK6Ft5GpU6OL2YFAO0dRI18zc4VXpkOb1LA=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<176901127352.23550.5669981077089400878@localhost>","References":"<20260120153057.1703714-1-rui.wang@ideasonboard.com>\n\t<20260120153057.1703714-3-rui.wang@ideasonboard.com>\n\t<176901127352.23550.5669981077089400878@localhost>","Subject":"Re: [PATCH v10 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","From":"Rui Wang <rui.wang@ideasonboard.com>","Cc":"","To":"Stefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Thu, 22 Jan 2026 10:57:02 -0500","Message-ID":"<176909742253.2020199.15885697052828733684@rui-Precision-7560.local>","User-Agent":"alot/0.12","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>"}}]