ipa: simple: agc: Read exposure target and gain from YAML
diff mbox series

Message ID 20260501191400.985920-4-devve.3@gmail.com
State New
Headers show
Series
  • ipa: simple: agc: Read exposure target and gain from YAML
Related show

Commit Message

d3vv3 May 1, 2026, 7:13 p.m. UTC
Replace the hardcoded kExposureOptimal, kExposureSatisfactory, and
kExpProportionalGain constants with member variables read from the
tuning file as exposureTarget, hysteresis, and proportionalGain.
Defaults match the previous values (2.5, 0.2, 0.04).

Signed-off-by: d3vv3 <devve.3@gmail.com>
---
 src/ipa/simple/algorithms/agc.cpp | 33 ++++++++++++++++++++-----------
 src/ipa/simple/algorithms/agc.h   |  8 ++++++++
 2 files changed, 30 insertions(+), 11 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp
index ac977d5f..66618d0f 100644
--- a/src/ipa/simple/algorithms/agc.cpp
+++ b/src/ipa/simple/algorithms/agc.cpp
@@ -28,45 +28,56 @@  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.
+ * in the middle of the range. Overridable via YAML exposureTarget.
  */
-static constexpr float kExposureOptimal = kExposureBinsCount / 2.0;
+static constexpr float kExposureTargetDefault = kExposureBinsCount / 2.0;
 
 /*
  * This implements the hysteresis for the exposure adjustment.
  * It is small enough to have the exposure close to the optimal, and is big
  * enough to prevent the exposure from wobbling around the optimal value.
  */
-static constexpr float kExposureSatisfactory = 0.2;
+static constexpr float kHysteresisDefault = 0.2;
 
 /*
  * Proportional gain for exposure/gain adjustment. Maps the MSV error to a
  * multiplicative correction factor:
  *
- *   factor = 1.0 + kExpProportionalGain * error
+ *   factor = 1.0 + proportionalGain_ * error
  *
- * With kExpProportionalGain = 0.04:
+ * With proportionalGain_ = 0.04:
  *   - max error ~2.5 -> factor 1.10 (~10% step, same as before)
  *   - error 1.0      -> factor 1.04 (~4% step)
  *   - error 0.3      -> factor 1.012 (~1.2% step)
  *
- * This replaces the fixed 10% bang-bang step with a proportional correction
- * that converges smoothly and avoids overshooting near the target.
+ * Overridable via YAML proportionalGain.
  */
-static constexpr float kExpProportionalGain = 0.04;
+static constexpr float kProportionalGainDefault = 0.04;
 
 Agc::Agc()
 {
 }
 
+int Agc::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData)
+{
+	exposureTarget_ = tuningData["exposureTarget"].get<float>()
+		.value_or(kExposureTargetDefault);
+	hysteresis_ = tuningData["hysteresis"].get<float>()
+		.value_or(kHysteresisDefault);
+	proportionalGain_ = tuningData["proportionalGain"].get<float>()
+		.value_or(kProportionalGainDefault);
+
+	return 0;
+}
+
 void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV)
 {
 	int32_t &exposure = frameContext.sensor.exposure;
 	double &again = frameContext.sensor.gain;
 
-	double error = kExposureOptimal - exposureMSV;
+	double error = exposureTarget_ - exposureMSV;
 
-	if (std::abs(error) <= kExposureSatisfactory)
+	if (std::abs(error) <= hysteresis_)
 		return;
 
 	/*
@@ -74,7 +85,7 @@  void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou
 	 * determines the direction: positive error means too dark (increase),
 	 * negative means too bright (decrease).
 	 */
-	float factor = 1.0f + static_cast<float>(error) * kExpProportionalGain;
+	float factor = 1.0f + static_cast<float>(error) * proportionalGain_;
 
 	if (factor > 1.0f) {
 		/* Scene too dark: increase exposure first, then gain. */
diff --git a/src/ipa/simple/algorithms/agc.h b/src/ipa/simple/algorithms/agc.h
index 112d9f5a..b8ed542b 100644
--- a/src/ipa/simple/algorithms/agc.h
+++ b/src/ipa/simple/algorithms/agc.h
@@ -7,6 +7,8 @@ 
 
 #pragma once
 
+#include <libcamera/internal/yaml_parser.h>
+
 #include "algorithm.h"
 
 namespace libcamera {
@@ -19,6 +21,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 +30,10 @@  public:
 
 private:
 	void updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV);
+
+	float exposureTarget_;
+	float hysteresis_;
+	float proportionalGain_;
 };
 
 } /* namespace ipa::soft::algorithms */