@@ -309,14 +309,14 @@ void Agc::setFixedShutter(Duration fixedShutter)
{
fixedShutter_ = fixedShutter;
/* Set this in case someone calls disableAuto() straight after. */
- status_.shutterTime = clipShutter(fixedShutter_);
+ status_.shutterTime = limitShutter(fixedShutter_);
}
void Agc::setFixedAnalogueGain(double fixedAnalogueGain)
{
fixedAnalogueGain_ = fixedAnalogueGain;
/* Set this in case someone calls disableAuto() straight after. */
- status_.analogueGain = fixedAnalogueGain;
+ status_.analogueGain = limitGain(fixedAnalogueGain);
}
void Agc::setMeteringMode(std::string const &meteringModeName)
@@ -342,7 +342,7 @@ void Agc::switchMode(CameraMode const &cameraMode,
housekeepConfig();
- Duration fixedShutter = clipShutter(fixedShutter_);
+ Duration fixedShutter = limitShutter(fixedShutter_);
if (fixedShutter && fixedAnalogueGain_) {
/* We're going to reset the algorithm here with these fixed values. */
@@ -516,7 +516,7 @@ void Agc::housekeepConfig()
{
/* First fetch all the up-to-date settings, so no one else has to do it. */
status_.ev = ev_;
- status_.fixedShutter = clipShutter(fixedShutter_);
+ status_.fixedShutter = limitShutter(fixedShutter_);
status_.fixedAnalogueGain = fixedAnalogueGain_;
status_.flickerPeriod = flickerPeriod_;
LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixedShutter "
@@ -703,7 +703,7 @@ void Agc::computeTargetExposure(double gain)
Duration maxShutter = status_.fixedShutter
? status_.fixedShutter
: exposureMode_->shutter.back();
- maxShutter = clipShutter(maxShutter);
+ maxShutter = limitShutter(maxShutter);
Duration maxTotalExposure =
maxShutter *
(status_.fixedAnalogueGain != 0.0
@@ -803,15 +803,16 @@ void Agc::divideUpExposure()
double analogueGain;
shutterTime = status_.fixedShutter ? status_.fixedShutter
: exposureMode_->shutter[0];
- shutterTime = clipShutter(shutterTime);
+ shutterTime = limitShutter(shutterTime);
analogueGain = status_.fixedAnalogueGain != 0.0 ? status_.fixedAnalogueGain
: exposureMode_->gain[0];
+ analogueGain = limitGain(analogueGain);
if (shutterTime * analogueGain < exposureValue) {
for (unsigned int stage = 1;
stage < exposureMode_->gain.size(); stage++) {
if (!status_.fixedShutter) {
Duration stageShutter =
- clipShutter(exposureMode_->shutter[stage]);
+ limitShutter(exposureMode_->shutter[stage]);
if (stageShutter * analogueGain >= exposureValue) {
shutterTime = exposureValue / analogueGain;
break;
@@ -824,6 +825,7 @@ void Agc::divideUpExposure()
break;
}
analogueGain = exposureMode_->gain[stage];
+ analogueGain = limitGain(analogueGain);
}
}
}
@@ -846,6 +848,7 @@ void Agc::divideUpExposure()
* gain as a side-effect.
*/
analogueGain = std::min(analogueGain, exposureMode_->gain.back());
+ analogueGain = limitGain(analogueGain);
shutterTime = newShutterTime;
}
LOG(RPiAgc, Debug) << "After flicker avoidance, shutter "
@@ -872,13 +875,37 @@ void Agc::writeAndFinish(Metadata *imageMetadata, bool desaturate)
<< " analogue gain " << filtered_.analogueGain;
}
-Duration Agc::clipShutter(Duration shutter)
+Duration Agc::limitShutter(Duration shutter)
{
- if (sensorLimits_.maxShutter)
- shutter = std::min(shutter, sensorLimits_.maxShutter);
+ /*
+ * shutter == 0 is a special case for fixed shutter values, and must pass
+ * through unchanged
+ */
+ if (!shutter)
+ return shutter;
+
+ shutter = std::clamp(shutter, sensorLimits_.minShutter,
+ sensorLimits_.maxShutter);
return shutter;
}
+double Agc::limitGain(double gain) const
+{
+ /*
+ * Only limit the lower bounds of the gain value to what the sensor limits.
+ * The upper bound on analogue gain will be made up with additional digital
+ * gain applied by the ISP.
+ *
+ * gain == 0.0 is a special case for fixed shutter values, and must pass
+ * through unchanged
+ */
+ if (!gain)
+ return gain;
+
+ gain = std::max(gain, sensorLimits_.minAnalogueGain);
+ return gain;
+}
+
/* Register algorithm with the system. */
static Algorithm *create(Controller *controller)
{
@@ -103,7 +103,8 @@ private:
void filterExposure(bool desaturate);
void divideUpExposure();
void writeAndFinish(Metadata *imageMetadata, bool desaturate);
- libcamera::utils::Duration clipShutter(libcamera::utils::Duration shutter);
+ libcamera::utils::Duration limitShutter(libcamera::utils::Duration shutter);
+ double limitGain(double gain) const;
AgcMeteringMode *meteringMode_;
AgcExposureMode *exposureMode_;
AgcConstraintMode *constraintMode_;