{"id":25169,"url":"https://patchwork.libcamera.org/api/patches/25169/?format=json","web_url":"https://patchwork.libcamera.org/patch/25169/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","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-3-rui.wang@ideasonboard.com>","date":"2025-11-25T00:08:39","name":"[v1,02/11] ipa: rkisp1: algorithms: dpf: init Dpf tuning config","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"a4f8361de074cb30f7b8485a49a692cd30a93f86","submitter":{"id":241,"url":"https://patchwork.libcamera.org/api/people/241/?format=json","name":"Rui Wang","email":"rui.wang@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/25169/mbox/","series":[{"id":5612,"url":"https://patchwork.libcamera.org/api/series/5612/?format=json","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/25169/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/25169/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 01580C3257\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 25 Nov 2025 00:09:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 99B5A60A80;\n\tTue, 25 Nov 2025 01:09:06 +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 38D2D608CF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 25 Nov 2025 01:09:05 +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 3482D1648;\n\tTue, 25 Nov 2025 01:06: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=\"dsPn0jdT\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1764029216;\n\tbh=IMB0LPoQqYANqR/0AvPU4uc9w6SsnqDnZqhk1APmWQk=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=dsPn0jdTT3Q3FVwWQXYJArNtQkwpI4ZxiBE9KdUyOTbTh/yq3tGVRf0SVmDQIXgVE\n\tjLWtzj33SIA1MPmDaFVNIBrm1lGqxqAXnwTtJUueaZ2B0AnDC55lmUa9LMwxjfK8az\n\tbSFab+k55gj7yFi1Gf0ecqtga88XjmtEdzShfrZ0=","From":"Rui Wang <rui.wang@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Cc":"Rui Wang <rui.wang@ideasonboard.com>","Subject":"[PATCH v1 02/11] ipa: rkisp1: algorithms: dpf: init Dpf tuning\n\tconfig","Date":"Mon, 24 Nov 2025 19:08:39 -0500","Message-ID":"<20251125000848.4103786-3-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":"Load tuning flags and gain levels on top of the single-config helper.\nThe parseConfig() function wraps parseSingleConfig() to load the base\nconfiguration, then parses optional enable/devmode flags and any\nexposure index -banded overrides.\n\nReplace the inline parsing in init() with a call to parseConfig(). This\nsimplifies init() and allows the parsing logic to be reused. The refactor\nalso adds logging of the parsed base tuning and preserves the base config\nfor manual mode restoration.\n\nRework domain filter, NLL, gain, and strength parsing into a\nparseSingleConfig() helper. This extracts the parsing logic so it can be\nreused for both the base tuning and per-exposure-gain-level configuration blocks.\n\nThe init method now:\n- Calls parseConfig() to load tuning data\n- Logs the parsed base configuration\n- Caches base config for manual mode restore\n- exposure levels are sorted by exposure index threshold for efficient band selection\nat runtime.\n\nSigned-off-by: Rui Wang <rui.wang@ideasonboard.com>\n---\n src/ipa/rkisp1/algorithms/denoise.h |  11 +-\n src/ipa/rkisp1/algorithms/dpf.cpp   | 186 ++++++++++++++++++++++++----\n src/ipa/rkisp1/algorithms/dpf.h     |  24 +++-\n 3 files changed, 195 insertions(+), 26 deletions(-)","diff":"diff --git a/src/ipa/rkisp1/algorithms/denoise.h b/src/ipa/rkisp1/algorithms/denoise.h\nindex 8907dc4e..abd08cba 100644\n--- a/src/ipa/rkisp1/algorithms/denoise.h\n+++ b/src/ipa/rkisp1/algorithms/denoise.h\n@@ -20,12 +20,21 @@ class DenoiseBaseAlgorithm : public ipa::rkisp1::Algorithm\n protected:\n \tDenoiseBaseAlgorithm() = default;\n \t~DenoiseBaseAlgorithm() = default;\n-\n+\tvirtual void setDevMode(bool dev) { devMode_ = dev; }\n+\tvirtual bool isDevMode() const { return devMode_; }\n \tvirtual uint32_t computeExposureIndex(const IPAContext &context,\n \t\t\t\t\t      const IPAFrameContext &frameContext) const;\n \ttemplate<typename LevelContainer>\n \tuint32_t selectExposureIndexBand(unsigned exposureIndex,\n \t\t\t\t\t const LevelContainer &levels) const;\n+\tvirtual bool parseConfig([[maybe_unused]] const YamlObject &tuningData)\n+\t{\n+\t\treturn true;\n+\t}\n+\n+private:\n+\t/**< Developer mode state for advanced controls */\n+\tbool devMode_ = false;\n };\n \n inline unsigned DenoiseBaseAlgorithm::computeExposureIndex(const IPAContext &context,\ndiff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\nindex 39f3e461..dc0a361c 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 <array>\n #include <string>\n #include <vector>\n \n@@ -37,7 +38,7 @@ namespace ipa::rkisp1::algorithms {\n LOG_DEFINE_CATEGORY(RkISP1Dpf)\n \n Dpf::Dpf()\n-\t: config_({}), strengthConfig_({})\n+\t: config_({}), strengthConfig_({}), baseConfig_({}), baseStrengthConfig_({})\n {\n }\n \n@@ -47,14 +48,130 @@ Dpf::Dpf()\n int Dpf::init([[maybe_unused]] IPAContext &context,\n \t      const YamlObject &tuningData)\n {\n-\tstd::vector<uint8_t> values;\n+\t/* Parse tuning block */\n+\tif (!parseConfig(tuningData))\n+\t\treturn -EINVAL;\n+\n+\t/* Log parsed base tuning (counts are always full-sized for base). */\n+\tLOG(RkISP1Dpf, Info)\n+\t\t<< \"DPF init: base tuning parsed, G coeffs=\"\n+\t\t<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n+\t\t<< \", RB fltsize=\"\n+\t\t<< (config_.rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9 ? \"13x9\" : \"9x9\")\n+\t\t<< \", NLL coeffs=\" << RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS\n+\t\t<< \", NLL scale=\"\n+\t\t<< (config_.nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC ? \"log\" : \"linear\")\n+\t\t<< \", Strength (r,g,b)=\"\n+\t\t<< (int)strengthConfig_.r << \",\" << (int)strengthConfig_.g\n+\t\t<< \",\" << (int)strengthConfig_.b;\n+\n+\t/* Preserve base (non-exposure index) YAML configuration for restoration after manual mode. */\n+\tbaseConfig_ = config_;\n+\tbaseStrengthConfig_ = strengthConfig_;\n+\n+\t/* Optional exposure index-banded tuning */\n+\tif (useExposureIndexLevels_) {\n+\t\tLOG(RkISP1Dpf, Info)\n+\t\t\t<< \"DPF init: loaded \" << exposureIndexLevels_.size()\n+\t\t\t<< \" exposureIndex level(s) from tuning\";\n+\t}\n+\n+\t/* Optional mode tuning */\n+\tif (!modes_.empty()) {\n+\t\tLOG(RkISP1Dpf, Info)\n+\t\t\t<< \"DPF init: loaded \" << modes_.size()\n+\t\t\t<< \" mode(s) from tuning\";\n+\t}\n+\n+\treturn 0;\n+}\n+\n+bool Dpf::parseConfig(const YamlObject &tuningData)\n+{\n+\t/* Parse base config */\n+\tif (!parseSingleConfig(tuningData, config_, strengthConfig_))\n+\t\treturn false;\n+\n+\tbaseConfig_ = config_;\n+\tbaseStrengthConfig_ = strengthConfig_;\n+\n+\t/* Optional developer mode flag (default true). If false, only basic manual controls available. */\n+\tbool devMode = tuningData[\"devmode\"].get<bool>().value_or(true);\n+\tsetDevMode(devMode);\n+\n+\t/* Parse exposure index levels */\n+\tif (tuningData.contains(\"ExposureIndexLevels\")) {\n+\t\tuseExposureIndexLevels_ = true;\n+\t\texposureIndexLevels_.clear();\n+\t\tfor (const auto &entry : tuningData[\"ExposureIndexLevels\"].asList()) {\n+\t\t\tstd::optional<uint32_t> maxExposureIndexOpt =\n+\t\t\t\tentry[\"maxExposureIndex\"].get<uint32_t>();\n+\t\t\tif (!maxExposureIndexOpt) {\n+\t\t\t\tLOG(RkISP1Dpf, Error) << \"ExposureIndexLevels entry missing maxExposureIndex\";\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tExposureIndexLevelConfig lvl{};\n+\t\t\tlvl.maxExposureIndex = *maxExposureIndexOpt;\n+\t\t\tif (!parseSingleConfig(entry, lvl.dpf, lvl.strength))\n+\t\t\t\tcontinue;\n+\t\t\texposureIndexLevels_.push_back(lvl);\n+\t\t}\n+\t\tstd::sort(exposureIndexLevels_.begin(), exposureIndexLevels_.end(),\n+\t\t\t  [](const ExposureIndexLevelConfig &a, const ExposureIndexLevelConfig &b) {\n+\t\t\t\t  return a.maxExposureIndex < b.maxExposureIndex;\n+\t\t\t  });\n+\t}\n+\n+\t/* Parse modes */\n+\tif (tuningData.contains(\"NoiseReductionMode\")) {\n+\t\tmodes_.clear();\n+\t\tfor (const auto &entry : tuningData[\"NoiseReductionMode\"].asList()) {\n+\t\t\tstd::optional<std::string> typeOpt =\n+\t\t\t\tentry[\"type\"].get<std::string>();\n+\t\t\tif (!typeOpt) {\n+\t\t\t\tLOG(RkISP1Dpf, Error) << \"Modes entry missing type\";\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tint32_t modeValue;\n+\t\t\tif (*typeOpt == \"minimal\") {\n+\t\t\t\tmodeValue = controls::draft::NoiseReductionModeMinimal;\n+\t\t\t} else if (*typeOpt == \"highquality\") {\n+\t\t\t\tmodeValue = controls::draft::NoiseReductionModeHighQuality;\n+\t\t\t} else if (*typeOpt == \"fast\") {\n+\t\t\t\tmodeValue = controls::draft::NoiseReductionModeFast;\n+\t\t\t} else if (*typeOpt == \"zsl\") {\n+\t\t\t\tmodeValue = controls::draft::NoiseReductionModeZSL;\n+\t\t\t} else {\n+\t\t\t\tLOG(RkISP1Dpf, Error) << \"Unknown mode type: \" << *typeOpt;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \n+\t\t\tModeConfig mode{};\n+\t\t\tmode.modeValue = modeValue;\n+\t\t\tif (!parseSingleConfig(entry, mode.dpf, mode.strength))\n+\t\t\t\tcontinue;\n+\t\t\tmodes_.push_back(mode);\n+\t\t}\n+\t}\n+\n+\treturn true;\n+}\n+\n+bool Dpf::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+\tstd::vector<uint8_t> values;\n \t/*\n \t * The domain kernel is configured with a 9x9 kernel for the green\n \t * pixels, and a 13x9 or 9x9 kernel for red and blue pixels.\n \t */\n+\tif (!tuningData.contains(\"DomainFilter\")) {\n+\t\tLOG(RkISP1Dpf, Error) << \"DomainFilter section missing\";\n+\t\treturn false;\n+\t}\n \tconst YamlObject &dFObject = tuningData[\"DomainFilter\"];\n-\n \t/*\n \t * For the green component, we have the 9x9 kernel specified\n \t * as 6 coefficients:\n@@ -78,14 +195,14 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n \t\t\t<< \"Invalid 'DomainFilter:g': expected \"\n \t\t\t<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n \t\t\t<< \" elements, got \" << values.size();\n-\t\treturn -EINVAL;\n+\t\treturn false;\n \t}\n \n \tstd::copy_n(values.begin(), values.size(),\n-\t\t    std::begin(config_.g_flt.spatial_coeff));\n+\t\t    std::begin(config.g_flt.spatial_coeff));\n \n-\tconfig_.g_flt.gr_enable = true;\n-\tconfig_.g_flt.gb_enable = true;\n+\tconfig.g_flt.gr_enable = true;\n+\tconfig.g_flt.gb_enable = true;\n \n \t/*\n \t * For the red and blue components, we have the 13x9 kernel specified\n@@ -116,24 +233,28 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n \t\t\t<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1\n \t\t\t<< \" or \" << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n \t\t\t<< \" elements, got \" << values.size();\n-\t\treturn -EINVAL;\n+\t\treturn false;\n \t}\n \n-\tconfig_.rb_flt.fltsize = values.size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n-\t\t\t       ? RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9\n-\t\t\t       : RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9;\n+\tconfig.rb_flt.fltsize = values.size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n+\t\t\t\t\t? RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9\n+\t\t\t\t\t: RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9;\n \n \tstd::copy_n(values.begin(), values.size(),\n-\t\t    std::begin(config_.rb_flt.spatial_coeff));\n+\t\t    std::begin(config.rb_flt.spatial_coeff));\n \n-\tconfig_.rb_flt.r_enable = true;\n-\tconfig_.rb_flt.b_enable = true;\n+\tconfig.rb_flt.r_enable = true;\n+\tconfig.rb_flt.b_enable = true;\n \n \t/*\n \t * The range kernel is configured with a noise level lookup table (NLL)\n \t * which stores a piecewise linear function that characterizes the\n \t * sensor noise profile as a noise level function curve (NLF).\n \t */\n+\tif (!tuningData.contains(\"NoiseLevelFunction\")) {\n+\t\tLOG(RkISP1Dpf, Error) << \"NoiseLevelFunction section missing\";\n+\t\treturn false;\n+\t}\n \tconst YamlObject &rFObject = tuningData[\"NoiseLevelFunction\"];\n \n \tstd::vector<uint16_t> nllValues;\n@@ -143,32 +264,49 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n \t\t\t<< \"Invalid 'RangeFilter:coeff': expected \"\n \t\t\t<< RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS\n \t\t\t<< \" elements, got \" << nllValues.size();\n-\t\treturn -EINVAL;\n+\t\treturn false;\n \t}\n \n \tstd::copy_n(nllValues.begin(), nllValues.size(),\n-\t\t    std::begin(config_.nll.coeff));\n+\t\t    std::begin(config.nll.coeff));\n \n \tstd::string scaleMode = rFObject[\"scale-mode\"].get<std::string>(\"\");\n \tif (scaleMode == \"linear\") {\n-\t\tconfig_.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LINEAR;\n+\t\tconfig.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LINEAR;\n \t} else if (scaleMode == \"logarithmic\") {\n-\t\tconfig_.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC;\n+\t\tconfig.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC;\n \t} else {\n \t\tLOG(RkISP1Dpf, Error)\n \t\t\t<< \"Invalid 'RangeFilter:scale-mode': expected \"\n \t\t\t<< \"'linear' or 'logarithmic' value, got \"\n \t\t\t<< scaleMode;\n-\t\treturn -EINVAL;\n+\t\treturn false;\n \t}\n \n+\tif (!tuningData.contains(\"Gain\")) {\n+\t\tLOG(RkISP1Dpf, Error) << \"Gain section missing\";\n+\t\treturn false;\n+\t}\n+\tconst YamlObject &gObject = tuningData[\"Gain\"];\n+\n+\tconfig.gain.mode =\n+\t\tgObject[\"gain_mode\"].get<uint32_t>().value_or(\n+\t\t\tRKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS);\n+\tconfig.gain.nf_r_gain = gObject[\"nf_r_gain\"].get<uint16_t>().value_or(256);\n+\tconfig.gain.nf_b_gain = gObject[\"nf_b_gain\"].get<uint16_t>().value_or(256);\n+\tconfig.gain.nf_gr_gain = gObject[\"nf_gr_gain\"].get<uint16_t>().value_or(256);\n+\tconfig.gain.nf_gb_gain = gObject[\"nf_gb_gain\"].get<uint16_t>().value_or(256);\n+\n+\tif (!tuningData.contains(\"FilterStrength\")) {\n+\t\tLOG(RkISP1Dpf, Error) << \"FilterStrength section missing\";\n+\t\treturn false;\n+\t}\n \tconst YamlObject &fSObject = tuningData[\"FilterStrength\"];\n \n-\tstrengthConfig_.r = fSObject[\"r\"].get<uint16_t>(64);\n-\tstrengthConfig_.g = fSObject[\"g\"].get<uint16_t>(64);\n-\tstrengthConfig_.b = fSObject[\"b\"].get<uint16_t>(64);\n-\n-\treturn 0;\n+\tstrengthConfig.r = fSObject[\"r\"].get<uint8_t>().value_or(64);\n+\tstrengthConfig.g = fSObject[\"g\"].get<uint8_t>().value_or(64);\n+\tstrengthConfig.b = fSObject[\"b\"].get<uint8_t>().value_or(64);\n+\treturn true;\n }\n \n /**\ndiff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\nindex 2dd8cd36..8691932d 100644\n--- a/src/ipa/rkisp1/algorithms/dpf.h\n+++ b/src/ipa/rkisp1/algorithms/dpf.h\n@@ -10,12 +10,13 @@\n #include <sys/types.h>\n \n #include \"algorithm.h\"\n+#include \"denoise.h\"\n \n namespace libcamera {\n \n namespace ipa::rkisp1::algorithms {\n \n-class Dpf : public Algorithm\n+class Dpf : public DenoiseBaseAlgorithm\n {\n public:\n \tDpf();\n@@ -32,6 +33,27 @@ public:\n private:\n \tstruct rkisp1_cif_isp_dpf_config config_;\n \tstruct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n+\tstruct rkisp1_cif_isp_dpf_config baseConfig_;\n+\tstruct rkisp1_cif_isp_dpf_strength_config baseStrengthConfig_;\n+\tstruct ExposureIndexLevelConfig {\n+\t\tuint32_t maxExposureIndex; /* inclusive upper bound */\n+\t\tstruct rkisp1_cif_isp_dpf_config dpf;\n+\t\tstruct rkisp1_cif_isp_dpf_strength_config strength;\n+\t};\n+\tstruct ModeConfig {\n+\t\tint32_t modeValue;\n+\t\tstruct rkisp1_cif_isp_dpf_config dpf;\n+\t\tstruct rkisp1_cif_isp_dpf_strength_config strength;\n+\t};\n+\n+\tstd::vector<ExposureIndexLevelConfig> exposureIndexLevels_;\n+\tstd::vector<ModeConfig> modes_;\n+\tbool useExposureIndexLevels_ = false;\n+\n+\tbool parseConfig(const YamlObject &tuningData) override;\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 \n } /* namespace ipa::rkisp1::algorithms */\n","prefixes":["v1","02/11"]}