[v1,07/11] ipa: rkisp1: algorithms: dpf: manage DPF mode transitions
diff mbox series

Message ID 20251125000848.4103786-8-rui.wang@ideasonboard.com
State New
Headers show
Series
  • ipa: rkisp1: DPF refactor and tuning improvements
Related show

Commit Message

Rui Wang Nov. 25, 2025, 12:08 a.m. UTC
Implement hysteresis-aware mode switching via processModeChange(), snapshot
the current configuration when entering manual mode, and restore base tuning
when returning to auto mode.

The implementation includes:
- processModeChange(): Detects DpfMode control changes with hysteresis to
  prevent rapid mode toggling
- snapshotCurrentToOverrides(): Captures current config when entering manual
  mode so users can continue from current state
- restoreAutoConfig(): Restores base or exposure gain config when returning to
  auto mode, clearing all manual overrides

Updates queueRequest() to handle mode transitions with appropriate logging
and config restoration.

Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>
---
 src/ipa/rkisp1/algorithms/denoise.h |  15 ++++
 src/ipa/rkisp1/algorithms/dpf.cpp   | 121 +++++++++++++++++++++++++++-
 src/ipa/rkisp1/algorithms/dpf.h     |   8 ++
 3 files changed, 140 insertions(+), 4 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/denoise.h b/src/ipa/rkisp1/algorithms/denoise.h
index ffe27af8..4c917c1a 100644
--- a/src/ipa/rkisp1/algorithms/denoise.h
+++ b/src/ipa/rkisp1/algorithms/denoise.h
@@ -35,12 +35,27 @@  protected:
 	virtual void collectManualOverrides([[maybe_unused]] const ControlList &controls)
 	{
 	}
+	virtual bool processModeChange([[maybe_unused]] const ControlList &controls,
+				       [[maybe_unused]] uint32_t currentFrame)
+	{
+		return false;
+	}
+	virtual void snapshotCurrentToOverrides()
+	{
+	}
+	virtual void restoreAutoConfig([[maybe_unused]] IPAContext &context, [[maybe_unused]] IPAFrameContext &frameContext)
+	{
+	}
 	virtual void handleReductionModeControl([[maybe_unused]] const ControlList &controls,
 						[[maybe_unused]] IPAFrameContext &frameContext,
 						[[maybe_unused]] IPAContext &context,
 						[[maybe_unused]] uint32_t frame)
 	{
 	}
+	virtual void handleDisableMode([[maybe_unused]] IPAFrameContext &frameContext,
+				       [[maybe_unused]] IPAContext &context)
+	{
+	}
 	virtual int32_t getRunningMode() const { return currentRunMode_; }
 	virtual void setRunningMode(int32_t mode) { currentRunMode_ = mode; }
 private:
diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index 0b070206..91bcd503 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -339,6 +339,17 @@  void Dpf::handleReductionModeControl(const ControlList &controls,
 	frameContext.dpf.denoise = true;
 	frameContext.dpf.update = true;
 }
+
+void Dpf::handleDisableMode(IPAFrameContext &frameContext, IPAContext &context)
+{
+	/* Reset reduction mode to Off when DPF is disabled */
+	currentReductionMode_ = controls::draft::NoiseReductionModeOff;
+
+	/* Ensure denoise is disabled */
+	context.activeState.dpf.denoise = false;
+	frameContext.dpf.denoise = false;
+}
+
 void Dpf::loadReductionModeConfig(IPAFrameContext &frameContext)
 {
 	/* Find mode config */
@@ -474,6 +485,76 @@  bool Dpf::checkOverridesChanged()
 	return false;
 }
 
+void Dpf::snapshotCurrentToOverrides()
+{
+	/* clear previous overrides */
+	overrides_.clear();
+	overrides_.strength = DpfStrengthSettings{
+		strengthConfig_.r,
+		strengthConfig_.g,
+		strengthConfig_.b
+	};
+	if (!isDevMode())
+		return;
+	/* Snapshot current config to overrides */
+	DpfSpatialGreenSettings green;
+	std::copy_n(std::begin(config_.g_flt.spatial_coeff),
+		    RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS,
+		    green.coeffs.begin());
+	overrides_.spatialGreen = green;
+	DpfSpatialRbSettings rb;
+	std::copy_n(std::begin(config_.rb_flt.spatial_coeff),
+		    RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS,
+		    rb.coeffs.begin());
+	rb.size = (config_.rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9)
+			  ? 1
+			  : 0;
+	overrides_.spatialRb = rb;
+	overrides_.rbSize = rb.size;
+	DpfNllSettings nll;
+	std::copy_n(std::begin(config_.nll.coeff),
+		    RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS,
+		    nll.coeffs.begin());
+	nll.scaleMode = (config_.nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC)
+				? 1
+				: 0;
+	overrides_.nll = nll;
+}
+
+void Dpf::restoreAutoConfig(IPAContext &context, IPAFrameContext &frameContext)
+{
+	/* clear previous overrides */
+	overrides_.clear();
+	if (useExposureIndexLevels_) {
+		uint32_t exposureIndex = computeExposureIndex(context, frameContext);
+		int32_t idx =
+			DenoiseBaseAlgorithm::selectExposureIndexBand(exposureIndex,
+								      exposureIndexLevels_);
+		if (idx >= 0) {
+			config_ = exposureIndexLevels_[idx].dpf;
+			strengthConfig_ = exposureIndexLevels_[idx].strength;
+			lastExposureGainIndex_ = idx;
+		}
+	} else {
+		config_ = baseConfig_;
+		strengthConfig_ = baseStrengthConfig_;
+		lastExposureGainIndex_ = -1;
+	}
+	frameContext.dpf.update = true;
+}
+
+bool Dpf::processModeChange(const ControlList &controls, [[maybe_unused]] uint32_t currentFrame)
+{
+	const auto &cMode = controls.get(controls::rkisp1::DenoiseMode);
+	if (!cMode)
+		return false;
+	int32_t requestedMode = static_cast<int32_t>(*cMode);
+	auto currentMode = getRunningMode();
+
+	setRunningMode(requestedMode);
+	return (currentMode != getRunningMode());
+}
+
 /**
  * \copydoc libcamera::ipa::Algorithm::queueRequest
  */
