[PATCH/RFC] libcamera: Rename "shutter speed" to "exposure time"

Laurent Pinchart laurent.pinchart at ideasonboard.com
Thu Oct 31 11:32:50 CET 2024


On Thu, Oct 31, 2024 at 10:13:51AM +0000, Naushir Patuck wrote:
> On Mon, 28 Oct 2024 at 01:34, Laurent Pinchart wrote:
> >
> > The terms "shutter" and "shutter speed" are used through libcamera to
> > mean "exposure time". This is confusing, both due to "speed" being used
> > as "time" while it should be the inverse (i.e. a maximum speed should
> > correspond to the minimum time), and due to "shutter speed" and
> > "exposure time" being used in different places with the same meaning.
> >
> > To improve clarity of the code base and the documentation, use "exposure
> > time" consistently to replace "shutter speed".
> >
> > I'm sending this patch as an RFC to gather opinions before addressing a
> > few remaining issues, regarding which I'd appreciate feedback as well:
> >
> > - The tuning data for the AgcMeanLuminance helper class still uses a
> >   "shutter" YAML element. I would ideally like to rename that too.
> >
> > - The ExposureModeHelper::splitExposure() function used to document that
> >   it splits "exposure time into shutter time and gain". I have reworded
> >   that to "split exposure into exposure time and gain", but I'm not
> >   entirely happy with the result as "exposure" has a defined meaning in
> >   photography (see https://en.wikipedia.org/wiki/Exposure_(photography))
> >   that is not expressed as a duration. It seems we need a better term
> >   here.
> >
> > - I haven't touched the Raspberry Pi IPA module. David, Naush, would you
> >   accept a rename there too ?
> 
> No objections from us to use either "shutter time" or "exposure time"
> in the RPi IPA as part of this change.  I would suggest leaving the
> tuning JSON files as-is for now though as users will have custom files
> in use.

Thanks for the feedback. I agree about the Raspberry Pi tuning files, it
would be too annoying to rename the YAML elements at this point.

While I have your attention, I'm wondering if we should use "integration
time" instead of "exposure time". The reason is to avoid confusion with
"exposure", which has a defined and different meaning in photography.

> > Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > ---
> >  src/ipa/ipu3/algorithms/agc.cpp         |  26 ++--
> >  src/ipa/ipu3/algorithms/agc.h           |   4 +-
> >  src/ipa/ipu3/ipa_context.cpp            |   8 +-
> >  src/ipa/ipu3/ipa_context.h              |   4 +-
> >  src/ipa/ipu3/ipu3.cpp                   |  10 +-
> >  src/ipa/libipa/agc_mean_luminance.cpp   |  43 +++----
> >  src/ipa/libipa/agc_mean_luminance.h     |   2 +-
> >  src/ipa/libipa/exposure_mode_helper.cpp | 152 ++++++++++++------------
> >  src/ipa/libipa/exposure_mode_helper.h   |  14 +--
> >  src/ipa/rkisp1/algorithms/agc.cpp       |  27 +++--
> >  src/ipa/rkisp1/ipa_context.cpp          |   8 +-
> >  src/ipa/rkisp1/ipa_context.h            |   4 +-
> >  src/ipa/rkisp1/rkisp1.cpp               |  10 +-
> >  src/libcamera/control_ids_core.yaml     |  14 +--
> >  14 files changed, 163 insertions(+), 163 deletions(-)
> >
> > diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
> > index c5f3d8f0ccac..ff0f857d378c 100644
> > --- a/src/ipa/ipu3/algorithms/agc.cpp
> > +++ b/src/ipa/ipu3/algorithms/agc.cpp
> > @@ -33,7 +33,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
> > @@ -51,13 +51,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)
> >  {
> >  }
> >
> > @@ -100,9 +100,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;
> > @@ -115,7 +115,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();
> >
> > @@ -222,20 +222,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 411f4da0704e..890c271b4462 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 917d06541abe..fe455e0715c6 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 c85d1e34ea85..29f38b36a9a3 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 10a8c86d8e64..e82287631146 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 f97ef11771c4..d2d50001e51a 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 =
> > +                       std::vector<uint32_t> exposureTimes =
> >                                 modeValues["shutter"].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";
> >                                 return -EINVAL;
> >                         }
> >
> > -                       if (shutters.empty()) {
> > +                       if (exposureTimes.empty()) {
> >                                 LOG(AgcMeanLuminance, Error)
> >                                         << "Shutter 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,8 +338,8 @@ 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 "shutter" and an array of
> > + * gain values with the key "gain", in this format:
> >   *
> >   * \code{.unparsed}
> >   * algorithms:
> > @@ -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 576d28be8eb0..c41391cb0b73 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 30da0c894044..f235316d3539 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 85c665d7d187..c5be1b6703a8 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 301b7ec26508..40e5a8f481b2 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 14d0c02a2b32..833e2cbb784f 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 e274d9b01e1c..5fc53011d9b4 100644
> > --- a/src/ipa/rkisp1/ipa_context.h
> > +++ b/src/ipa/rkisp1/ipa_context.h
> > @@ -50,8 +50,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 9e161cabdea4..69417b9ec6bf 100644
> > --- a/src/ipa/rkisp1/rkisp1.cpp
> > +++ b/src/ipa/rkisp1/rkisp1.cpp
> > @@ -256,14 +256,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/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml
> > index 1b1bd9507d25..438a5d003750 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
> >
> > base-commit: 80a7ccd3add45eb56fda6f1fb445017ac01fea7a
> > prerequisite-patch-id: 19ba9a578d3e04662488c7189f88ffea94c769fe

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list