[v4,16/19] libipa: agc_mean_luminance: Add support for additional constraints
diff mbox series

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

Commit Message

Stefan Klug Sept. 18, 2025, 2:43 p.m. UTC
Add support for additional constraints added at runtime. This is for
example useful for WDR use cases where you want to add an upper
constraint to limit the amount of saturated pixels.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

---

Changes in v4:
- Added missings docs for the constraints parameter
- Collected tag

Changes in v3:
- Added this patch
---
 src/ipa/ipu3/algorithms/agc.cpp       |  2 +-
 src/ipa/libipa/agc_mean_luminance.cpp | 17 +++++++++++++----
 src/ipa/libipa/agc_mean_luminance.h   |  3 ++-
 src/ipa/mali-c55/algorithms/agc.cpp   |  3 ++-
 src/ipa/rkisp1/algorithms/agc.cpp     |  4 ++--
 5 files changed, 20 insertions(+), 9 deletions(-)

Comments

Kieran Bingham Sept. 18, 2025, 6:28 p.m. UTC | #1
Quoting Stefan Klug (2025-09-18 15:43:25)
> Add support for additional constraints added at runtime. This is for
> example useful for WDR use cases where you want to add an upper
> constraint to limit the amount of saturated pixels.
> 
> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> 

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> ---
> 
> Changes in v4:
> - Added missings docs for the constraints parameter
> - Collected tag
> 
> Changes in v3:
> - Added this patch
> ---
>  src/ipa/ipu3/algorithms/agc.cpp       |  2 +-
>  src/ipa/libipa/agc_mean_luminance.cpp | 17 +++++++++++++----
>  src/ipa/libipa/agc_mean_luminance.h   |  3 ++-
>  src/ipa/mali-c55/algorithms/agc.cpp   |  3 ++-
>  src/ipa/rkisp1/algorithms/agc.cpp     |  4 ++--
>  5 files changed, 20 insertions(+), 9 deletions(-)
> 
> diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
> index da045640d569..b0d89541da85 100644
> --- a/src/ipa/ipu3/algorithms/agc.cpp
> +++ b/src/ipa/ipu3/algorithms/agc.cpp
> @@ -117,7 +117,7 @@ int Agc::configure(IPAContext &context,
>  
>         /* \todo Run this again when FrameDurationLimits is passed in */
>         setLimits(minExposureTime_, maxExposureTime_, minAnalogueGain_,
> -                 maxAnalogueGain_);
> +                 maxAnalogueGain_, {});
>         resetFrameCount();
>  
>         return 0;
> diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp
> index 45eba97516f3..64f36bd75dd2 100644
> --- a/src/ipa/libipa/agc_mean_luminance.cpp
> +++ b/src/ipa/libipa/agc_mean_luminance.cpp
> @@ -7,6 +7,7 @@
>  
>  #include "agc_mean_luminance.h"
>  
> +#include <algorithm>
>  #include <cmath>
>  
>  #include <libcamera/base/log.h>
> @@ -408,16 +409,20 @@ int AgcMeanLuminance::parseTuningData(const YamlObject &tuningData)
>   * \param[in] maxExposureTime Maximum ewposure time to allow
>   * \param[in] minGain Minimum gain to allow
>   * \param[in] maxGain Maximum gain to allow
> + * \param[in] constraints Additional constraints to apply
>   *
>   * This function calls \ref ExposureModeHelper::setLimits() for each
>   * ExposureModeHelper that has been created for this class.
>   */
>  void AgcMeanLuminance::setLimits(utils::Duration minExposureTime,
>                                  utils::Duration maxExposureTime,
> -                                double minGain, double maxGain)
> +                                double minGain, double maxGain,
> +                                std::vector<AgcMeanLuminance::AgcConstraint> constraints)
>  {
>         for (auto &[id, helper] : exposureModeHelpers_)
>                 helper->setLimits(minExposureTime, maxExposureTime, minGain, maxGain);
> +
> +       additionalConstraints_ = std::move(constraints);
>  }
>  
>  /**
> @@ -495,8 +500,7 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,
>                                              const Histogram &hist,
>                                              double gain)
>  {
> -       std::vector<AgcConstraint> &constraints = constraintModes_[constraintModeIndex];
> -       for (const AgcConstraint &constraint : constraints) {
> +       auto applyConstraint = [&gain, &hist](const AgcConstraint &constraint) {
>                 double newGain = constraint.yTarget * hist.bins() /
>                                  hist.interQuantileMean(constraint.qLo, constraint.qHi);
>  
> @@ -515,7 +519,12 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,
>                                 << newGain;
>                         gain = newGain;
>                 }
> -       }
> +       };
> +
> +       std::vector<AgcConstraint> &constraints = constraintModes_[constraintModeIndex];
> +       std::for_each(constraints.begin(), constraints.end(), applyConstraint);
> +
> +       std::for_each(additionalConstraints_.begin(), additionalConstraints_.end(), applyConstraint);
>  
>         return gain;
>  }
> diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h
> index 950b7b893754..d7ec548e3e58 100644
> --- a/src/ipa/libipa/agc_mean_luminance.h
> +++ b/src/ipa/libipa/agc_mean_luminance.h
> @@ -51,7 +51,7 @@ public:
>         }
>  
>         void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
> -                      double minGain, double maxGain);
> +                      double minGain, double maxGain, std::vector<AgcConstraint> constraints);
>  
>         std::map<int32_t, std::vector<AgcConstraint>> constraintModes()
>         {
> @@ -97,6 +97,7 @@ private:
>         utils::Duration filteredExposure_;
>         double relativeLuminanceTarget_;
>  
> +       std::vector<AgcConstraint> additionalConstraints_;
>         std::map<int32_t, std::vector<AgcConstraint>> constraintModes_;
>         std::map<int32_t, std::shared_ptr<ExposureModeHelper>> exposureModeHelpers_;
>         ControlInfoMap::Map controls_;
> diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp
> index 88f8664c9823..f60fddac3f04 100644
> --- a/src/ipa/mali-c55/algorithms/agc.cpp
> +++ b/src/ipa/mali-c55/algorithms/agc.cpp
> @@ -173,7 +173,8 @@ int Agc::configure(IPAContext &context,
>         setLimits(context.configuration.agc.minShutterSpeed,
>                   context.configuration.agc.maxShutterSpeed,
>                   context.configuration.agc.minAnalogueGain,
> -                 context.configuration.agc.maxAnalogueGain);
> +                 context.configuration.agc.maxAnalogueGain,
> +                 {});
>  
>         resetFrameCount();
>  
> diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
> index d0337fd0027f..d1b6bb7196f4 100644
> --- a/src/ipa/rkisp1/algorithms/agc.cpp
> +++ b/src/ipa/rkisp1/algorithms/agc.cpp
> @@ -206,7 +206,7 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
>         setLimits(context.configuration.sensor.minExposureTime,
>                   context.configuration.sensor.maxExposureTime,
>                   context.configuration.sensor.minAnalogueGain,
> -                 context.configuration.sensor.maxAnalogueGain);
> +                 context.configuration.sensor.maxAnalogueGain, {});
>  
>         resetFrameCount();
>  
> @@ -590,7 +590,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
>                 maxAnalogueGain = frameContext.agc.gain;
>         }
>  
> -       setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain);
> +       setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain, {});
>  
>         /*
>          * The Agc algorithm needs to know the effective exposure value that was
> -- 
> 2.48.1
>

Patch
diff mbox series

diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
index da045640d569..b0d89541da85 100644
--- a/src/ipa/ipu3/algorithms/agc.cpp
+++ b/src/ipa/ipu3/algorithms/agc.cpp
@@ -117,7 +117,7 @@  int Agc::configure(IPAContext &context,
 
 	/* \todo Run this again when FrameDurationLimits is passed in */
 	setLimits(minExposureTime_, maxExposureTime_, minAnalogueGain_,
-		  maxAnalogueGain_);
+		  maxAnalogueGain_, {});
 	resetFrameCount();
 
 	return 0;
diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp
index 45eba97516f3..64f36bd75dd2 100644
--- a/src/ipa/libipa/agc_mean_luminance.cpp
+++ b/src/ipa/libipa/agc_mean_luminance.cpp
@@ -7,6 +7,7 @@ 
 
 #include "agc_mean_luminance.h"
 
+#include <algorithm>
 #include <cmath>
 
 #include <libcamera/base/log.h>
@@ -408,16 +409,20 @@  int AgcMeanLuminance::parseTuningData(const YamlObject &tuningData)
  * \param[in] maxExposureTime Maximum ewposure time to allow
  * \param[in] minGain Minimum gain to allow
  * \param[in] maxGain Maximum gain to allow
+ * \param[in] constraints Additional constraints to apply
  *
  * This function calls \ref ExposureModeHelper::setLimits() for each
  * ExposureModeHelper that has been created for this class.
  */
 void AgcMeanLuminance::setLimits(utils::Duration minExposureTime,
 				 utils::Duration maxExposureTime,
-				 double minGain, double maxGain)
+				 double minGain, double maxGain,
+				 std::vector<AgcMeanLuminance::AgcConstraint> constraints)
 {
 	for (auto &[id, helper] : exposureModeHelpers_)
 		helper->setLimits(minExposureTime, maxExposureTime, minGain, maxGain);
+
+	additionalConstraints_ = std::move(constraints);
 }
 
 /**
@@ -495,8 +500,7 @@  double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,
 					     const Histogram &hist,
 					     double gain)
 {
-	std::vector<AgcConstraint> &constraints = constraintModes_[constraintModeIndex];
-	for (const AgcConstraint &constraint : constraints) {
+	auto applyConstraint = [&gain, &hist](const AgcConstraint &constraint) {
 		double newGain = constraint.yTarget * hist.bins() /
 				 hist.interQuantileMean(constraint.qLo, constraint.qHi);
 
@@ -515,7 +519,12 @@  double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,
 				<< newGain;
 			gain = newGain;
 		}
-	}
+	};
+
+	std::vector<AgcConstraint> &constraints = constraintModes_[constraintModeIndex];
+	std::for_each(constraints.begin(), constraints.end(), applyConstraint);
+
+	std::for_each(additionalConstraints_.begin(), additionalConstraints_.end(), applyConstraint);
 
 	return gain;
 }
diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h
index 950b7b893754..d7ec548e3e58 100644
--- a/src/ipa/libipa/agc_mean_luminance.h
+++ b/src/ipa/libipa/agc_mean_luminance.h
@@ -51,7 +51,7 @@  public:
 	}
 
 	void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
-		       double minGain, double maxGain);
+		       double minGain, double maxGain, std::vector<AgcConstraint> constraints);
 
 	std::map<int32_t, std::vector<AgcConstraint>> constraintModes()
 	{
@@ -97,6 +97,7 @@  private:
 	utils::Duration filteredExposure_;
 	double relativeLuminanceTarget_;
 
+	std::vector<AgcConstraint> additionalConstraints_;
 	std::map<int32_t, std::vector<AgcConstraint>> constraintModes_;
 	std::map<int32_t, std::shared_ptr<ExposureModeHelper>> exposureModeHelpers_;
 	ControlInfoMap::Map controls_;
diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp
index 88f8664c9823..f60fddac3f04 100644
--- a/src/ipa/mali-c55/algorithms/agc.cpp
+++ b/src/ipa/mali-c55/algorithms/agc.cpp
@@ -173,7 +173,8 @@  int Agc::configure(IPAContext &context,
 	setLimits(context.configuration.agc.minShutterSpeed,
 		  context.configuration.agc.maxShutterSpeed,
 		  context.configuration.agc.minAnalogueGain,
-		  context.configuration.agc.maxAnalogueGain);
+		  context.configuration.agc.maxAnalogueGain,
+		  {});
 
 	resetFrameCount();
 
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index d0337fd0027f..d1b6bb7196f4 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -206,7 +206,7 @@  int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
 	setLimits(context.configuration.sensor.minExposureTime,
 		  context.configuration.sensor.maxExposureTime,
 		  context.configuration.sensor.minAnalogueGain,
-		  context.configuration.sensor.maxAnalogueGain);
+		  context.configuration.sensor.maxAnalogueGain, {});
 
 	resetFrameCount();
 
@@ -590,7 +590,7 @@  void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 		maxAnalogueGain = frameContext.agc.gain;
 	}
 
-	setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain);
+	setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain, {});
 
 	/*
 	 * The Agc algorithm needs to know the effective exposure value that was