@@ -483,13 +564,45 @@  void Dpf::queueRequest(IPAContext &context,
 		       const ControlList &controls)
 {
 	frameContext.dpf.update = false;
-	auto currentRunnungMode = getRunningMode();
-	handleReductionModeControl(controls, frameContext, context, frame);
 
-	if (currentRunnungMode == controls::rkisp1::DenoiseModeReduction && currentReductionMode_ != controls::draft::NoiseReductionModeOff) {
-		loadReductionModeConfig(frameContext);
+	auto modeChanged = processModeChange(controls, frame);
+	switch (getRunningMode()) {
+	case controls::rkisp1::DenoiseModeManual:
+		snapshotCurrentToOverrides();
+		collectManualOverrides(controls);
+		if (checkOverridesChanged()) {
+			frameContext.dpf.update = true;
+		}
+		LOG(RkISP1Dpf, Debug) << "DPF mode=Manual (snapshot captured)";
+		break;
+	case controls::rkisp1::DenoiseModeAuto:
+		restoreAutoConfig(context, frameContext);
+		LOG(RkISP1Dpf, Debug) << "DPF mode=Auto (restored auto config)";
+		break;
+	case controls::rkisp1::DenoiseModeReduction:
+		handleReductionModeControl(controls,
+					   frameContext,
+					   context,
+					   frame); /* Check reduction mode first */
+		if (currentReductionMode_ != controls::draft::NoiseReductionModeOff) {
+			loadReductionModeConfig(frameContext);
+		}
+		LOG(RkISP1Dpf, Debug) << "DPF mode=Reduction (config loaded)";
+		break;
+	case controls::rkisp1::DenoiseModeDisabled:
+		handleDisableMode(frameContext, context);
+		break;
+	default:
+		LOG(RkISP1Dpf, Warning) << "DPF mode=Disabled";
 		return;
 	}
+	/* Set denoise based on mode */
+
+	if (modeChanged)
+		frameContext.dpf.update = true;
+	bool denoise = (getRunningMode() != controls::rkisp1::DenoiseModeDisabled);
+	context.activeState.dpf.denoise = denoise;
+	frameContext.dpf.denoise = denoise;
 }
 
 /**
diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h
index d6707d34..c63d1558 100644
--- a/src/ipa/rkisp1/algorithms/dpf.h
+++ b/src/ipa/rkisp1/algorithms/dpf.h
@@ -71,12 +71,14 @@  private:
 	std::vector<ExposureIndexLevelConfig> exposureIndexLevels_;
 	std::vector<ModeConfig> modes_;
 	bool useExposureIndexLevels_ = false;
+	int32_t lastExposureGainIndex_ = -1;
 	int32_t currentReductionMode_ = controls::draft::NoiseReductionModeOff;
 
 	void handleReductionModeControl(const ControlList &controls,
 					IPAFrameContext &frameContext,
 					IPAContext &context,
 					uint32_t frame) override;
+	void handleDisableMode(IPAFrameContext &frameContext, IPAContext &context) override;
 	void loadReductionModeConfig(IPAFrameContext &frameContext);
 	void collectManualOverrides(const ControlList &controls) override;
 	bool checkOverridesChanged();
@@ -84,6 +86,12 @@  private:
 	bool parseSingleConfig(const YamlObject &tuningData,
 			       rkisp1_cif_isp_dpf_config &config,
 			       rkisp1_cif_isp_dpf_strength_config &strengthConfig);
+
+	bool processModeChange(const ControlList &controls, uint32_t currentFrame) override;
+
+	void snapshotCurrentToOverrides() override;
+
+	void restoreAutoConfig(IPAContext &context, IPAFrameContext &frameContext) override;
 };
 
 } /* namespace ipa::rkisp1::algorithms */