| Message ID | 20261109094954.341480-7-barnabas.pocze@ideasonboard.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
Hi Barnabás, Quoting Barnabás Pőcze (2026-11-09 10:49:41) > 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 assertions are added. s/an assertions are/add an assertion/ ? > And the general agc algorithm is adjusted to provide stages for the fallback > mode. > > Note that the `stageGain` initialization has to be adjusted to retrieve the > quantization gain, so that at the end of the loop > > * stageExposureTime > * stageGain > * quantGain > * quantGain2 > > are all up to date for the last stage. > > Closes: https://gitlab.freedesktop.org/camera/libcamera/-/work_items/362 > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Looks good to me. Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com> Best regards, Stefan > --- > src/ipa/libipa/agc.cpp | 7 ++++++- > src/ipa/libipa/exposure_mode_helper.cpp | 27 ++++++++++++------------- > 2 files changed, 19 insertions(+), 15 deletions(-) > > diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp > index 6127859d0f..c1345787f7 100644 > --- a/src/ipa/libipa/agc.cpp > +++ b/src/ipa/libipa/agc.cpp > @@ -463,7 +463,12 @@ void addFallbacks(AgcMeanLuminance::Configuration &config) > if (config.exposureModeHelpers.empty()) > config.exposureModeHelpers.try_emplace( > controls::AeExposureModeNormal, > - std::vector<ExposureModeHelper::Stage>{}); > + std::vector{ > + ExposureModeHelper::Stage{ > + .exposureTime = utils::Duration::max(), > + .gain = std::numeric_limits<double>::max(), > + }, > + }); > } > > } /* namespace */ > diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp > index 4ec31f54c3..5c4242519b 100644 > --- a/src/ipa/libipa/exposure_mode_helper.cpp > +++ b/src/ipa/libipa/exposure_mode_helper.cpp > @@ -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 > @@ -219,6 +220,7 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const > { > ASSERT(maxExposureTime_); > ASSERT(maxGain_); > + ASSERT(!stages_.empty()); > > utils::Duration exposureTime; > double gain; > @@ -240,13 +242,13 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const > exposure / (exposureTime * gain * quantGain) }; > } > > - double stageGain = clampGain(1.0); > - double lastStageGain = stageGain; > + utils::Duration stageExposureTime = {}; > + double lastStageGain = clampGain(1.0); > + double stageGain = {}; > > for (const auto &stage : stages_) { > - utils::Duration stageExposureTime = clampExposureTime(stage.exposureTime, > - &quantGain); > - stageGain = clampGain(stage.gain); > + stageExposureTime = clampExposureTime(stage.exposureTime, &quantGain); > + stageGain = clampGain(stage.gain, &quantGain2); > > /* > * We perform the clamping on both exposure time and gain in > @@ -280,14 +282,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 stageGain 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, which is the maximum allowed. > */ > - exposureTime = clampExposureTime(exposure / stageGain, &quantGain); > - gain = clampGain(exposure / exposureTime, &quantGain2); > + exposureTime = stageExposureTime; > + gain = stageGain; > quantGain *= quantGain2; > > return { exposureTime, gain, quantGain, > -- > 2.56.0 >
diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp index 6127859d0f..c1345787f7 100644 --- a/src/ipa/libipa/agc.cpp +++ b/src/ipa/libipa/agc.cpp @@ -463,7 +463,12 @@ void addFallbacks(AgcMeanLuminance::Configuration &config) if (config.exposureModeHelpers.empty()) config.exposureModeHelpers.try_emplace( controls::AeExposureModeNormal, - std::vector<ExposureModeHelper::Stage>{}); + std::vector{ + ExposureModeHelper::Stage{ + .exposureTime = utils::Duration::max(), + .gain = std::numeric_limits<double>::max(), + }, + }); } } /* namespace */ diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp index 4ec31f54c3..5c4242519b 100644 --- a/src/ipa/libipa/exposure_mode_helper.cpp +++ b/src/ipa/libipa/exposure_mode_helper.cpp @@ -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 @@ -219,6 +220,7 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const { ASSERT(maxExposureTime_); ASSERT(maxGain_); + ASSERT(!stages_.empty()); utils::Duration exposureTime; double gain; @@ -240,13 +242,13 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const exposure / (exposureTime * gain * quantGain) }; } - double stageGain = clampGain(1.0); - double lastStageGain = stageGain; + utils::Duration stageExposureTime = {}; + double lastStageGain = clampGain(1.0); + double stageGain = {}; for (const auto &stage : stages_) { - utils::Duration stageExposureTime = clampExposureTime(stage.exposureTime, - &quantGain); - stageGain = clampGain(stage.gain); + stageExposureTime = clampExposureTime(stage.exposureTime, &quantGain); + stageGain = clampGain(stage.gain, &quantGain2); /* * We perform the clamping on both exposure time and gain in @@ -280,14 +282,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 stageGain 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, which is the maximum allowed. */ - exposureTime = clampExposureTime(exposure / stageGain, &quantGain); - gain = clampGain(exposure / exposureTime, &quantGain2); + exposureTime = stageExposureTime; + gain = stageGain; quantGain *= quantGain2; return { exposureTime, gain, quantGain,