[v3,10/19] ipa: rkisp1: agc: Add correction for exposure quantization
diff mbox series

Message ID 20250815102945.1602071-11-stefan.klug@ideasonboard.com
State New
Headers show
Series
  • Implement WDR algorithm
Related show

Commit Message

Stefan Klug Aug. 15, 2025, 10:29 a.m. UTC
There are several occations where quantization can lead to visible
effects.

In WDR mode it can happen that exposure times get set to very low values
(Sometimes 2-3 lines). This intentionally introduced underexposure is
corrected by the GWDR module. As exposure time is quantized by lines,
the smallest possible change in exposure time now results in a quite
visible change in perceived brightness.

Sometimes the possible gain steps are also quite large leading to
visible jumps if e.g. if the exposure time is fixed.

Mitigate that by applying a global gain to account for the error
introduced by the exposure quantization.

ToDo: This needs perfect frame synchronous control of the sensor to work
properly which is not guaranteed in all cases. It still improves the
behavior with the current regulation and can easily be skipped, when
there is no compress algorithm.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>

---

Changes in v3:
- Collected tags
---
 src/ipa/rkisp1/algorithms/agc.cpp | 24 +++++++++++++++++++++---
 src/ipa/rkisp1/ipa_context.h      |  2 ++
 2 files changed, 23 insertions(+), 3 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index 0a29326841fb..d34c041f9fe1 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -199,6 +199,9 @@  int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
 	context.configuration.agc.measureWindow.h_size = configInfo.outputSize.width;
 	context.configuration.agc.measureWindow.v_size = configInfo.outputSize.height;
 
+	AgcMeanLuminance::configure(context.configuration.sensor.lineDuration,
+				    context.camHelper.get());
+
 	setLimits(context.configuration.sensor.minExposureTime,
 		  context.configuration.sensor.maxExposureTime,
 		  context.configuration.sensor.minAnalogueGain,
@@ -283,6 +286,10 @@  void Agc::queueRequest(IPAContext &context,
 	if (!frameContext.agc.autoGainEnabled)
 		frameContext.agc.gain = agc.manual.gain;
 
+	if (!frameContext.agc.autoExposureEnabled &&
+	    !frameContext.agc.autoGainEnabled)
+		frameContext.agc.quantizationGain = 1.0;
+
 	const auto &meteringMode = controls.get(controls::AeMeteringMode);
 	if (meteringMode) {
 		frameContext.agc.updateMetering = agc.meteringMode != *meteringMode;
@@ -336,12 +343,17 @@  void Agc::prepare(IPAContext &context, const uint32_t frame,
 {
 	uint32_t activeAutoExposure = context.activeState.agc.automatic.exposure;
 	double activeAutoGain = context.activeState.agc.automatic.gain;
+	double activeAutoQGain = context.activeState.agc.automatic.quantizationGain;
 
 	/* Populate exposure and gain in auto mode */
-	if (frameContext.agc.autoExposureEnabled)
+	if (frameContext.agc.autoExposureEnabled) {
 		frameContext.agc.exposure = activeAutoExposure;
-	if (frameContext.agc.autoGainEnabled)
+		frameContext.agc.quantizationGain = activeAutoQGain;
+	}
+	if (frameContext.agc.autoGainEnabled) {
 		frameContext.agc.gain = activeAutoGain;
+		frameContext.agc.quantizationGain = activeAutoQGain;
+	}
 
 	/*
 	 * Populate manual exposure and gain from the active auto values when
@@ -354,6 +366,12 @@  void Agc::prepare(IPAContext &context, const uint32_t frame,
 	if (!frameContext.agc.autoGainEnabled && frameContext.agc.autoGainModeChange) {
 		context.activeState.agc.manual.gain = activeAutoGain;
 		frameContext.agc.gain = activeAutoGain;
+		frameContext.agc.quantizationGain = activeAutoQGain;
+	}
+
+	if (context.activeState.compress.supported) {
+		frameContext.compress.enable = true;
+		frameContext.compress.gain = frameContext.agc.quantizationGain;
 	}
 
 	if (frame > 0 && !frameContext.agc.updateMetering)
@@ -582,7 +600,7 @@  void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 	/* Update the estimated exposure and gain. */
 	activeState.agc.automatic.exposure = newExposureTime / lineDuration;
 	activeState.agc.automatic.gain = aGain;
-
+	activeState.agc.automatic.quantizationGain = qGain;
 	/*
 	 * Expand the target frame duration so that we do not run faster than
 	 * the minimum frame duration when we have short exposures.
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index 37a74215ce19..362ab2fda5fe 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -77,6 +77,7 @@  struct IPAActiveState {
 		struct {
 			uint32_t exposure;
 			double gain;
+			double quantizationGain;
 		} automatic;
 
 		bool autoExposureEnabled;
@@ -135,6 +136,7 @@  struct IPAFrameContext : public FrameContext {
 		uint32_t exposure;
 		double gain;
 		double exposureValue;
+		double quantizationGain;
 		uint32_t vblank;
 		bool autoExposureEnabled;
 		bool autoGainEnabled;