[v4,5/7] ipa: rkisp1: algorithms: dpf: Use YamlObject::Getter for parsing
diff mbox series

Message ID 20251208004808.1274417-6-rui.wang@ideasonboard.com
State New
Headers show
Series
  • rebase_dpf_refactory_patch_v4
Related show

Commit Message

Rui Wang Dec. 8, 2025, 12:48 a.m. UTC
Refactor DPF configuration parsing to use YamlObject::Getter
specializations, similar to the approach used in pwl.cpp. This
simplifies parseSingleConfig() by delegating the parsing logic
to dedicated getter specializations.

Implement two YamlObject::Getter specializations:
- rkisp1_cif_isp_dpf_config: Parses filter and nll parameters
- rkisp1_cif_isp_dpf_strength_config: Parses strength parameters

The specializations are defined at the top of the file in the
libcamera namespace.

Remove LOG statements from the getter specializations to avoid
namespace visibility issues, as the LOG macro requires access
to the log category which is defined in a nested namespace.

Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>
---
 src/ipa/rkisp1/algorithms/dpf.cpp | 240 ++++++++++++++++--------------
 1 file changed, 125 insertions(+), 115 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index dea04cc3..68a94afe 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -23,107 +23,31 @@ 
 
 namespace libcamera {
 
-namespace ipa::rkisp1::algorithms {
-
-/**
- * \class Dpf
- * \brief RkISP1 Denoise Pre-Filter control
- *
- * The denoise pre-filter algorithm is a bilateral filter which combines a
- * range filter and a domain filter. The denoise pre-filter is applied before
- * demosaicing.
- */
-
-LOG_DEFINE_CATEGORY(RkISP1Dpf)
-
-Dpf::Dpf()
-	: config_({}), strengthConfig_({}),
-	  noiseReductionModes_({}),
-	  runningMode_(controls::draft::NoiseReductionModeOff)
-{
-}
-
-/**
- * \copydoc libcamera::ipa::Algorithm::init
- */
-int Dpf::init([[maybe_unused]] IPAContext &context,
-	      const YamlObject &tuningData)
-{
-	/* Parse tuning block. */
-	if (!parseConfig(tuningData)) {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-bool Dpf::parseConfig(const YamlObject &tuningData)
+template<>
+std::optional<rkisp1_cif_isp_dpf_strength_config>
+YamlObject::Getter<rkisp1_cif_isp_dpf_strength_config>::get(const YamlObject &obj) const
 {
-	/* Parse base config. */
-	if (!parseSingleConfig(tuningData, config_, strengthConfig_)) {
-		return false;
-	}
+	rkisp1_cif_isp_dpf_strength_config config = {};
 
-	/* Parse modes. */
-	if (!parseModes(tuningData)) {
-		return false;
-	}
+	config.r = obj["r"].get<uint8_t>().value_or(64);
+	config.g = obj["g"].get<uint8_t>().value_or(64);
+	config.b = obj["b"].get<uint8_t>().value_or(64);
 
-	return true;
+	return config;
 }
 
-bool Dpf::parseModes(const YamlObject &tuningData)
-{
-	/* Parse noise reduction modes. */
-	if (!tuningData.contains("modes")) {
-		return true;
-	}
-
-	noiseReductionModes_.clear();
-	for (const auto &entry : tuningData["modes"].asList()) {
-		std::optional<std::string> typeOpt =
-			entry["type"].get<std::string>();
-		if (!typeOpt) {
-			LOG(RkISP1Dpf, Error) << "Modes entry missing type";
-			return false;
-		}
-
-		int32_t modeValue = controls::draft::NoiseReductionModeOff;
-		if (*typeOpt == "minimal") {
-			modeValue = controls::draft::NoiseReductionModeMinimal;
-		} else if (*typeOpt == "fast") {
-			modeValue = controls::draft::NoiseReductionModeFast;
-		} else if (*typeOpt == "highquality") {
-			modeValue = controls::draft::NoiseReductionModeHighQuality;
-		} else if (*typeOpt == "zsl") {
-			modeValue = controls::draft::NoiseReductionModeZSL;
-		} else {
-			LOG(RkISP1Dpf, Error) << "Unknown mode type: " << *typeOpt;
-			return false;
-		}
-
-		ModeConfig mode{};
-		mode.modeValue = modeValue;
-		if (!parseSingleConfig(entry, mode.dpf, mode.strength)) {
-			return false;
-		}
-		noiseReductionModes_.push_back(mode);
-	}
-
-	return true;
-}
-
-bool Dpf::parseSingleConfig(const YamlObject &tuningData,
-			    rkisp1_cif_isp_dpf_config &config,
-			    rkisp1_cif_isp_dpf_strength_config &strengthConfig)
+template<>
+std::optional<rkisp1_cif_isp_dpf_config>
+YamlObject::Getter<rkisp1_cif_isp_dpf_config>::get(const YamlObject &obj) const
 {
+	rkisp1_cif_isp_dpf_config config = {};
 	std::vector<uint8_t> 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["filter"];
+	const YamlObject &dFObject = obj["filter"];
 
 	/*
 	 * For the green component, we have the 9x9 kernel specified
@@ -144,11 +68,7 @@  bool Dpf::parseSingleConfig(const YamlObject &tuningData,
 	 */
 	values = dFObject["g"].getList<uint8_t>().value_or(std::vector<uint8_t>{});
 	if (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) {
-		LOG(RkISP1Dpf, Error)
-			<< "Invalid 'filter:g': expected "
-			<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS
-			<< " elements, got " << values.size();
-		return false;
+		return std::nullopt;
 	}
 
 	std::copy_n(values.begin(), values.size(),
@@ -181,12 +101,7 @@  bool Dpf::parseSingleConfig(const YamlObject &tuningData,
 	values = dFObject["rb"].getList<uint8_t>().value_or(std::vector<uint8_t>{});
 	if (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS &&
 	    values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1) {
-		LOG(RkISP1Dpf, Error)
-			<< "Invalid 'filter:rb': expected "
-			<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1
-			<< " or " << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS
-			<< " elements, got " << values.size();
-		return false;
+		return std::nullopt;
 	}
 
 	config.rb_flt.fltsize = values.size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS
@@ -204,39 +119,134 @@  bool Dpf::parseSingleConfig(const YamlObject &tuningData,
 	 * which stores a piecewise linear function that characterizes the
 	 * sensor noise profile as a noise level function curve (NLF).
 	 */
-	const YamlObject &rFObject = tuningData["nll"];
+	const YamlObject &rFObject = obj["nll"];
 
 	std::vector<uint16_t> nllValues;
 	nllValues = rFObject["coeff"].getList<uint16_t>().value_or(std::vector<uint16_t>{});
 	if (nllValues.size() != RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS) {
-		LOG(RkISP1Dpf, Error)
-			<< "Invalid 'nll:coeff': expected "
-			<< RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS
-			<< " elements, got " << nllValues.size();
-		return false;
+		return std::nullopt;
 	}
 
 	std::copy_n(nllValues.begin(), nllValues.size(),
 		    std::begin(config.nll.coeff));
 
-	std::string scaleMode = rFObject["scale-mode"].get<std::string>("");
+	std::string scaleMode = rFObject["scale-mode"].get<std::string>().value_or("");
 	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 'nll:scale-mode': expected "
-			<< "'linear' or 'logarithmic' value, got "
-			<< scaleMode;
+		return std::nullopt;
+	}
+
+	return config;
+}
+
+namespace ipa::rkisp1::algorithms {
+
+/**
+ * \class Dpf
+ * \brief RkISP1 Denoise Pre-Filter control
+ *
+ * The denoise pre-filter algorithm is a bilateral filter which combines a
+ * range filter and a domain filter. The denoise pre-filter is applied before
+ * demosaicing.
+ */
+
+LOG_DEFINE_CATEGORY(RkISP1Dpf)
+
+Dpf::Dpf()
+	: config_({}), strengthConfig_({}),
+	  noiseReductionModes_({}),
+	  runningMode_(controls::draft::NoiseReductionModeOff)
+{
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int Dpf::init([[maybe_unused]] IPAContext &context,
+	      const YamlObject &tuningData)
+{
+	/* Parse tuning block. */
+	if (!parseConfig(tuningData)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+bool Dpf::parseConfig(const YamlObject &tuningData)
+{
+	/* Parse base config. */
+	if (!parseSingleConfig(tuningData, config_, strengthConfig_)) {
+		return false;
+	}
+
+	/* Parse modes. */
+	if (!parseModes(tuningData)) {
 		return false;
 	}
 
-	const YamlObject &fSObject = tuningData["strength"];
+	return true;
+}
+
+bool Dpf::parseModes(const YamlObject &tuningData)
+{
+	/* Parse noise reduction modes. */
+	if (!tuningData.contains("modes")) {
+		return true;
+	}
+
+	noiseReductionModes_.clear();
+	for (const auto &entry : tuningData["modes"].asList()) {
+		std::optional<std::string> typeOpt =
+			entry["type"].get<std::string>();
+		if (!typeOpt) {
+			LOG(RkISP1Dpf, Error) << "Modes entry missing type";
+			return false;
+		}
+
+		int32_t modeValue = controls::draft::NoiseReductionModeOff;
+		if (*typeOpt == "minimal") {
+			modeValue = controls::draft::NoiseReductionModeMinimal;
+		} else if (*typeOpt == "fast") {
+			modeValue = controls::draft::NoiseReductionModeFast;
+		} else if (*typeOpt == "highquality") {
+			modeValue = controls::draft::NoiseReductionModeHighQuality;
+		} else if (*typeOpt == "zsl") {
+			modeValue = controls::draft::NoiseReductionModeZSL;
+		} else {
+			LOG(RkISP1Dpf, Error) << "Unknown mode type: " << *typeOpt;
+			return false;
+		}
+
+		ModeConfig mode{};
+		mode.modeValue = modeValue;
+		if (!parseSingleConfig(entry, mode.dpf, mode.strength)) {
+			return false;
+		}
+		noiseReductionModes_.push_back(mode);
+	}
+
+	return true;
+}
+
+bool Dpf::parseSingleConfig(const YamlObject &tuningData,
+			    rkisp1_cif_isp_dpf_config &config,
+			    rkisp1_cif_isp_dpf_strength_config &strengthConfig)
+{
+	auto dpfConfig = tuningData.get<rkisp1_cif_isp_dpf_config>();
+	if (!dpfConfig)
+		return false;
+
+	config = *dpfConfig;
+
+	auto strength = tuningData["strength"].get<rkisp1_cif_isp_dpf_strength_config>();
+	if (!strength)
+		return false;
 
-	strengthConfig.r = fSObject["r"].get<uint8_t>().value_or(64);
-	strengthConfig.g = fSObject["g"].get<uint8_t>().value_or(64);
-	strengthConfig.b = fSObject["b"].get<uint8_t>().value_or(64);
+	strengthConfig = *strength;
 
 	return true;
 }