[PATCH 4/8] ipa: rkisp1: Add correction for exposure quantization

Stefan Klug stefan.klug at ideasonboard.com
Fri Apr 11 15:04:11 CEST 2025


When WDR regulation is active, 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 smalles possible change in exposure time now
results in a quite visible change in perceived brightness.

Mitigate that by applying a small 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.

Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>
---
 src/ipa/rkisp1/algorithms/agc.cpp |  2 ++
 src/ipa/rkisp1/algorithms/awb.cpp | 12 ++++++++----
 src/ipa/rkisp1/ipa_context.h      |  2 ++
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index 8e77455e7afd..0e4fd3663167 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -583,6 +583,8 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 	activeState.agc.automatic.exposure = newExposureTime / lineDuration;
 	activeState.agc.automatic.gain = aGain;
 
+	activeState.agc.automatic.gainLostInExposureQuantization =
+		newExposureTime / (activeState.agc.automatic.exposure * lineDuration);
 	/*
 	 * 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/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
index 84aa1d29419d..cc78136a22c8 100644
--- a/src/ipa/rkisp1/algorithms/awb.cpp
+++ b/src/ipa/rkisp1/algorithms/awb.cpp
@@ -170,6 +170,7 @@ void Awb::queueRequest(IPAContext &context,
 	awbAlgo_->handleControls(controls);
 
 	frameContext.awb.autoEnabled = awb.autoEnabled;
+	frameContext.awb.additionalGain = 1.0;
 
 	if (awb.autoEnabled)
 		return;
@@ -218,15 +219,18 @@ void Awb::prepare(IPAContext &context, const uint32_t frame,
 		auto &awb = context.activeState.awb;
 		frameContext.awb.gains = awb.automatic.gains;
 		frameContext.awb.temperatureK = awb.automatic.temperatureK;
+		frameContext.awb.additionalGain =
+			context.activeState.agc.automatic.gainLostInExposureQuantization;
 	}
 
+	auto gains = frameContext.awb.gains * frameContext.awb.additionalGain;
 	auto gainConfig = params->block<BlockType::AwbGain>();
 	gainConfig.setEnabled(true);
 
-	gainConfig->gain_green_b = std::clamp<int>(256 * frameContext.awb.gains.g(), 0, 0x3ff);
-	gainConfig->gain_blue = std::clamp<int>(256 * frameContext.awb.gains.b(), 0, 0x3ff);
-	gainConfig->gain_red = std::clamp<int>(256 * frameContext.awb.gains.r(), 0, 0x3ff);
-	gainConfig->gain_green_r = std::clamp<int>(256 * frameContext.awb.gains.g(), 0, 0x3ff);
+	gainConfig->gain_green_b = std::clamp<int>(256 * gains.g(), 0, 0x3ff);
+	gainConfig->gain_blue = std::clamp<int>(256 * gains.b(), 0, 0x3ff);
+	gainConfig->gain_red = std::clamp<int>(256 * gains.r(), 0, 0x3ff);
+	gainConfig->gain_green_r = std::clamp<int>(256 * gains.g(), 0, 0x3ff);
 
 	/* If we have already set the AWB measurement parameters, return. */
 	if (frame > 0)
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index 7ccc7b501aff..182203880ac9 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -76,6 +76,7 @@ struct IPAActiveState {
 		} manual;
 		struct {
 			uint32_t exposure;
+			double gainLostInExposureQuantization;
 			double gain;
 		} automatic;
 
@@ -149,6 +150,7 @@ struct IPAFrameContext : public FrameContext {
 		RGB<double> gains;
 		bool autoEnabled;
 		unsigned int temperatureK;
+		double additionalGain;
 	} awb;
 
 	struct {
-- 
2.43.0



More information about the libcamera-devel mailing list