@@ -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;
}
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(-)