@@ -442,14 +442,19 @@ void fillMissing(AgcMeanLuminance::Configuration &config)
{
/*
* If we don't have any exposure modes in the tuning data we create an
- * ExposureModeHelper using an empty vector of stages. This will result
- * in the ExposureModeHelper simply driving the exposure time as high as
- * possible before touching gain.
+ * ExposureModeHelper using a single stage of effectively unlimited exposure
+ * and gain. This will result in the ExposureModeHelper simply driving the
+ * exposure time as high as possible before touching gain.
*/
if (config.exposureModeHelpers.empty())
config.exposureModeHelpers.try_emplace(
controls::ExposureMaximize,
- std::vector<ExposureModeHelper::Stage>{});
+ std::vector{
+ ExposureModeHelper::Stage{
+ .exposureTime = utils::Duration::max(),
+ .gain = std::numeric_limits<double>::max(),
+ },
+ });
/*
* If the tuning data file contains no constraints then we use the
@@ -84,6 +84,7 @@ ExposureModeHelper::ExposureModeHelper(std::vector<Stage> &&stages)
: stages_(std::move(stages)), lineDuration_(1us), minExposureTime_(0us),
maxExposureTime_(0us), minGain_(0), maxGain_(0), sensorHelper_(nullptr)
{
+ ASSERT(!stages_.empty());
}
/**
@@ -203,8 +204,8 @@ double ExposureModeHelper::clampGain(double gain, double *quantizationGain) cons
* value.
*
* If no combination of exposure time and gain limits is found that meets the
- * required exposure, the helper falls-back to simply maximising the exposure
- * time first, followed by analogue gain, followed by digital gain.
+ * required exposure, then the exposure and gain of the last stage will be used,
+ * and the digital gain will be increased as necessary.
*
* During the calculations the gain missed due to quantization is recorded and
* returned as quantization gain. The quantization gain is not included in the
@@ -280,14 +281,11 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const
}
/*
- * From here on all we can do is max out the exposure time, followed by
- * the analogue gain. If we still haven't achieved the target we send
- * the rest of the exposure time to digital gain. If we were given no
- * stages to use then the default gain of 1.0 is used so that exposure
- * time is maxed before gain is touched at all.
+ * If no stages could satisfy the desired exposure, then use the last
+ * stage's exposure time and gain.
*/
- exposureTime = clampExposureTime(exposure / lastStageGain, &quantGain);
- gain = clampGain(exposure / exposureTime, &quantGain2);
+ exposureTime = clampExposureTime(stages_.back().exposureTime, &quantGain);
+ gain = clampGain(stages_.back().gain, &quantGain2);
quantGain *= quantGain2;
return { exposureTime, gain, quantGain,
Currently `splitExposure()` will raise the exposure and analogue gain above what is specified in the last stage, if the desired exposure could not be reached. This behaviour is different from that of the raspberry pi ipa, and also could be surprising to the user / tuning file creator. So make sure that the exposure time and analogue gain is limited by the last stage, in addition to the runtime controlled upper bound. With this change, at least one stage is required, so an assertion is added in the constructor. Also modify the general agc algorithm to provide stages for the implicitly instantiated "Maximize" mode. Closes: https://gitlab.freedesktop.org/camera/libcamera/-/work_items/362 Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> --- src/ipa/libipa/agc.cpp | 13 +++++++++---- src/ipa/libipa/exposure_mode_helper.cpp | 16 +++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-)