diff options
33 files changed, 334 insertions, 327 deletions
diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom index 5986c436..0b92587d 100644 --- a/include/libcamera/ipa/raspberrypi.mojom +++ b/include/libcamera/ipa/raspberrypi.mojom @@ -272,7 +272,7 @@ interface IPARPiEventInterface { * \param[in] delayContext IPA context index used for this request * * This asynchronous event is signalled to the pipeline handler when - * the IPA requires sensor specific controls (e.g. shutter speed, gain, + * the IPA requires sensor specific controls (e.g. exposure time, gain, * blanking) to be applied. */ setDelayedControls(libcamera.ControlList controls, uint32 delayContext); diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 466b3fb3..46669203 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -34,7 +34,7 @@ namespace ipa::ipu3::algorithms { * \class Agc * \brief A mean-based auto-exposure algorithm * - * This algorithm calculates a shutter time and an analogue gain so that the + * This algorithm calculates an exposure time and an analogue gain so that the * average value of the green channel of the brightest 2% of pixels approaches * 0.5. The AWB gains are not used here, and all cells in the grid have the same * weight, like an average-metering case. In this metering mode, the camera uses @@ -52,13 +52,13 @@ LOG_DEFINE_CATEGORY(IPU3Agc) static constexpr double kMinAnalogueGain = 1.0; /* \todo Honour the FrameDurationLimits control instead of hardcoding a limit */ -static constexpr utils::Duration kMaxShutterSpeed = 60ms; +static constexpr utils::Duration kMaxExposureTime = 60ms; /* Histogram constants */ static constexpr uint32_t knumHistogramBins = 256; Agc::Agc() - : minShutterSpeed_(0s), maxShutterSpeed_(0s) + : minExposureTime_(0s), maxExposureTime_(0s) { } @@ -101,9 +101,9 @@ int Agc::configure(IPAContext &context, stride_ = configuration.grid.stride; bdsGrid_ = configuration.grid.bdsGrid; - minShutterSpeed_ = configuration.agc.minShutterSpeed; - maxShutterSpeed_ = std::min(configuration.agc.maxShutterSpeed, - kMaxShutterSpeed); + minExposureTime_ = configuration.agc.minExposureTime; + maxExposureTime_ = std::min(configuration.agc.maxExposureTime, + kMaxExposureTime); minAnalogueGain_ = std::max(configuration.agc.minAnalogueGain, kMinAnalogueGain); maxAnalogueGain_ = configuration.agc.maxAnalogueGain; @@ -116,7 +116,7 @@ int Agc::configure(IPAContext &context, context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first; /* \todo Run this again when FrameDurationLimits is passed in */ - setLimits(minShutterSpeed_, maxShutterSpeed_, minAnalogueGain_, + setLimits(minExposureTime_, maxExposureTime_, minAnalogueGain_, maxAnalogueGain_); resetFrameCount(); @@ -223,20 +223,20 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, double analogueGain = frameContext.sensor.gain; utils::Duration effectiveExposureValue = exposureTime * analogueGain; - utils::Duration shutterTime; + utils::Duration newExposureTime; double aGain, dGain; - std::tie(shutterTime, aGain, dGain) = + std::tie(newExposureTime, aGain, dGain) = calculateNewEv(context.activeState.agc.constraintMode, context.activeState.agc.exposureMode, hist, effectiveExposureValue); LOG(IPU3Agc, Debug) - << "Divided up shutter, analogue gain and digital gain are " - << shutterTime << ", " << aGain << " and " << dGain; + << "Divided up exposure time, analogue gain and digital gain are " + << newExposureTime << ", " << aGain << " and " << dGain; IPAActiveState &activeState = context.activeState; - /* Update the estimated exposure and gain. */ - activeState.agc.exposure = shutterTime / context.configuration.sensor.lineDuration; + /* Update the estimated exposure time and gain. */ + activeState.agc.exposure = newExposureTime / context.configuration.sensor.lineDuration; activeState.agc.gain = aGain; metadata.set(controls::AnalogueGain, frameContext.sensor.gain); diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h index 411f4da0..890c271b 100644 --- a/src/ipa/ipu3/algorithms/agc.h +++ b/src/ipa/ipu3/algorithms/agc.h @@ -42,8 +42,8 @@ private: Histogram parseStatistics(const ipu3_uapi_stats_3a *stats, const ipu3_uapi_grid_config &grid); - utils::Duration minShutterSpeed_; - utils::Duration maxShutterSpeed_; + utils::Duration minExposureTime_; + utils::Duration maxExposureTime_; double minAnalogueGain_; double maxAnalogueGain_; diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp index 917d0654..fe455e07 100644 --- a/src/ipa/ipu3/ipa_context.cpp +++ b/src/ipa/ipu3/ipa_context.cpp @@ -92,11 +92,11 @@ namespace libcamera::ipa::ipu3 { * \var IPASessionConfiguration::agc * \brief AGC parameters configuration of the IPA * - * \var IPASessionConfiguration::agc.minShutterSpeed - * \brief Minimum shutter speed supported with the configured sensor + * \var IPASessionConfiguration::agc.minExposureTime + * \brief Minimum exposure time supported with the configured sensor * - * \var IPASessionConfiguration::agc.maxShutterSpeed - * \brief Maximum shutter speed supported with the configured sensor + * \var IPASessionConfiguration::agc.maxExposureTime + * \brief Maximum exposure time supported with the configured sensor * * \var IPASessionConfiguration::agc.minAnalogueGain * \brief Minimum analogue gain supported with the configured sensor diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index c85d1e34..29f38b36 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -33,8 +33,8 @@ struct IPASessionConfiguration { } af; struct { - utils::Duration minShutterSpeed; - utils::Duration maxShutterSpeed; + utils::Duration minExposureTime; + utils::Duration maxExposureTime; double minAnalogueGain; double maxAnalogueGain; } agc; diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 89c3192c..44c98cbf 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -112,7 +112,7 @@ namespace ipa::ipu3 { * blue gains to apply to generate a neutral grey frame overall. * * AGC is handled by calculating a histogram of the green channel to estimate an - * analogue gain and shutter time which will provide a well exposed frame. A + * analogue gain and exposure time which will provide a well exposed frame. A * low-pass IIR filter is used to smooth the changes to the sensor to reduce * perceivable steps. * @@ -215,13 +215,13 @@ void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls) /* * When the AGC computes the new exposure values for a frame, it needs - * to know the limits for shutter speed and analogue gain. + * to know the limits for exposure time and analogue gain. * As it depends on the sensor, update it with the controls. * - * \todo take VBLANK into account for maximum shutter speed + * \todo take VBLANK into account for maximum exposure time */ - context_.configuration.agc.minShutterSpeed = minExposure * context_.configuration.sensor.lineDuration; - context_.configuration.agc.maxShutterSpeed = maxExposure * context_.configuration.sensor.lineDuration; + context_.configuration.agc.minExposureTime = minExposure * context_.configuration.sensor.lineDuration; + context_.configuration.agc.maxExposureTime = maxExposure * context_.configuration.sensor.lineDuration; context_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain); context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain); } diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index f97ef117..cd175708 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -89,10 +89,10 @@ static constexpr double kDefaultRelativeLuminanceTarget = 0.16; * \class AgcMeanLuminance * \brief A mean-based auto-exposure algorithm * - * This algorithm calculates a shutter time, analogue and digital gain such that - * the normalised mean luminance value of an image is driven towards a target, - * which itself is discovered from tuning data. The algorithm is a two-stage - * process. + * This algorithm calculates an exposure time, analogue and digital gain such + * that the normalised mean luminance value of an image is driven towards a + * target, which itself is discovered from tuning data. The algorithm is a + * two-stage process. * * In the first stage, an initial gain value is derived by iteratively comparing * the gain-adjusted mean luminance across the entire image against a target, @@ -109,7 +109,7 @@ static constexpr double kDefaultRelativeLuminanceTarget = 0.16; * stage is then clamped to the gain from this stage. * * The final gain is used to adjust the effective exposure value of the image, - * and that new exposure value is divided into shutter time, analogue gain and + * and that new exposure value is divided into exposure time, analogue gain and * digital gain according to the selected AeExposureMode. This class uses the * \ref ExposureModeHelper class to assist in that division, and expects the * data needed to initialise that class to be present in tuning data in a @@ -247,27 +247,27 @@ int AgcMeanLuminance::parseExposureModes(const YamlObject &tuningData) return -EINVAL; } - std::vector<uint32_t> shutters = - modeValues["shutter"].getList<uint32_t>().value_or(std::vector<uint32_t>{}); + std::vector<uint32_t> exposureTimes = + modeValues["exposure-time"].getList<uint32_t>().value_or(std::vector<uint32_t>{}); std::vector<double> gains = modeValues["gain"].getList<double>().value_or(std::vector<double>{}); - if (shutters.size() != gains.size()) { + if (exposureTimes.size() != gains.size()) { LOG(AgcMeanLuminance, Error) - << "Shutter and gain array sizes unequal"; + << "Exposure time and gain array sizes unequal"; return -EINVAL; } - if (shutters.empty()) { + if (exposureTimes.empty()) { LOG(AgcMeanLuminance, Error) - << "Shutter and gain arrays are empty"; + << "Exposure time and gain arrays are empty"; return -EINVAL; } std::vector<std::pair<utils::Duration, double>> stages; - for (unsigned int i = 0; i < shutters.size(); i++) { + for (unsigned int i = 0; i < exposureTimes.size(); i++) { stages.push_back({ - std::chrono::microseconds(shutters[i]), + std::chrono::microseconds(exposureTimes[i]), gains[i] }); } @@ -283,7 +283,7 @@ int AgcMeanLuminance::parseExposureModes(const YamlObject &tuningData) /* * 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 shutter as high as + * in the ExposureModeHelper simply driving the exposure time as high as * possible before touching gain. */ if (availableExposureModes.empty()) { @@ -338,18 +338,18 @@ int AgcMeanLuminance::parseExposureModes(const YamlObject &tuningData) * For the AeExposureMode control the data should contain a dictionary called * AeExposureMode containing per-mode setting dictionaries with the key being a * value from \ref controls::AeExposureModeNameValueMap. Each mode dict should - * contain an array of shutter times with the key "shutter" and an array of gain - * values with the key "gain", in this format: + * contain an array of exposure times with the key "exposure-time" and an array + * of gain values with the key "gain", in this format: * * \code{.unparsed} * algorithms: * - Agc: * AeExposureMode: * ExposureNormal: - * shutter: [ 100, 10000, 30000, 60000, 120000 ] + * exposure-time: [ 100, 10000, 30000, 60000, 120000 ] * gain: [ 2.0, 4.0, 6.0, 8.0, 10.0 ] * ExposureShort: - * shutter: [ 100, 10000, 30000, 60000, 120000 ] + * exposure-time: [ 100, 10000, 30000, 60000, 120000 ] * gain: [ 2.0, 4.0, 6.0, 8.0, 10.0 ] * * \endcode @@ -371,20 +371,20 @@ int AgcMeanLuminance::parseTuningData(const YamlObject &tuningData) /** * \brief Set the ExposureModeHelper limits for this class - * \param[in] minShutter Minimum shutter time to allow - * \param[in] maxShutter Maximum shutter time to allow + * \param[in] minExposureTime Minimum exposure time to allow + * \param[in] maxExposureTime Maximum ewposure time to allow * \param[in] minGain Minimum gain to allow * \param[in] maxGain Maximum gain to allow * * This function calls \ref ExposureModeHelper::setLimits() for each * ExposureModeHelper that has been created for this class. */ -void AgcMeanLuminance::setLimits(utils::Duration minShutter, - utils::Duration maxShutter, +void AgcMeanLuminance::setLimits(utils::Duration minExposureTime, + utils::Duration maxExposureTime, double minGain, double maxGain) { for (auto &[id, helper] : exposureModeHelpers_) - helper->setLimits(minShutter, maxShutter, minGain, maxGain); + helper->setLimits(minExposureTime, maxExposureTime, minGain, maxGain); } /** @@ -513,7 +513,8 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) } /** - * \brief Calculate the new exposure value and splut it between shutter time and gain + * \brief Calculate the new exposure value and splut it between exposure time + * and gain * \param[in] constraintModeIndex The index of the current constraint mode * \param[in] exposureModeIndex The index of the current exposure mode * \param[in] yHist A Histogram from the ISP statistics to use in constraining @@ -523,9 +524,9 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) * * Calculate a new exposure value to try to obtain the target. The calculated * exposure value is filtered to prevent rapid changes from frame to frame, and - * divided into shutter time, analogue and digital gain. + * divided into exposure time, analogue and digital gain. * - * \return Tuple of shutter time, analogue gain, and digital gain + * \return Tuple of exposure time, analogue gain, and digital gain */ std::tuple<utils::Duration, double, double> AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index 576d28be..c41391cb 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -44,7 +44,7 @@ public: int parseTuningData(const YamlObject &tuningData); - void setLimits(utils::Duration minShutter, utils::Duration maxShutter, + void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, double minGain, double maxGain); std::map<int32_t, std::vector<AgcConstraint>> constraintModes() diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp index 30da0c89..f235316d 100644 --- a/src/ipa/libipa/exposure_mode_helper.cpp +++ b/src/ipa/libipa/exposure_mode_helper.cpp @@ -14,9 +14,9 @@ * \file exposure_mode_helper.h * \brief Helper class that performs computations relating to exposure * - * AEGC algorithms have a need to split exposure between shutter time, analogue + * AEGC algorithms have a need to split exposure between exposure time, analogue * and digital gain. Multiple implementations do so based on paired stages of - * shutter time and gain limits; provide a helper to avoid duplicating the code. + * exposure time and gain limits; provide a helper to avoid duplicating the code. */ namespace libcamera { @@ -29,24 +29,24 @@ namespace ipa { /** * \class ExposureModeHelper - * \brief Class for splitting exposure into shutter time and total gain + * \brief Class for splitting exposure into exposure time and total gain * * The ExposureModeHelper class provides a standard interface through which an - * AEGC algorithm can divide exposure between shutter time and gain. It is - * configured with a set of shutter time and gain pairs and works by initially - * fixing gain at 1.0 and increasing shutter time up to the shutter time value + * AEGC algorithm can divide exposure between exposure time and gain. It is + * configured with a set of exposure time and gain pairs and works by initially + * fixing gain at 1.0 and increasing exposure time up to the exposure time value * from the first pair in the set in an attempt to meet the required exposure * value. * - * If the required exposure is not achievable by the first shutter time value + * If the required exposure is not achievable by the first exposure time value * alone it ramps gain up to the value from the first pair in the set. If the - * required exposure is still not met it then allows shutter time to ramp up to - * the shutter time value from the second pair in the set, and continues in this + * required exposure is still not met it then allows exposure time to ramp up to + * the exposure time value from the second pair in the set, and continues in this * vein until either the required exposure time is met, or else the hardware's - * shutter time or gain limits are reached. + * exposure time or gain limits are reached. * * This method allows users to strike a balance between a well-exposed image and - * an acceptable frame-rate, as opposed to simply maximising shutter time + * an acceptable frame-rate, as opposed to simply maximising exposure time * followed by gain. The same helpers can be used to perform the latter * operation if needed by passing an empty set of pairs to the initialisation * function. @@ -61,9 +61,9 @@ namespace ipa { /** * \brief Construct an ExposureModeHelper instance - * \param[in] stages The vector of paired shutter time and gain limits + * \param[in] stages The vector of paired exposure time and gain limits * - * The input stages are shutter time and _total_ gain pairs; the gain + * The input stages are exposure time and _total_ gain pairs; the gain * encompasses both analogue and digital gain. * * The vector of stages may be empty. In that case, the helper will simply use @@ -71,46 +71,46 @@ namespace ipa { */ ExposureModeHelper::ExposureModeHelper(const Span<std::pair<utils::Duration, double>> stages) { - minShutter_ = 0us; - maxShutter_ = 0us; + minExposureTime_ = 0us; + maxExposureTime_ = 0us; minGain_ = 0; maxGain_ = 0; for (const auto &[s, g] : stages) { - shutters_.push_back(s); + exposureTimes_.push_back(s); gains_.push_back(g); } } /** - * \brief Set the shutter time and gain limits - * \param[in] minShutter The minimum shutter time supported - * \param[in] maxShutter The maximum shutter time supported + * \brief Set the exposure time and gain limits + * \param[in] minExposureTime The minimum exposure time supported + * \param[in] maxExposureTime The maximum exposure time supported * \param[in] minGain The minimum analogue gain supported * \param[in] maxGain The maximum analogue gain supported * - * This function configures the shutter time and analogue gain limits that need + * This function configures the exposure time and analogue gain limits that need * to be adhered to as the helper divides up exposure. Note that this function * *must* be called whenever those limits change and before splitExposure() is * used. * - * If the algorithm using the helpers needs to indicate that either shutter time + * If the algorithm using the helpers needs to indicate that either exposure time * or analogue gain or both should be fixed it can do so by setting both the * minima and maxima to the same value. */ -void ExposureModeHelper::setLimits(utils::Duration minShutter, - utils::Duration maxShutter, +void ExposureModeHelper::setLimits(utils::Duration minExposureTime, + utils::Duration maxExposureTime, double minGain, double maxGain) { - minShutter_ = minShutter; - maxShutter_ = maxShutter; + minExposureTime_ = minExposureTime; + maxExposureTime_ = maxExposureTime; minGain_ = minGain; maxGain_ = maxGain; } -utils::Duration ExposureModeHelper::clampShutter(utils::Duration shutter) const +utils::Duration ExposureModeHelper::clampExposureTime(utils::Duration exposureTime) const { - return std::clamp(shutter, minShutter_, maxShutter_); + return std::clamp(exposureTime, minExposureTime_, maxExposureTime_); } double ExposureModeHelper::clampGain(double gain) const @@ -119,108 +119,108 @@ double ExposureModeHelper::clampGain(double gain) const } /** - * \brief Split exposure time into shutter time and gain - * \param[in] exposure Exposure time + * \brief Split exposure into exposure time and gain + * \param[in] exposure Exposure value * - * This function divides a given exposure time into shutter time, analogue and - * digital gain by iterating through stages of shutter time and gain limits. At - * each stage the current stage's shutter time limit is multiplied by the + * This function divides a given exposure into exposure time, analogue and + * digital gain by iterating through stages of exposure time and gain limits. + * At each stage the current stage's exposure time limit is multiplied by the * previous stage's gain limit (or 1.0 initially) to see if the combination of - * the two can meet the required exposure time. If they cannot then the current - * stage's shutter time limit is multiplied by the same stage's gain limit to + * the two can meet the required exposure. If they cannot then the current + * stage's exposure time limit is multiplied by the same stage's gain limit to * see if that combination can meet the required exposure time. If they cannot * then the function moves to consider the next stage. * - * When a combination of shutter time and gain _stage_ limits are found that are - * sufficient to meet the required exposure time, the function attempts to - * reduce shutter time as much as possible whilst fixing gain and still meeting - * the exposure time. If a _runtime_ limit prevents shutter time from being - * lowered enough to meet the exposure time with gain fixed at the stage limit, - * gain is also lowered to compensate. + * When a combination of exposure time and gain _stage_ limits are found that + * are sufficient to meet the required exposure, the function attempts to reduce + * exposure time as much as possible whilst fixing gain and still meeting the + * exposure. If a _runtime_ limit prevents exposure time from being lowered + * enough to meet the exposure with gain fixed at the stage limit, gain is also + * lowered to compensate. * - * Once the shutter time and gain values are ascertained, gain is assigned as + * Once the exposure time and gain values are ascertained, gain is assigned as * analogue gain as much as possible, with digital gain only in use if the * maximum analogue gain runtime limit is unable to accommodate the exposure * value. * - * If no combination of shutter time and gain limits is found that meets the - * required exposure time, the helper falls-back to simply maximising the - * shutter time first, followed by analogue gain, followed by digital gain. + * 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. * - * \return Tuple of shutter time, analogue gain, and digital gain + * \return Tuple of exposure time, analogue gain, and digital gain */ std::tuple<utils::Duration, double, double> ExposureModeHelper::splitExposure(utils::Duration exposure) const { - ASSERT(maxShutter_); + ASSERT(maxExposureTime_); ASSERT(maxGain_); bool gainFixed = minGain_ == maxGain_; - bool shutterFixed = minShutter_ == maxShutter_; + bool exposureTimeFixed = minExposureTime_ == maxExposureTime_; /* * There's no point entering the loop if we cannot change either gain - * nor shutter anyway. + * nor exposure time anyway. */ - if (shutterFixed && gainFixed) - return { minShutter_, minGain_, exposure / (minShutter_ * minGain_) }; + if (exposureTimeFixed && gainFixed) + return { minExposureTime_, minGain_, exposure / (minExposureTime_ * minGain_) }; - utils::Duration shutter; + utils::Duration exposureTime; double stageGain = 1.0; double gain; for (unsigned int stage = 0; stage < gains_.size(); stage++) { double lastStageGain = stage == 0 ? 1.0 : clampGain(gains_[stage - 1]); - utils::Duration stageShutter = clampShutter(shutters_[stage]); + utils::Duration stageExposureTime = clampExposureTime(exposureTimes_[stage]); stageGain = clampGain(gains_[stage]); /* - * We perform the clamping on both shutter and gain in case the - * helper has had limits set that prevent those values being - * lowered beyond a certain minimum...this can happen at runtime - * for various reasons and so would not be known when the stage - * limits are initialised. + * We perform the clamping on both exposure time and gain in + * case the helper has had limits set that prevent those values + * being lowered beyond a certain minimum...this can happen at + * runtime for various reasons and so would not be known when + * the stage limits are initialised. */ - if (stageShutter * lastStageGain >= exposure) { - shutter = clampShutter(exposure / clampGain(lastStageGain)); - gain = clampGain(exposure / shutter); + if (stageExposureTime * lastStageGain >= exposure) { + exposureTime = clampExposureTime(exposure / clampGain(lastStageGain)); + gain = clampGain(exposure / exposureTime); - return { shutter, gain, exposure / (shutter * gain) }; + return { exposureTime, gain, exposure / (exposureTime * gain) }; } - if (stageShutter * stageGain >= exposure) { - shutter = clampShutter(exposure / clampGain(stageGain)); - gain = clampGain(exposure / shutter); + if (stageExposureTime * stageGain >= exposure) { + exposureTime = clampExposureTime(exposure / clampGain(stageGain)); + gain = clampGain(exposure / exposureTime); - return { shutter, gain, exposure / (shutter * gain) }; + return { exposureTime, gain, exposure / (exposureTime * gain) }; } } /* - * From here on all we can do is max out the shutter time, followed by + * 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 - * shutter time is maxed before gain is touched at all. + * exposure time is maxed before gain is touched at all. */ - shutter = clampShutter(exposure / clampGain(stageGain)); - gain = clampGain(exposure / shutter); + exposureTime = clampExposureTime(exposure / clampGain(stageGain)); + gain = clampGain(exposure / exposureTime); - return { shutter, gain, exposure / (shutter * gain) }; + return { exposureTime, gain, exposure / (exposureTime * gain) }; } /** - * \fn ExposureModeHelper::minShutter() - * \brief Retrieve the configured minimum shutter time limit set through + * \fn ExposureModeHelper::minExposureTime() + * \brief Retrieve the configured minimum exposure time limit set through * setLimits() - * \return The minShutter_ value + * \return The minExposureTime_ value */ /** - * \fn ExposureModeHelper::maxShutter() - * \brief Retrieve the configured maximum shutter time set through setLimits() - * \return The maxShutter_ value + * \fn ExposureModeHelper::maxExposureTime() + * \brief Retrieve the configured maximum exposure time set through setLimits() + * \return The maxExposureTime_ value */ /** diff --git a/src/ipa/libipa/exposure_mode_helper.h b/src/ipa/libipa/exposure_mode_helper.h index 85c665d7..c5be1b67 100644 --- a/src/ipa/libipa/exposure_mode_helper.h +++ b/src/ipa/libipa/exposure_mode_helper.h @@ -24,26 +24,26 @@ public: ExposureModeHelper(const Span<std::pair<utils::Duration, double>> stages); ~ExposureModeHelper() = default; - void setLimits(utils::Duration minShutter, utils::Duration maxShutter, + void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, double minGain, double maxGain); std::tuple<utils::Duration, double, double> splitExposure(utils::Duration exposure) const; - utils::Duration minShutter() const { return minShutter_; } - utils::Duration maxShutter() const { return maxShutter_; } + utils::Duration minExposureTime() const { return minExposureTime_; } + utils::Duration maxExposureTime() const { return maxExposureTime_; } double minGain() const { return minGain_; } double maxGain() const { return maxGain_; } private: - utils::Duration clampShutter(utils::Duration shutter) const; + utils::Duration clampExposureTime(utils::Duration exposureTime) const; double clampGain(double gain) const; - std::vector<utils::Duration> shutters_; + std::vector<utils::Duration> exposureTimes_; std::vector<double> gains_; - utils::Duration minShutter_; - utils::Duration maxShutter_; + utils::Duration minExposureTime_; + utils::Duration maxExposureTime_; double minGain_; double maxGain_; }; diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 301b7ec2..40e5a8f4 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -183,7 +183,7 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) * except it's computed in the IPA and not here so we'd have to * recompute it. */ - context.activeState.agc.maxFrameDuration = context.configuration.sensor.maxShutterSpeed; + context.activeState.agc.maxFrameDuration = context.configuration.sensor.maxExposureTime; /* * Define the measurement window for AGC as a centered rectangle @@ -194,8 +194,8 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) context.configuration.agc.measureWindow.h_size = 3 * configInfo.outputSize.width / 4; context.configuration.agc.measureWindow.v_size = 3 * configInfo.outputSize.height / 4; - setLimits(context.configuration.sensor.minShutterSpeed, - context.configuration.sensor.maxShutterSpeed, + setLimits(context.configuration.sensor.minExposureTime, + context.configuration.sensor.maxExposureTime, context.configuration.sensor.minAnalogueGain, context.configuration.sensor.maxAnalogueGain); @@ -424,12 +424,12 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, [](uint32_t x) { return x >> 4; }); expMeans_ = { params->ae.exp_mean, context.hw->numAeCells }; - utils::Duration maxShutterSpeed = + utils::Duration maxExposureTime = std::clamp(frameContext.agc.maxFrameDuration, - context.configuration.sensor.minShutterSpeed, - context.configuration.sensor.maxShutterSpeed); - setLimits(context.configuration.sensor.minShutterSpeed, - maxShutterSpeed, + context.configuration.sensor.minExposureTime, + context.configuration.sensor.maxExposureTime); + setLimits(context.configuration.sensor.minExposureTime, + maxExposureTime, context.configuration.sensor.minAnalogueGain, context.configuration.sensor.maxAnalogueGain); @@ -442,20 +442,21 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, double analogueGain = frameContext.sensor.gain; utils::Duration effectiveExposureValue = exposureTime * analogueGain; - utils::Duration shutterTime; + utils::Duration newExposureTime; double aGain, dGain; - std::tie(shutterTime, aGain, dGain) = + std::tie(newExposureTime, aGain, dGain) = calculateNewEv(frameContext.agc.constraintMode, frameContext.agc.exposureMode, hist, effectiveExposureValue); LOG(RkISP1Agc, Debug) - << "Divided up shutter, analogue gain and digital gain are " - << shutterTime << ", " << aGain << " and " << dGain; + << "Divided up exposure time, analogue gain and digital gain are " + << newExposureTime << ", " << aGain << " and " << dGain; IPAActiveState &activeState = context.activeState; /* Update the estimated exposure and gain. */ - activeState.agc.automatic.exposure = shutterTime / context.configuration.sensor.lineDuration; + activeState.agc.automatic.exposure = newExposureTime + / context.configuration.sensor.lineDuration; activeState.agc.automatic.gain = aGain; fillMetadata(context, frameContext, metadata); diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 14d0c02a..833e2cbb 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -78,11 +78,11 @@ namespace libcamera::ipa::rkisp1 { * \var IPASessionConfiguration::sensor * \brief Sensor-specific configuration of the IPA * - * \var IPASessionConfiguration::sensor.minShutterSpeed - * \brief Minimum shutter speed supported with the sensor + * \var IPASessionConfiguration::sensor.minExposureTime + * \brief Minimum exposure time supported with the sensor * - * \var IPASessionConfiguration::sensor.maxShutterSpeed - * \brief Maximum shutter speed supported with the sensor + * \var IPASessionConfiguration::sensor.maxExposureTime + * \brief Maximum exposure time supported with the sensor * * \var IPASessionConfiguration::sensor.minAnalogueGain * \brief Minimum analogue gain supported with the sensor diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 7b93a9e9..0a165c13 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -53,8 +53,8 @@ struct IPASessionConfiguration { } lsc; struct { - utils::Duration minShutterSpeed; - utils::Duration maxShutterSpeed; + utils::Duration minExposureTime; + utils::Duration maxExposureTime; double minAnalogueGain; double maxAnalogueGain; diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index a29dab34..2ffdd99b 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -257,14 +257,14 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig, /* * When the AGC computes the new exposure values for a frame, it needs - * to know the limits for shutter speed and analogue gain. - * As it depends on the sensor, update it with the controls. + * to know the limits for exposure time and analogue gain. As it depends + * on the sensor, update it with the controls. * - * \todo take VBLANK into account for maximum shutter speed + * \todo take VBLANK into account for maximum exposure time */ - context_.configuration.sensor.minShutterSpeed = + context_.configuration.sensor.minExposureTime = minExposure * context_.configuration.sensor.lineDuration; - context_.configuration.sensor.maxShutterSpeed = + context_.configuration.sensor.maxExposureTime = maxExposure * context_.configuration.sensor.lineDuration; context_.configuration.sensor.minAnalogueGain = context_.camHelper->gain(minGain); diff --git a/src/ipa/rpi/cam_helper/cam_helper.cpp b/src/ipa/rpi/cam_helper/cam_helper.cpp index ee5d011f..6493e882 100644 --- a/src/ipa/rpi/cam_helper/cam_helper.cpp +++ b/src/ipa/rpi/cam_helper/cam_helper.cpp @@ -241,7 +241,7 @@ void CamHelper::parseEmbeddedData(Span<const uint8_t> buffer, return; } - deviceStatus.shutterSpeed = parsedDeviceStatus.shutterSpeed; + deviceStatus.exposureTime = parsedDeviceStatus.exposureTime; deviceStatus.analogueGain = parsedDeviceStatus.analogueGain; deviceStatus.frameLength = parsedDeviceStatus.frameLength; deviceStatus.lineLength = parsedDeviceStatus.lineLength; diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp index 91461f7a..ba01153e 100644 --- a/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp +++ b/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp @@ -99,7 +99,7 @@ void CamHelperImx219::populateMetadata(const MdParser::RegisterMap ®isters, deviceStatus.lineLength = lineLengthPckToDuration(registers.at(lineLengthHiReg) * 256 + registers.at(lineLengthLoReg)); - deviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), + deviceStatus.exposureTime = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), deviceStatus.lineLength); deviceStatus.analogueGain = gain(registers.at(gainReg)); deviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg); diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp index 6bd89334..a53c40cd 100644 --- a/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp +++ b/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp @@ -112,7 +112,7 @@ void CamHelperImx477::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m DeviceStatus parsedDeviceStatus; metadata.get("device.status", parsedDeviceStatus); - parsedDeviceStatus.shutterSpeed = deviceStatus.shutterSpeed; + parsedDeviceStatus.exposureTime = deviceStatus.exposureTime; parsedDeviceStatus.frameLength = deviceStatus.frameLength; metadata.set("device.status", parsedDeviceStatus); @@ -180,7 +180,7 @@ void CamHelperImx477::populateMetadata(const MdParser::RegisterMap ®isters, deviceStatus.lineLength = lineLengthPckToDuration(registers.at(lineLengthHiReg) * 256 + registers.at(lineLengthLoReg)); - deviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), + deviceStatus.exposureTime = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), deviceStatus.lineLength); deviceStatus.analogueGain = gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg)); deviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg); diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp index c2de3d40..2ff08653 100644 --- a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp +++ b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp @@ -112,7 +112,7 @@ void CamHelperImx519::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m DeviceStatus parsedDeviceStatus; metadata.get("device.status", parsedDeviceStatus); - parsedDeviceStatus.shutterSpeed = deviceStatus.shutterSpeed; + parsedDeviceStatus.exposureTime = deviceStatus.exposureTime; parsedDeviceStatus.frameLength = deviceStatus.frameLength; metadata.set("device.status", parsedDeviceStatus); @@ -180,7 +180,7 @@ void CamHelperImx519::populateMetadata(const MdParser::RegisterMap ®isters, deviceStatus.lineLength = lineLengthPckToDuration(registers.at(lineLengthHiReg) * 256 + registers.at(lineLengthLoReg)); - deviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), + deviceStatus.exposureTime = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), deviceStatus.lineLength); deviceStatus.analogueGain = gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg)); deviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg); diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp index 63ddb55e..ec83d9fd 100644 --- a/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp +++ b/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp @@ -155,7 +155,7 @@ void CamHelperImx708::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m DeviceStatus parsedDeviceStatus; metadata.get("device.status", parsedDeviceStatus); - parsedDeviceStatus.shutterSpeed = deviceStatus.shutterSpeed; + parsedDeviceStatus.exposureTime = deviceStatus.exposureTime; parsedDeviceStatus.frameLength = deviceStatus.frameLength; metadata.set("device.status", parsedDeviceStatus); @@ -255,7 +255,7 @@ void CamHelperImx708::populateMetadata(const MdParser::RegisterMap ®isters, deviceStatus.lineLength = lineLengthPckToDuration(registers.at(lineLengthHiReg) * 256 + registers.at(lineLengthLoReg)); - deviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), + deviceStatus.exposureTime = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg), deviceStatus.lineLength); deviceStatus.analogueGain = gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg)); deviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg); diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp index 468f36a8..5fce17e6 100644 --- a/src/ipa/rpi/common/ipa_base.cpp +++ b/src/ipa/rpi/common/ipa_base.cpp @@ -224,7 +224,7 @@ int32_t IpaBase::configure(const IPACameraSensorInfo &sensorInfo, const ConfigPa /* Supply initial values for gain and exposure. */ AgcStatus agcStatus; - agcStatus.shutterTime = defaultExposureTime; + agcStatus.exposureTime = defaultExposureTime; agcStatus.analogueGain = defaultAnalogueGain; applyAGC(&agcStatus, ctrls); @@ -265,8 +265,8 @@ int32_t IpaBase::configure(const IPACameraSensorInfo &sensorInfo, const ConfigPa static_cast<float>(mode_.maxAnalogueGain)); ctrlMap[&controls::ExposureTime] = - ControlInfo(static_cast<int32_t>(mode_.minShutter.get<std::micro>()), - static_cast<int32_t>(mode_.maxShutter.get<std::micro>())); + ControlInfo(static_cast<int32_t>(mode_.minExposureTime.get<std::micro>()), + static_cast<int32_t>(mode_.maxExposureTime.get<std::micro>())); /* Declare colour processing related controls for non-mono sensors. */ if (!monoSensor_) @@ -299,11 +299,11 @@ void IpaBase::start(const ControlList &controls, StartResult *result) /* SwitchMode may supply updated exposure/gain values to use. */ AgcStatus agcStatus; - agcStatus.shutterTime = 0.0s; + agcStatus.exposureTime = 0.0s; agcStatus.analogueGain = 0.0; metadata.get("agc.status", agcStatus); - if (agcStatus.shutterTime && agcStatus.analogueGain) { + if (agcStatus.exposureTime && agcStatus.analogueGain) { ControlList ctrls(sensorCtrls_); applyAGC(&agcStatus, ctrls); result->controls = std::move(ctrls); @@ -599,7 +599,7 @@ void IpaBase::setMode(const IPACameraSensorInfo &sensorInfo) mode_.sensitivity = helper_->getModeSensitivity(mode_); const ControlInfo &gainCtrl = sensorCtrls_.at(V4L2_CID_ANALOGUE_GAIN); - const ControlInfo &shutterCtrl = sensorCtrls_.at(V4L2_CID_EXPOSURE); + const ControlInfo &exposureTimeCtrl = sensorCtrls_.at(V4L2_CID_EXPOSURE); mode_.minAnalogueGain = helper_->gain(gainCtrl.min().get<int32_t>()); mode_.maxAnalogueGain = helper_->gain(gainCtrl.max().get<int32_t>()); @@ -610,11 +610,15 @@ void IpaBase::setMode(const IPACameraSensorInfo &sensorInfo) */ helper_->setCameraMode(mode_); - /* Shutter speed is calculated based on the limits of the frame durations. */ - mode_.minShutter = helper_->exposure(shutterCtrl.min().get<int32_t>(), mode_.minLineLength); - mode_.maxShutter = Duration::max(); - helper_->getBlanking(mode_.maxShutter, - mode_.minFrameDuration, mode_.maxFrameDuration); + /* + * Exposure time is calculated based on the limits of the frame + * durations. + */ + mode_.minExposureTime = helper_->exposure(exposureTimeCtrl.min().get<int32_t>(), + mode_.minLineLength); + mode_.maxExposureTime = Duration::max(); + helper_->getBlanking(mode_.maxExposureTime, mode_.minFrameDuration, + mode_.maxFrameDuration); } void IpaBase::setCameraTimeoutValue() @@ -788,7 +792,7 @@ void IpaBase::applyControls(const ControlList &controls) } /* The control provides units of microseconds. */ - agc->setFixedShutter(0, ctrl.second.get<int32_t>() * 1.0us); + agc->setFixedExposureTime(0, ctrl.second.get<int32_t>() * 1.0us); libcameraMetadata_.set(controls::ExposureTime, ctrl.second.get<int32_t>()); break; @@ -1281,7 +1285,7 @@ void IpaBase::fillDeviceStatus(const ControlList &sensorControls, unsigned int i int32_t hblank = sensorControls.get(V4L2_CID_HBLANK).get<int32_t>(); deviceStatus.lineLength = helper_->hblankToLineLength(hblank); - deviceStatus.shutterSpeed = helper_->exposure(exposureLines, deviceStatus.lineLength); + deviceStatus.exposureTime = helper_->exposure(exposureLines, deviceStatus.lineLength); deviceStatus.analogueGain = helper_->gain(gainCode); deviceStatus.frameLength = mode_.height + vblank; @@ -1308,7 +1312,7 @@ void IpaBase::reportMetadata(unsigned int ipaContext) DeviceStatus *deviceStatus = rpiMetadata.getLocked<DeviceStatus>("device.status"); if (deviceStatus) { libcameraMetadata_.set(controls::ExposureTime, - deviceStatus->shutterSpeed.get<std::micro>()); + deviceStatus->exposureTime.get<std::micro>()); libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogueGain); libcameraMetadata_.set(controls::FrameDuration, helper_->exposure(deviceStatus->frameLength, deviceStatus->lineLength).get<std::micro>()); @@ -1459,15 +1463,15 @@ void IpaBase::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDu /* * Calculate the maximum exposure time possible for the AGC to use. - * getBlanking() will update maxShutter with the largest exposure + * getBlanking() will update maxExposureTime with the largest exposure * value possible. */ - Duration maxShutter = Duration::max(); - helper_->getBlanking(maxShutter, minFrameDuration_, maxFrameDuration_); + Duration maxExposureTime = Duration::max(); + helper_->getBlanking(maxExposureTime, minFrameDuration_, maxFrameDuration_); RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.getAlgorithm("agc")); - agc->setMaxShutter(maxShutter); + agc->setMaxExposureTime(maxExposureTime); } void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls) @@ -1484,14 +1488,14 @@ void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls) gainCode = std::clamp<int32_t>(gainCode, minGainCode, maxGainCode); /* getBlanking might clip exposure time to the fps limits. */ - Duration exposure = agcStatus->shutterTime; + Duration exposure = agcStatus->exposureTime; auto [vblank, hblank] = helper_->getBlanking(exposure, minFrameDuration_, maxFrameDuration_); int32_t exposureLines = helper_->exposureLines(exposure, helper_->hblankToLineLength(hblank)); LOG(IPARPI, Debug) << "Applying AGC Exposure: " << exposure - << " (Shutter lines: " << exposureLines << ", AGC requested " - << agcStatus->shutterTime << ") Gain: " + << " (Exposure lines: " << exposureLines << ", AGC requested " + << agcStatus->exposureTime << ") Gain: " << agcStatus->analogueGain << " (Gain Code: " << gainCode << ")"; diff --git a/src/ipa/rpi/controller/agc_algorithm.h b/src/ipa/rpi/controller/agc_algorithm.h index 1132de7e..c9782857 100644 --- a/src/ipa/rpi/controller/agc_algorithm.h +++ b/src/ipa/rpi/controller/agc_algorithm.h @@ -23,9 +23,9 @@ public: virtual std::vector<double> const &getWeights() const = 0; virtual void setEv(unsigned int channel, double ev) = 0; virtual void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) = 0; - virtual void setFixedShutter(unsigned int channel, - libcamera::utils::Duration fixedShutter) = 0; - virtual void setMaxShutter(libcamera::utils::Duration maxShutter) = 0; + virtual void setFixedExposureTime(unsigned int channel, + libcamera::utils::Duration fixedExposureTime) = 0; + virtual void setMaxExposureTime(libcamera::utils::Duration maxExposureTime) = 0; virtual void setFixedAnalogueGain(unsigned int channel, double fixedAnalogueGain) = 0; virtual void setMeteringMode(std::string const &meteringModeName) = 0; virtual void setExposureMode(std::string const &exposureModeName) = 0; diff --git a/src/ipa/rpi/controller/agc_status.h b/src/ipa/rpi/controller/agc_status.h index c7c87b83..9308b156 100644 --- a/src/ipa/rpi/controller/agc_status.h +++ b/src/ipa/rpi/controller/agc_status.h @@ -28,7 +28,7 @@ struct AgcStatus { libcamera::utils::Duration totalExposureValue; /* value for all exposure and gain for this image */ libcamera::utils::Duration targetExposureValue; /* (unfiltered) target total exposure AGC is aiming for */ - libcamera::utils::Duration shutterTime; + libcamera::utils::Duration exposureTime; double analogueGain; std::string exposureMode; std::string constraintMode; @@ -36,7 +36,7 @@ struct AgcStatus { double ev; libcamera::utils::Duration flickerPeriod; int floatingRegionEnable; - libcamera::utils::Duration fixedShutter; + libcamera::utils::Duration fixedExposureTime; double fixedAnalogueGain; unsigned int channel; HdrStatus hdr; diff --git a/src/ipa/rpi/controller/camera_mode.h b/src/ipa/rpi/controller/camera_mode.h index 4fdb5b85..61162b32 100644 --- a/src/ipa/rpi/controller/camera_mode.h +++ b/src/ipa/rpi/controller/camera_mode.h @@ -50,9 +50,9 @@ struct CameraMode { double sensitivity; /* pixel clock rate */ uint64_t pixelRate; - /* Mode specific shutter speed limits */ - libcamera::utils::Duration minShutter; - libcamera::utils::Duration maxShutter; + /* Mode specific exposure time limits */ + libcamera::utils::Duration minExposureTime; + libcamera::utils::Duration maxExposureTime; /* Mode specific analogue gain limits */ double minAnalogueGain; double maxAnalogueGain; diff --git a/src/ipa/rpi/controller/device_status.cpp b/src/ipa/rpi/controller/device_status.cpp index 68100137..1695764d 100644 --- a/src/ipa/rpi/controller/device_status.cpp +++ b/src/ipa/rpi/controller/device_status.cpp @@ -10,7 +10,7 @@ using namespace libcamera; /* for the Duration operator<< overload */ std::ostream &operator<<(std::ostream &out, const DeviceStatus &d) { - out << "Exposure: " << d.shutterSpeed + out << "Exposure time: " << d.exposureTime << " Frame length: " << d.frameLength << " Line length: " << d.lineLength << " Gain: " << d.analogueGain; diff --git a/src/ipa/rpi/controller/device_status.h b/src/ipa/rpi/controller/device_status.h index 518f15b5..b1792035 100644 --- a/src/ipa/rpi/controller/device_status.h +++ b/src/ipa/rpi/controller/device_status.h @@ -12,21 +12,21 @@ #include <libcamera/base/utils.h> /* - * Definition of "device metadata" which stores things like shutter time and + * Definition of "device metadata" which stores things like exposure time and * analogue gain that downstream control algorithms will want to know. */ struct DeviceStatus { DeviceStatus() - : shutterSpeed(std::chrono::seconds(0)), frameLength(0), + : exposureTime(std::chrono::seconds(0)), frameLength(0), lineLength(std::chrono::seconds(0)), analogueGain(0.0) { } friend std::ostream &operator<<(std::ostream &out, const DeviceStatus &d); - /* time shutter is open */ - libcamera::utils::Duration shutterSpeed; + /* time the image is exposed */ + libcamera::utils::Duration exposureTime; /* frame length given in number of lines */ uint32_t frameLength; /* line length for the current frame */ diff --git a/src/ipa/rpi/controller/rpi/agc.cpp b/src/ipa/rpi/controller/rpi/agc.cpp index fcf7aec9..c48fdf15 100644 --- a/src/ipa/rpi/controller/rpi/agc.cpp +++ b/src/ipa/rpi/controller/rpi/agc.cpp @@ -127,21 +127,21 @@ void Agc::setFlickerPeriod(Duration flickerPeriod) data.channel.setFlickerPeriod(flickerPeriod); } -void Agc::setMaxShutter(Duration maxShutter) +void Agc::setMaxExposureTime(Duration maxExposureTime) { /* Frame durations will be the same across all channels too. */ for (auto &data : channelData_) - data.channel.setMaxShutter(maxShutter); + data.channel.setMaxExposureTime(maxExposureTime); } -void Agc::setFixedShutter(unsigned int channelIndex, Duration fixedShutter) +void Agc::setFixedExposureTime(unsigned int channelIndex, Duration fixedExposureTime) { if (checkChannel(channelIndex)) return; - LOG(RPiAgc, Debug) << "setFixedShutter " << fixedShutter + LOG(RPiAgc, Debug) << "setFixedExposureTime " << fixedExposureTime << " for channel " << channelIndex; - channelData_[channelIndex].channel.setFixedShutter(fixedShutter); + channelData_[channelIndex].channel.setFixedExposureTime(fixedExposureTime); } void Agc::setFixedAnalogueGain(unsigned int channelIndex, double fixedAnalogueGain) diff --git a/src/ipa/rpi/controller/rpi/agc.h b/src/ipa/rpi/controller/rpi/agc.h index 5d056f02..3aca000b 100644 --- a/src/ipa/rpi/controller/rpi/agc.h +++ b/src/ipa/rpi/controller/rpi/agc.h @@ -32,9 +32,9 @@ public: std::vector<double> const &getWeights() const override; void setEv(unsigned int channel, double ev) override; void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) override; - void setMaxShutter(libcamera::utils::Duration maxShutter) override; - void setFixedShutter(unsigned int channelIndex, - libcamera::utils::Duration fixedShutter) override; + void setMaxExposureTime(libcamera::utils::Duration maxExposureTime) override; + void setFixedExposureTime(unsigned int channelIndex, + libcamera::utils::Duration fixedExposureTime) override; void setFixedAnalogueGain(unsigned int channelIndex, double fixedAnalogueGain) override; void setMeteringMode(std::string const &meteringModeName) override; diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp index 8583f4f3..14335943 100644 --- a/src/ipa/rpi/controller/rpi/agc_channel.cpp +++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp @@ -67,7 +67,7 @@ int AgcExposureMode::read(const libcamera::YamlObject ¶ms) auto value = params["shutter"].getList<double>(); if (!value) return -EINVAL; - std::transform(value->begin(), value->end(), std::back_inserter(shutter), + std::transform(value->begin(), value->end(), std::back_inserter(exposureTime), [](double v) { return v * 1us; }); value = params["gain"].getList<double>(); @@ -75,13 +75,13 @@ int AgcExposureMode::read(const libcamera::YamlObject ¶ms) return -EINVAL; gain = std::move(*value); - if (shutter.size() < 2 || gain.size() < 2) { + if (exposureTime.size() < 2 || gain.size() < 2) { LOG(RPiAgc, Error) << "AgcExposureMode: must have at least two entries in exposure profile"; return -EINVAL; } - if (shutter.size() != gain.size()) { + if (exposureTime.size() != gain.size()) { LOG(RPiAgc, Error) << "AgcExposureMode: expect same number of exposure and gain entries in exposure profile"; return -EINVAL; @@ -262,7 +262,7 @@ int AgcConfig::read(const libcamera::YamlObject ¶ms) } AgcChannel::ExposureValues::ExposureValues() - : shutter(0s), analogueGain(0), + : exposureTime(0s), analogueGain(0), totalExposure(0s), totalExposureNoDG(0s) { } @@ -271,7 +271,7 @@ AgcChannel::AgcChannel() : meteringMode_(nullptr), exposureMode_(nullptr), constraintMode_(nullptr), frameCount_(0), lockCount_(0), lastTargetExposure_(0s), ev_(1.0), flickerPeriod_(0s), - maxShutter_(0s), fixedShutter_(0s), fixedAnalogueGain_(0.0) + maxExposureTime_(0s), fixedExposureTime_(0s), fixedAnalogueGain_(0.0) { /* Set AWB default values in case early frames have no updates in metadata. */ awb_.gainR = 1.0; @@ -312,31 +312,31 @@ int AgcChannel::read(const libcamera::YamlObject ¶ms, exposureMode_ = &config_.exposureModes[exposureModeName_]; constraintModeName_ = config_.defaultConstraintMode; constraintMode_ = &config_.constraintModes[constraintModeName_]; - /* Set up the "last shutter/gain" values, in case AGC starts "disabled". */ - status_.shutterTime = config_.defaultExposureTime; + /* Set up the "last exposure time/gain" values, in case AGC starts "disabled". */ + status_.exposureTime = config_.defaultExposureTime; status_.analogueGain = config_.defaultAnalogueGain; return 0; } void AgcChannel::disableAuto() { - fixedShutter_ = status_.shutterTime; + fixedExposureTime_ = status_.exposureTime; fixedAnalogueGain_ = status_.analogueGain; } void AgcChannel::enableAuto() { - fixedShutter_ = 0s; + fixedExposureTime_ = 0s; fixedAnalogueGain_ = 0; } unsigned int AgcChannel::getConvergenceFrames() const { /* - * If shutter and gain have been explicitly set, there is no + * If exposure time and gain have been explicitly set, there is no * convergence to happen, so no need to drop any frames - return zero. */ - if (fixedShutter_ && fixedAnalogueGain_) + if (fixedExposureTime_ && fixedAnalogueGain_) return 0; else return config_.convergenceFrames; @@ -364,16 +364,16 @@ void AgcChannel::setFlickerPeriod(Duration flickerPeriod) flickerPeriod_ = flickerPeriod; } -void AgcChannel::setMaxShutter(Duration maxShutter) +void AgcChannel::setMaxExposureTime(Duration maxExposureTime) { - maxShutter_ = maxShutter; + maxExposureTime_ = maxExposureTime; } -void AgcChannel::setFixedShutter(Duration fixedShutter) +void AgcChannel::setFixedExposureTime(Duration fixedExposureTime) { - fixedShutter_ = fixedShutter; + fixedExposureTime_ = fixedExposureTime; /* Set this in case someone calls disableAuto() straight after. */ - status_.shutterTime = limitShutter(fixedShutter_); + status_.exposureTime = limitExposureTime(fixedExposureTime_); } void AgcChannel::setFixedAnalogueGain(double fixedAnalogueGain) @@ -413,22 +413,22 @@ void AgcChannel::switchMode(CameraMode const &cameraMode, double lastSensitivity = mode_.sensitivity; mode_ = cameraMode; - Duration fixedShutter = limitShutter(fixedShutter_); - if (fixedShutter && fixedAnalogueGain_) { + Duration fixedExposureTime = limitExposureTime(fixedExposureTime_); + if (fixedExposureTime && fixedAnalogueGain_) { /* We're going to reset the algorithm here with these fixed values. */ fetchAwbStatus(metadata); double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 }); ASSERT(minColourGain != 0.0); /* This is the equivalent of computeTargetExposure and applyDigitalGain. */ - target_.totalExposureNoDG = fixedShutter_ * fixedAnalogueGain_; + target_.totalExposureNoDG = fixedExposureTime_ * fixedAnalogueGain_; target_.totalExposure = target_.totalExposureNoDG / minColourGain; /* Equivalent of filterExposure. This resets any "history". */ filtered_ = target_; /* Equivalent of divideUpExposure. */ - filtered_.shutter = fixedShutter; + filtered_.exposureTime = fixedExposureTime; filtered_.analogueGain = fixedAnalogueGain_; } else if (status_.totalExposureValue) { /* @@ -450,14 +450,15 @@ void AgcChannel::switchMode(CameraMode const &cameraMode, divideUpExposure(); } else { /* - * We come through here on startup, when at least one of the shutter - * or gain has not been fixed. We must still write those values out so - * that they will be applied immediately. We supply some arbitrary defaults - * for any that weren't set. + * We come through here on startup, when at least one of the + * exposure time or gain has not been fixed. We must still + * write those values out so that they will be applied + * immediately. We supply some arbitrary defaults for any that + * weren't set. */ /* Equivalent of divideUpExposure. */ - filtered_.shutter = fixedShutter ? fixedShutter : config_.defaultExposureTime; + filtered_.exposureTime = fixedExposureTime ? fixedExposureTime : config_.defaultExposureTime; filtered_.analogueGain = fixedAnalogueGain_ ? fixedAnalogueGain_ : config_.defaultAnalogueGain; } @@ -483,7 +484,7 @@ void AgcChannel::prepare(Metadata *imageMetadata) /* Process has run, so we have meaningful values. */ DeviceStatus deviceStatus; if (imageMetadata->get("device.status", deviceStatus) == 0) { - Duration actualExposure = deviceStatus.shutterSpeed * + Duration actualExposure = deviceStatus.exposureTime * deviceStatus.analogueGain; if (actualExposure) { double digitalGain = totalExposureValue / actualExposure; @@ -537,7 +538,7 @@ void AgcChannel::process(StatisticsPtr &stats, DeviceStatus const &deviceStatus, */ bool desaturate = applyDigitalGain(gain, targetY, channelBound); /* - * The last thing is to divide up the exposure value into a shutter time + * The last thing is to divide up the exposure value into a exposure time * and analogue gain, according to the current exposure mode. */ divideUpExposure(); @@ -553,7 +554,7 @@ bool AgcChannel::updateLockStatus(DeviceStatus const &deviceStatus) const double resetMargin = 1.5; /* Add 200us to the exposure time error to allow for line quantisation. */ - Duration exposureError = lastDeviceStatus_.shutterSpeed * errorFactor + 200us; + Duration exposureError = lastDeviceStatus_.exposureTime * errorFactor + 200us; double gainError = lastDeviceStatus_.analogueGain * errorFactor; Duration targetError = lastTargetExposure_ * errorFactor; @@ -562,15 +563,15 @@ bool AgcChannel::updateLockStatus(DeviceStatus const &deviceStatus) * the values we keep requesting may be unachievable. For this reason * we only insist that we're close to values in the past few frames. */ - if (deviceStatus.shutterSpeed > lastDeviceStatus_.shutterSpeed - exposureError && - deviceStatus.shutterSpeed < lastDeviceStatus_.shutterSpeed + exposureError && + if (deviceStatus.exposureTime > lastDeviceStatus_.exposureTime - exposureError && + deviceStatus.exposureTime < lastDeviceStatus_.exposureTime + exposureError && deviceStatus.analogueGain > lastDeviceStatus_.analogueGain - gainError && deviceStatus.analogueGain < lastDeviceStatus_.analogueGain + gainError && status_.targetExposureValue > lastTargetExposure_ - targetError && status_.targetExposureValue < lastTargetExposure_ + targetError) lockCount_ = std::min(lockCount_ + 1, maxLockCount); - else if (deviceStatus.shutterSpeed < lastDeviceStatus_.shutterSpeed - resetMargin * exposureError || - deviceStatus.shutterSpeed > lastDeviceStatus_.shutterSpeed + resetMargin * exposureError || + else if (deviceStatus.exposureTime < lastDeviceStatus_.exposureTime - resetMargin * exposureError || + deviceStatus.exposureTime > lastDeviceStatus_.exposureTime + resetMargin * exposureError || deviceStatus.analogueGain < lastDeviceStatus_.analogueGain - resetMargin * gainError || deviceStatus.analogueGain > lastDeviceStatus_.analogueGain + resetMargin * gainError || status_.targetExposureValue < lastTargetExposure_ - resetMargin * targetError || @@ -588,11 +589,11 @@ void AgcChannel::housekeepConfig() { /* First fetch all the up-to-date settings, so no one else has to do it. */ status_.ev = ev_; - status_.fixedShutter = limitShutter(fixedShutter_); + status_.fixedExposureTime = limitExposureTime(fixedExposureTime_); status_.fixedAnalogueGain = fixedAnalogueGain_; status_.flickerPeriod = flickerPeriod_; - LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixedShutter " - << status_.fixedShutter << " fixedAnalogueGain " + LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixedExposureTime " + << status_.fixedExposureTime << " fixedAnalogueGain " << status_.fixedAnalogueGain; /* * Make sure the "mode" pointers point to the up-to-date things, if @@ -636,10 +637,10 @@ void AgcChannel::housekeepConfig() void AgcChannel::fetchCurrentExposure(DeviceStatus const &deviceStatus) { - current_.shutter = deviceStatus.shutterSpeed; + current_.exposureTime = deviceStatus.exposureTime; current_.analogueGain = deviceStatus.analogueGain; current_.totalExposure = 0s; /* this value is unused */ - current_.totalExposureNoDG = current_.shutter * current_.analogueGain; + current_.totalExposureNoDG = current_.exposureTime * current_.analogueGain; } void AgcChannel::fetchAwbStatus(Metadata *imageMetadata) @@ -777,17 +778,17 @@ void AgcChannel::computeGain(StatisticsPtr &statistics, Metadata *imageMetadata, void AgcChannel::computeTargetExposure(double gain) { - if (status_.fixedShutter && status_.fixedAnalogueGain) { + if (status_.fixedExposureTime && status_.fixedAnalogueGain) { /* - * When ag and shutter are both fixed, we need to drive the - * total exposure so that we end up with a digital gain of at least - * 1/minColourGain. Otherwise we'd desaturate channels causing - * white to go cyan or magenta. + * When analogue gain and exposure time are both fixed, we need + * to drive the total exposure so that we end up with a digital + * gain of at least 1/minColourGain. Otherwise we'd desaturate + * channels causing white to go cyan or magenta. */ double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 }); ASSERT(minColourGain != 0.0); target_.totalExposure = - status_.fixedShutter * status_.fixedAnalogueGain / minColourGain; + status_.fixedExposureTime * status_.fixedAnalogueGain / minColourGain; } else { /* * The statistics reflect the image without digital gain, so the final @@ -795,12 +796,12 @@ void AgcChannel::computeTargetExposure(double gain) */ target_.totalExposure = current_.totalExposureNoDG * gain; /* The final target exposure is also limited to what the exposure mode allows. */ - Duration maxShutter = status_.fixedShutter - ? status_.fixedShutter - : exposureMode_->shutter.back(); - maxShutter = limitShutter(maxShutter); + Duration maxExposureTime = status_.fixedExposureTime + ? status_.fixedExposureTime + : exposureMode_->exposureTime.back(); + maxExposureTime = limitExposureTime(maxExposureTime); Duration maxTotalExposure = - maxShutter * + maxExposureTime * (status_.fixedAnalogueGain != 0.0 ? status_.fixedAnalogueGain : exposureMode_->gain.back()); @@ -884,11 +885,12 @@ void AgcChannel::filterExposure() double stableRegion = config_.stableRegion; /* - * AGC adapts instantly if both shutter and gain are directly specified - * or we're in the startup phase. Also disable the stable region, because we want - * to reflect any user exposure/gain updates, however small. + * AGC adapts instantly if both exposure time and gain are directly + * specified or we're in the startup phase. Also disable the stable + * region, because we want to reflect any user exposure/gain updates, + * however small. */ - if ((status_.fixedShutter && status_.fixedAnalogueGain) || + if ((status_.fixedExposureTime && status_.fixedAnalogueGain) || frameCount_ <= config_.startupFrames) { speed = 1.0; stableRegion = 0.0; @@ -916,34 +918,34 @@ void AgcChannel::filterExposure() void AgcChannel::divideUpExposure() { /* - * Sending the fixed shutter/gain cases through the same code may seem - * unnecessary, but it will make more sense when extend this to cover - * variable aperture. + * Sending the fixed exposure time/gain cases through the same code may + * seem unnecessary, but it will make more sense when extend this to + * cover variable aperture. */ Duration exposureValue = filtered_.totalExposureNoDG; - Duration shutterTime; + Duration exposureTime; double analogueGain; - shutterTime = status_.fixedShutter ? status_.fixedShutter - : exposureMode_->shutter[0]; - shutterTime = limitShutter(shutterTime); + exposureTime = status_.fixedExposureTime ? status_.fixedExposureTime + : exposureMode_->exposureTime[0]; + exposureTime = limitExposureTime(exposureTime); analogueGain = status_.fixedAnalogueGain != 0.0 ? status_.fixedAnalogueGain : exposureMode_->gain[0]; analogueGain = limitGain(analogueGain); - if (shutterTime * analogueGain < exposureValue) { + if (exposureTime * analogueGain < exposureValue) { for (unsigned int stage = 1; stage < exposureMode_->gain.size(); stage++) { - if (!status_.fixedShutter) { - Duration stageShutter = - limitShutter(exposureMode_->shutter[stage]); - if (stageShutter * analogueGain >= exposureValue) { - shutterTime = exposureValue / analogueGain; + if (!status_.fixedExposureTime) { + Duration stageExposureTime = + limitExposureTime(exposureMode_->exposureTime[stage]); + if (stageExposureTime * analogueGain >= exposureValue) { + exposureTime = exposureValue / analogueGain; break; } - shutterTime = stageShutter; + exposureTime = stageExposureTime; } if (status_.fixedAnalogueGain == 0.0) { - if (exposureMode_->gain[stage] * shutterTime >= exposureValue) { - analogueGain = exposureValue / shutterTime; + if (exposureMode_->gain[stage] * exposureTime >= exposureValue) { + analogueGain = exposureValue / exposureTime; break; } analogueGain = exposureMode_->gain[stage]; @@ -951,18 +953,19 @@ void AgcChannel::divideUpExposure() } } } - LOG(RPiAgc, Debug) << "Divided up shutter and gain are " << shutterTime << " and " - << analogueGain; + LOG(RPiAgc, Debug) + << "Divided up exposure time and gain are " << exposureTime + << " and " << analogueGain; /* - * Finally adjust shutter time for flicker avoidance (require both - * shutter and gain not to be fixed). + * Finally adjust exposure time for flicker avoidance (require both + * exposure time and gain not to be fixed). */ - if (!status_.fixedShutter && !status_.fixedAnalogueGain && + if (!status_.fixedExposureTime && !status_.fixedAnalogueGain && status_.flickerPeriod) { - int flickerPeriods = shutterTime / status_.flickerPeriod; + int flickerPeriods = exposureTime / status_.flickerPeriod; if (flickerPeriods) { - Duration newShutterTime = flickerPeriods * status_.flickerPeriod; - analogueGain *= shutterTime / newShutterTime; + Duration newExposureTime = flickerPeriods * status_.flickerPeriod; + analogueGain *= exposureTime / newExposureTime; /* * We should still not allow the ag to go over the * largest value in the exposure mode. Note that this @@ -971,12 +974,12 @@ void AgcChannel::divideUpExposure() */ analogueGain = std::min(analogueGain, exposureMode_->gain.back()); analogueGain = limitGain(analogueGain); - shutterTime = newShutterTime; + exposureTime = newExposureTime; } - LOG(RPiAgc, Debug) << "After flicker avoidance, shutter " - << shutterTime << " gain " << analogueGain; + LOG(RPiAgc, Debug) << "After flicker avoidance, exposure time " + << exposureTime << " gain " << analogueGain; } - filtered_.shutter = shutterTime; + filtered_.exposureTime = exposureTime; filtered_.analogueGain = analogueGain; } @@ -984,7 +987,7 @@ void AgcChannel::writeAndFinish(Metadata *imageMetadata, bool desaturate) { status_.totalExposureValue = filtered_.totalExposure; status_.targetExposureValue = desaturate ? 0s : target_.totalExposure; - status_.shutterTime = filtered_.shutter; + status_.exposureTime = filtered_.exposureTime; status_.analogueGain = filtered_.analogueGain; /* * Write to metadata as well, in case anyone wants to update the camera @@ -993,32 +996,32 @@ void AgcChannel::writeAndFinish(Metadata *imageMetadata, bool desaturate) imageMetadata->set("agc.status", status_); LOG(RPiAgc, Debug) << "Output written, total exposure requested is " << filtered_.totalExposure; - LOG(RPiAgc, Debug) << "Camera exposure update: shutter time " << filtered_.shutter + LOG(RPiAgc, Debug) << "Camera exposure update: exposure time " << filtered_.exposureTime << " analogue gain " << filtered_.analogueGain; } -Duration AgcChannel::limitShutter(Duration shutter) +Duration AgcChannel::limitExposureTime(Duration exposureTime) { /* - * shutter == 0 is a special case for fixed shutter values, and must pass - * through unchanged + * exposureTime == 0 is a special case for fixed exposure time values, + * and must pass through unchanged. */ - if (!shutter) - return shutter; + if (!exposureTime) + return exposureTime; - shutter = std::clamp(shutter, mode_.minShutter, maxShutter_); - return shutter; + exposureTime = std::clamp(exposureTime, mode_.minExposureTime, maxExposureTime_); + return exposureTime; } double AgcChannel::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. + * 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 + * gain == 0.0 is a special case for fixed exposure time values, and + * must pass through unchanged. */ if (!gain) return gain; diff --git a/src/ipa/rpi/controller/rpi/agc_channel.h b/src/ipa/rpi/controller/rpi/agc_channel.h index 58368889..734e5efd 100644 --- a/src/ipa/rpi/controller/rpi/agc_channel.h +++ b/src/ipa/rpi/controller/rpi/agc_channel.h @@ -30,7 +30,7 @@ struct AgcMeteringMode { }; struct AgcExposureMode { - std::vector<libcamera::utils::Duration> shutter; + std::vector<libcamera::utils::Duration> exposureTime; std::vector<double> gain; int read(const libcamera::YamlObject ¶ms); }; @@ -90,8 +90,8 @@ public: std::vector<double> const &getWeights() const; void setEv(double ev); void setFlickerPeriod(libcamera::utils::Duration flickerPeriod); - void setMaxShutter(libcamera::utils::Duration maxShutter); - void setFixedShutter(libcamera::utils::Duration fixedShutter); + void setMaxExposureTime(libcamera::utils::Duration maxExposureTime); + void setFixedExposureTime(libcamera::utils::Duration fixedExposureTime); void setFixedAnalogueGain(double fixedAnalogueGain); void setMeteringMode(std::string const &meteringModeName); void setExposureMode(std::string const &exposureModeName); @@ -117,7 +117,7 @@ private: bool applyDigitalGain(double gain, double targetY, bool channelBound); void divideUpExposure(); void writeAndFinish(Metadata *imageMetadata, bool desaturate); - libcamera::utils::Duration limitShutter(libcamera::utils::Duration shutter); + libcamera::utils::Duration limitExposureTime(libcamera::utils::Duration exposureTime); double limitGain(double gain) const; AgcMeteringMode *meteringMode_; AgcExposureMode *exposureMode_; @@ -128,7 +128,7 @@ private: struct ExposureValues { ExposureValues(); - libcamera::utils::Duration shutter; + libcamera::utils::Duration exposureTime; double analogueGain; libcamera::utils::Duration totalExposure; libcamera::utils::Duration totalExposureNoDG; /* without digital gain */ @@ -146,8 +146,8 @@ private: std::string constraintModeName_; double ev_; libcamera::utils::Duration flickerPeriod_; - libcamera::utils::Duration maxShutter_; - libcamera::utils::Duration fixedShutter_; + libcamera::utils::Duration maxExposureTime_; + libcamera::utils::Duration fixedExposureTime_; double fixedAnalogueGain_; }; diff --git a/src/ipa/rpi/controller/rpi/lux.cpp b/src/ipa/rpi/controller/rpi/lux.cpp index 652d85d7..27b89a8f 100644 --- a/src/ipa/rpi/controller/rpi/lux.cpp +++ b/src/ipa/rpi/controller/rpi/lux.cpp @@ -40,7 +40,7 @@ int Lux::read(const libcamera::YamlObject ¶ms) auto value = params["reference_shutter_speed"].get<double>(); if (!value) return -EINVAL; - referenceShutterSpeed_ = *value * 1.0us; + referenceExposureTime_ = *value * 1.0us; value = params["reference_gain"].get<double>(); if (!value) @@ -82,11 +82,11 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata) double currentAperture = deviceStatus.aperture.value_or(currentAperture_); double currentY = stats->yHist.interQuantileMean(0, 1); double gainRatio = referenceGain_ / currentGain; - double shutterSpeedRatio = - referenceShutterSpeed_ / deviceStatus.shutterSpeed; + double exposureTimeRatio = + referenceExposureTime_ / deviceStatus.exposureTime; double apertureRatio = referenceAperture_ / currentAperture; double yRatio = currentY * (65536 / stats->yHist.bins()) / referenceY_; - double estimatedLux = shutterSpeedRatio * gainRatio * + double estimatedLux = exposureTimeRatio * gainRatio * apertureRatio * apertureRatio * yRatio * referenceLux_; LuxStatus status; diff --git a/src/ipa/rpi/controller/rpi/lux.h b/src/ipa/rpi/controller/rpi/lux.h index 89f441fc..da007fe9 100644 --- a/src/ipa/rpi/controller/rpi/lux.h +++ b/src/ipa/rpi/controller/rpi/lux.h @@ -32,7 +32,7 @@ private: * These values define the conditions of the reference image, against * which we compare the new image. */ - libcamera::utils::Duration referenceShutterSpeed_; + libcamera::utils::Duration referenceExposureTime_; double referenceGain_; double referenceAperture_; /* units of 1/f */ double referenceY_; /* out of 65536 */ diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index d34a2d06..d45cf8e5 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -102,7 +102,7 @@ controls: Specify an exposure mode for the AE algorithm to use. The exposure modes specify how the desired total exposure is divided - between the shutter time and the sensor's analogue gain. They are + between the exposure time and the sensor's analogue gain. They are platform specific, and not all exposure modes may be supported. enum: - name: ExposureNormal @@ -135,8 +135,7 @@ controls: - ExposureTime: type: int32_t description: | - Exposure time (shutter speed) for the frame applied in the sensor - device. + Exposure time for the frame applied in the sensor device. This value is specified in micro-seconds. @@ -463,14 +462,13 @@ controls: values to be the same. Setting both values to 0 reverts to using the camera defaults. - The maximum frame duration provides the absolute limit to the shutter - speed computed by the AE algorithm and it overrides any exposure mode + The maximum frame duration provides the absolute limit to the exposure + time computed by the AE algorithm and it overrides any exposure mode setting specified with controls::AeExposureMode. Similarly, when a manual exposure time is set through controls::ExposureTime, it also gets clipped to the limits set by this control. When reported in - metadata, the control expresses the minimum and maximum frame - durations used after being clipped to the sensor provided frame - duration limits. + metadata, the control expresses the minimum and maximum frame durations + used after being clipped to the sensor provided frame duration limits. \sa AeExposureMode \sa ExposureTime diff --git a/utils/tuning/libtuning/modules/agc/rkisp1.py b/utils/tuning/libtuning/modules/agc/rkisp1.py index 7147028a..1a4dbe7b 100644 --- a/utils/tuning/libtuning/modules/agc/rkisp1.py +++ b/utils/tuning/libtuning/modules/agc/rkisp1.py @@ -47,9 +47,9 @@ class AGCRkISP1(AGC): } def _generate_exposure_modes(self) -> dict: - normal = {'shutter': [100, 10000, 30000, 60000, 120000], + normal = {'exposure-time': [100, 10000, 30000, 60000, 120000], 'gain': [2.0, 4.0, 6.0, 6.0, 6.0]} - short = {'shutter': [100, 5000, 10000, 20000, 120000], + short = {'exposure-time': [100, 5000, 10000, 20000, 120000], 'gain': [2.0, 4.0, 6.0, 6.0, 6.0]} return {'ExposureNormal': normal, 'ExposureShort': short} |