[v2,1/7] ipa: rkisp1: filter: Parse tuning modes/sharpness from config
diff mbox series

Message ID 20260220221636.216353-2-rui.wang@ideasonboard.com
State New
Headers show
Series
  • ipa: rkisp1: make Filter tuning-driven and add manual controls
Related show

Commit Message

Rui Wang Feb. 20, 2026, 10:16 p.m. UTC
- Add Filter tuning parsers for NoiseReductionModes and Sharpness,
 - Validate keys during parsing, and store parsed values
   in unordered_map/unordered_set-based containers for faster lookup
   and simpler key-based access.

Sample format in YAML:
- Filter:
    NoiseReductionModes:
      NoiseReductionModeFast: [thresh_sh0: 18, thresh_sh1: 33, thresh_bl0: 8,
	thresh_bl1: 2, mode: 1, lum_weight: 2, grn_stage1: 4, chr_v_mode: 3,
	chr_h_mode: 3, fac_sh0: 4, fac_sh1: 4, fac_mid: 4, fac_bl0: 2, fac_bl1:0]
    Sharpness:
	  - [fac_sh0:  4, fac_sh1:  4, fac_mid:  4, fac_bl0:  2, fac_bl1:  0]

Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>
---
 src/ipa/rkisp1/algorithms/filter.cpp | 128 +++++++++++++++++++++++++++
 src/ipa/rkisp1/algorithms/filter.h   |  10 +++
 2 files changed, 138 insertions(+)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp
index 8ad79801..85963f8c 100644
--- a/src/ipa/rkisp1/algorithms/filter.cpp
+++ b/src/ipa/rkisp1/algorithms/filter.cpp
@@ -8,6 +8,7 @@ 
 #include "filter.h"
 
 #include <cmath>
+#include <unordered_set>
 
 #include <libcamera/base/log.h>
 
@@ -39,6 +40,18 @@  LOG_DEFINE_CATEGORY(RkISP1Filter)
 static constexpr uint32_t kFiltLumWeightDefault = 0x00022040;
 static constexpr uint32_t kFiltModeDefault = 0x000004f2;
 
+namespace {
+const std::unordered_set<std::string> kSharpnessKeyNames = {
+	"fac_sh0", "fac_sh1", "fac_mid", "fac_bl0", "fac_bl1"
+};
+
+const std::unordered_set<std::string> kFilterKeyNames = {
+	"thresh_sh0", "thresh_sh1", "thresh_bl0", "thresh_bl1",
+	"mode", "lum_weight", "grn_stage1", "chr_v_mode", "chr_h_mode",
+	"fac_sh0", "fac_sh1", "fac_mid", "fac_bl0", "fac_bl1"
+};
+} /* namespace */
+
 /**
  * \copydoc libcamera::ipa::Algorithm::init
  */
@@ -50,6 +63,121 @@  int Filter::init(IPAContext &context,
 
 	return 0;
 }
