[2/2] ipa: simple: agc: make the exposure target tunable
diff mbox series

Message ID 20261017153829.442320-3-xiaqinghuan@mail.ustc.edu.cn
State New
Headers show
Series
  • ipa: libipa: add sensor helpers for GC08A8/S5KJNS and make the AGC target tunable
Related show

Commit Message

Qianhui Xu Oct. 17, 2026, 3:38 p.m. UTC
The simple IPA AGC targets the middle of the histogram range, i.e. a mean
sample value of 0.5. As the debayer step gamma-encodes its output (the
default gamma is 2.2), such a target maps to roughly 73% of the full code
range on output, which looks washed out and clips highlights in scenes
with a high dynamic range.

Allow platforms to override the target from the tuning file with a new
"exposureTarget" parameter, expressed as a fraction of the histogram
range. The default keeps the existing behaviour, so existing tuning files
keep their meaning.

Signed-off-by: Qianhui Xu <xiaqinghuan@mail.ustc.edu.cn>
---
 src/ipa/simple/algorithms/agc.cpp | 24 +++++++++++++++++++-----
 src/ipa/simple/algorithms/agc.h   |  4 ++++
 2 files changed, 23 insertions(+), 5 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp
index 2f7e040..b6e9d30 100644
--- a/src/ipa/simple/algorithms/agc.cpp
+++ b/src/ipa/simple/algorithms/agc.cpp
@@ -25,10 +25,11 @@  namespace ipa::soft::algorithms {
 static constexpr unsigned int kExposureBinsCount = 5;
 
 /*
- * The exposure is optimal when the mean sample value of the histogram is
- * in the middle of the range.
+ * The exposure is optimal when the mean sample value of the histogram matches
+ * the configured target. 0.5 (the middle of the range) is a bright default;
+ * sensors tuned for photographic output usually target a lower code value.
  */
-static constexpr float kExposureOptimal = kExposureBinsCount / 2.0;
+static constexpr double kDefaultExposureTarget = 0.5;
 
 /*
  * This implements the hysteresis for the exposure adjustment.
@@ -38,9 +39,21 @@  static constexpr float kExposureOptimal = kExposureBinsCount / 2.0;
 static constexpr float kExposureSatisfactory = 0.2;
 
 Agc::Agc()
+	: exposureTarget_(kDefaultExposureTarget)
 {
 }
 
+int Agc::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData)
+{
+	const ValueNode &target = tuningData["exposureTarget"];
+
+	exposureTarget_ = target.get<double>(kDefaultExposureTarget);
+	LOG(IPASoftExposure, Debug)
+		<< "Exposure target " << exposureTarget_;
+
+	return 0;
+}
+
 void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV)
 {
 	/*
@@ -53,8 +66,9 @@  void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou
 
 	int32_t &exposure = frameContext.sensor.exposure;
 	double &again = frameContext.sensor.gain;
+	const double optimal = exposureTarget_ * kExposureBinsCount;
 
-	if (exposureMSV < kExposureOptimal - kExposureSatisfactory) {
+	if (exposureMSV < optimal - kExposureSatisfactory) {
 		if (exposure < context.configuration.agc.exposureMax) {
 			int32_t next = exposure * kExpNumeratorUp / kExpDenominator;
 			if (next - exposure < 1)
@@ -70,7 +84,7 @@  void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou
 		}
 	}
 
-	if (exposureMSV > kExposureOptimal + kExposureSatisfactory) {
+	if (exposureMSV > optimal + kExposureSatisfactory) {
 		if (again > context.configuration.agc.again10) {
 			double next = again * kExpNumeratorDown / kExpDenominator;
 			if (again - next < context.configuration.agc.againMinStep)
diff --git a/src/ipa/simple/algorithms/agc.h b/src/ipa/simple/algorithms/agc.h
index 112d9f5..8d3d2f6 100644
--- a/src/ipa/simple/algorithms/agc.h
+++ b/src/ipa/simple/algorithms/agc.h
@@ -19,6 +19,8 @@  public:
 	Agc();
 	~Agc() = default;
 
+	int init(IPAContext &context, const ValueNode &tuningData) override;
+
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const SwIspStats *stats,
@@ -26,6 +28,8 @@  public:
 
 private:
 	void updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV);
+
+	double exposureTarget_;
 };
 
 } /* namespace ipa::soft::algorithms */