@@ -181,7 +181,7 @@ int AgcMeanLuminance::parseRelativeLuminanceTarget(const YamlObject &tuningData)
return 0;
}
-void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)
+int AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)
{
for (const auto &[boundName, content] : modeDict.asDict()) {
if (boundName != "upper" && boundName != "lower") {
@@ -194,10 +194,27 @@ void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)
AgcConstraint::Bound bound = static_cast<AgcConstraint::Bound>(idx);
double qLo = content["qLo"].get<double>().value_or(0.98);
double qHi = content["qHi"].get<double>().value_or(1.0);
- double yTarget =
- content["yTarget"].getList<double>().value_or(std::vector<double>{ 0.5 }).at(0);
+ auto &target = content["yTarget"];
+ Pwl yTarget;
+ if (target.isValue()) {
+ auto v = target.get<double>();
+ if (!v) {
+ LOG(AgcMeanLuminance, Error)
+ << "Failed to parse single value yTarget";
+ return -EINVAL;
+ }
+ yTarget.append(0, *v);
+ } else {
+ auto v = target.get<Pwl>();
+ if (!v) {
+ LOG(AgcMeanLuminance, Error)
+ << "Failed to parse PWL based yTarget";
+ return -EINVAL;
+ }
+ yTarget.swap(*v);
+ }
- AgcConstraint constraint = { bound, qLo, qHi, yTarget };
+ AgcConstraint constraint = { bound, qLo, qHi, std::move(yTarget) };
if (!constraintModes_.count(id))
constraintModes_[id] = {};
@@ -207,6 +224,8 @@ void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)
else
constraintModes_[id].insert(constraintModes_[id].begin(), constraint);
}
+
+ return 0;
}
int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)
@@ -229,8 +248,11 @@ int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)
return -EINVAL;
}
- parseConstraint(modeDict,
- AeConstraintModeNameValueMap.at(modeName));
+ int ret = parseConstraint(modeDict,
+ AeConstraintModeNameValueMap.at(modeName));
+ if (ret)
+ return ret;
+
availableConstraintModes.push_back(
AeConstraintModeNameValueMap.at(modeName));
}
@@ -247,7 +269,7 @@ int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)
AgcConstraint::Bound::Lower,
0.98,
1.0,
- 0.5
+ { 0.0, 0.5 }
};
constraintModes_[controls::ConstraintNormal].insert(
@@ -360,8 +382,9 @@ void AgcMeanLuminance::configure(utils::Duration lineDuration,
* the data in a specific format; the Agc algorithm's tuning data should contain
* a dictionary called AeConstraintMode containing per-mode setting dictionaries
* with the key being a value from \ref controls::AeConstraintModeNameValueMap.
- * Each mode dict may contain either a "lower" or "upper" key or both, for
- * example:
+ * The yTarget can either be provided as single value or as array in which case
+ * it is interpreted as a PWL mapping lux levels to yTarget values. Each mode
+ * dict may contain either a "lower" or "upper" key or both, for example:
*
* \code{.unparsed}
* algorithms:
@@ -380,7 +403,7 @@ void AgcMeanLuminance::configure(utils::Duration lineDuration,
* upper:
* qLo: 0.98
* qHi: 1.0
- * yTarget: 0.8
+ * yTarget: [ 100, 0.8, 20000, 0.5 ]
*
* \endcode
*
@@ -536,8 +559,15 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,
const Histogram &hist,
double gain)
{
- auto applyConstraint = [&gain, &hist](const AgcConstraint &constraint) {
- double newGain = constraint.yTarget * hist.bins() /
+ auto applyConstraint = [this, &gain, &hist](const AgcConstraint &constraint) {
+ double lux = lux_;
+
+ if (relativeLuminanceTarget_.size() > 1 && lux_ == 0)
+ lux = kDefaultLuxLevel;
+
+ double target = constraint.yTarget.eval(
+ constraint.yTarget.domain().clamp(lux));
+ double newGain = target * hist.bins() /
hist.interQuantileMean(constraint.qLo, constraint.qHi);
if (constraint.bound == AgcConstraint::Bound::Lower &&
@@ -40,7 +40,7 @@ public:
Bound bound;
double qLo;
double qHi;
- double yTarget;
+ Pwl yTarget;
};
void configure(utils::Duration lineDuration, const CameraSensorHelper *sensorHelper);
@@ -88,8 +88,7 @@ public:
private:
virtual double estimateLuminance(const double gain) const = 0;
int parseRelativeLuminanceTarget(const YamlObject &tuningData);
-
- void parseConstraint(const YamlObject &modeDict, int32_t id);
+ int parseConstraint(const YamlObject &modeDict, int32_t id);
int parseConstraintModes(const YamlObject &tuningData);
int parseExposureModes(const YamlObject &tuningData);
double estimateInitialGain() const;
@@ -175,7 +175,8 @@ int WideDynamicRange::configure(IPAContext &context,
constraint.bound = AgcMeanLuminance::AgcConstraint::Bound::Upper;
constraint.qHi = 1.0;
constraint.qLo = 1.0 - exposureConstraintMaxBrightPixels_;
- constraint.yTarget = exposureConstraintY_;
+ constraint.yTarget.clear();
+ constraint.yTarget.append(0, exposureConstraintY_);
return 0;
}
The yTarget loading code is broken and works neither for plain values nor for arrays of values to form a PWL. Fix this by supporting both cases. If a list is provided in the tuning file construct a PWL, otherwise construct a single point PWL with the given value. Fixes: 24247a12c7d3 ("ipa: libipa: Add AgcMeanLuminance base class") Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> --- src/ipa/libipa/agc_mean_luminance.cpp | 54 +++++++++++++++++++++------ src/ipa/libipa/agc_mean_luminance.h | 5 +-- src/ipa/rkisp1/algorithms/wdr.cpp | 3 +- 3 files changed, 46 insertions(+), 16 deletions(-)