+
+int Filter::parseConfig(const YamlObject &tuningData)
+{
+	if (!tuningData.contains("NoiseReductionModes")) {
+		LOG(RkISP1Filter, Error) << "Missing NoiseReductionModes in Filter tuning data";
+		return -EINVAL;
+	}
+
+	const YamlObject &modesObject = tuningData["NoiseReductionModes"];
+	if (!modesObject.isDictionary()) {
+		LOG(RkISP1Filter, Error) << "NoiseReductionModes must be a dictionary";
+		return -EINVAL;
+	}
+
+	for (const auto &[modeName, modeData] : modesObject.asDict()) {
+		auto it = controls::draft::NoiseReductionModeNameValueMap.find(modeName);
+		if (it == controls::draft::NoiseReductionModeNameValueMap.end()) {
+			LOG(RkISP1Filter, Error) << "Unknown mode: " << modeName;
+			return -EINVAL;
+		}
+
+		int ret = parseModeConfig(modeData, modes_[it->second]);
+		if (ret)
+			return ret;
+	}
+
+	if (!tuningData.contains("Sharpness")) {
+		LOG(RkISP1Filter, Error) << "Missing Sharpness in Filter tuning data";
+		return -EINVAL;
+	}
+
+	const YamlObject &sharpnessObject = tuningData["Sharpness"];
+	if (!sharpnessObject.isList()) {
+		LOG(RkISP1Filter, Error) << "Sharpness must be a list";
+		return -EINVAL;
+	}
+
+	const size_t sharpnessLevels = sharpnessObject.size();
+	if (!sharpnessLevels) {
+		LOG(RkISP1Filter, Error) << "Sharpness must not be empty";
+		return -EINVAL;
+	}
+
+	sharpness_.assign(sharpnessLevels, {});
+
+	for (size_t i = 0; i < sharpnessLevels; i++) {
+		int ret = parseSharpnessConfig(sharpnessObject[i], sharpness_[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int Filter::parseModeConfig(const YamlObject &modeData,
+			    std::unordered_map<std::string, uint32_t> &modeParams)
+{
+	if (!modeData.isList()) {
+		LOG(RkISP1Filter, Error) << "Mode config must be a list";
+		return -EINVAL;
+	}
+
+	for (const auto &entry : modeData.asList()) {
+		for (const auto &[key, val] : entry.asDict()) {
+			if (kFilterKeyNames.find(key) == kFilterKeyNames.end()) {
+				LOG(RkISP1Filter, Error)
+					<< "Unknown mode key '" << key << "'";
+				return -EINVAL;
+			}
+
+			auto v = val.get<uint32_t>();
+			if (!v) {
+				LOG(RkISP1Filter, Error)
+					<< "Invalid value for key '" << key << "'";
+				return -EINVAL;
+			}
+			modeParams[key] = *v;
+		}
+	}
+
+	return 0;
+}
+
+int Filter::parseSharpnessConfig(const YamlObject &data,
+				 std::unordered_map<std::string, uint32_t> &sharpParams)
+{
+	if (!data.isList()) {
+		LOG(RkISP1Filter, Error) << "Sharpness entry must be a list";
+		return -EINVAL;
+	}
+
+	sharpParams.clear();
+
+	for (const auto &entry : data.asList()) {
+		for (const auto &[key, val] : entry.asDict()) {
+			if (kSharpnessKeyNames.find(key) == kSharpnessKeyNames.end()) {
+				LOG(RkISP1Filter, Error)
+					<< "Unknown sharpness key '" << key << "'";
+				return -EINVAL;
+			}
+
+			auto v = val.get<uint32_t>();
+			if (!v) {
+				LOG(RkISP1Filter, Error)
+					<< "Invalid value for key '" << key << "'";
+				return -EINVAL;
+			}
+
+			sharpParams[key] = *v;
+		}
+	}
+
+	return 0;
+}
+
 /**
  * \copydoc libcamera::ipa::Algorithm::queueRequest
  */
diff --git a/src/ipa/rkisp1/algorithms/filter.h b/src/ipa/rkisp1/algorithms/filter.h
index 37d8938d..83b90ef3 100644
--- a/src/ipa/rkisp1/algorithms/filter.h
+++ b/src/ipa/rkisp1/algorithms/filter.h
@@ -28,6 +28,16 @@  public:
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     RkISP1Params *params) override;
+
+private:
+	int parseConfig(const YamlObject &tuningData);
+	int parseModeConfig(const YamlObject &modeData,
+			    std::unordered_map<std::string, uint32_t> &modeParams);
+	int parseSharpnessConfig(const YamlObject &data,
+				 std::unordered_map<std::string, uint32_t> &sharpParams);
+
+	std::unordered_map<int32_t, std::unordered_map<std::string, uint32_t>> modes_;
+	std::vector<std::unordered_map<std::string, uint32_t>> sharpness_;
 };
 
 } /* namespace ipa::rkisp1::algorithms */