[libcamera-devel] [PATCH 07/10] libcamera: ipa: raspberrypi: agc: Report fixed exposure/gain values during SwitchMode

Naushir Patuck naush at raspberrypi.com
Tue Nov 17 11:56:25 CET 2020


Hi David,

On Mon, 16 Nov 2020 at 16:49, David Plowman <david.plowman at raspberrypi.com>
wrote:

> When an application has specified fixed exposure time and/or gain they
> must be programmed into the sensor immediately, even before the sensor
> has been started. For this to happen they must be written into the
> image metadata when the SwitchMode method is invoked.
>
> We also make the default exposure/gain, when nothing has been set,
> customisable in the tuning file.
>
> Signed-off-by: David Plowman <david.plowman at raspberrypi.com>
>

Reviewed-by: Naushir Patuck <naush at raspberrypi.com>


> ---
>  src/ipa/raspberrypi/controller/rpi/agc.cpp | 74 +++++++++++++++++-----
>  src/ipa/raspberrypi/controller/rpi/agc.hpp |  2 +
>  2 files changed, 60 insertions(+), 16 deletions(-)
>
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> index 6de56def..7c7944e8 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> @@ -147,6 +147,9 @@ void AgcConfig::Read(boost::property_tree::ptree const
> &params)
>         fast_reduce_threshold =
>                 params.get<double>("fast_reduce_threshold", 0.4);
>         base_ev = params.get<double>("base_ev", 1.0);
> +       // Start with quite a low value as ramping up is easier than
> ramping down.
> +       default_exposure_time =
> params.get<double>("default_exposure_time", 1000);
> +       default_analogue_gain =
> params.get<double>("default_analogue_gain", 1.0);
>  }
>
>  Agc::Agc(Controller *controller)
> @@ -222,14 +225,42 @@ void Agc::SetConstraintMode(std::string const
> &constraint_mode_name)
>  void Agc::SwitchMode([[maybe_unused]] CameraMode const &camera_mode,
>                      Metadata *metadata)
>  {
> -       // On a mode switch, it's possible the exposure profile could
> change,
> -       // so we run through the dividing up of exposure/gain again and
> -       // write the results into the metadata we've been given.
> -       if (status_.total_exposure_value) {
> -               housekeepConfig();
> +       housekeepConfig();
> +
> +       if (fixed_shutter_ != 0.0 && fixed_analogue_gain_ != 0.0) {
> +               // We're going to reset the algorithm here with these
> fixed values.
> +
> +               fetchAwbStatus(metadata);
> +               double min_colour_gain = std::min({ awb_.gain_r,
> awb_.gain_g, awb_.gain_b, 1.0 });
> +               assert(min_colour_gain != 0.0);
> +
> +               // This is the equivalent of computeTargetExposure and
> applyDigitalGain.
> +               target_.total_exposure_no_dg = fixed_shutter_ *
> fixed_analogue_gain_;
> +               target_.total_exposure = target_.total_exposure_no_dg /
> min_colour_gain;
> +
> +               // Equivalent of filterExposure. This resets any "history".
> +               filtered_ = target_;
> +
> +               // Equivalent of divideUpExposure.
> +               filtered_.shutter = fixed_shutter_;
> +               filtered_.analogue_gain = fixed_analogue_gain_;
> +       } else if (status_.total_exposure_value) {
> +               // On a mode switch, it's possible the exposure profile
> could change,
> +               // or a fixed exposure/gain might be set so we divide up
> the exposure/
> +               // gain again, but we don't change any target values.
>                 divideUpExposure();
> -               writeAndFinish(metadata, false);
> +       } 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.
> +
> +               // Equivalent of divideUpExposure.
> +               filtered_.shutter = fixed_shutter_ ? fixed_shutter_ :
> config_.default_exposure_time;
> +               filtered_.analogue_gain = fixed_analogue_gain_ ?
> fixed_analogue_gain_ : config_.default_analogue_gain;
>         }
> +
> +       writeAndFinish(metadata, false);
>  }
>
>  void Agc::Prepare(Metadata *image_metadata)
> @@ -475,20 +506,31 @@ void Agc::computeGain(bcm2835_isp_stats *statistics,
> Metadata *image_metadata,
>
>  void Agc::computeTargetExposure(double gain)
>  {
> -       // The statistics reflect the image without digital gain, so the
> final
> -       // total exposure we're aiming for is:
> -       target_.total_exposure = current_.total_exposure_no_dg * gain;
> -       // The final target exposure is also limited to what the exposure
> -       // mode allows.
> -       double max_total_exposure =
> -               (status_.fixed_shutter != 0.0
> +       if (status_.fixed_shutter != 0.0 && status_.fixed_analogue_gain !=
> 0.0) {
> +               // 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/min_colour_gain. Otherwise we'd desaturate channels
> causing
> +               // white to go cyan or magenta.
> +               double min_colour_gain = std::min({ awb_.gain_r,
> awb_.gain_g, awb_.gain_b, 1.0 });
> +               assert(min_colour_gain != 0.0);
> +               target_.total_exposure =
> +                       status_.fixed_shutter *
> status_.fixed_analogue_gain / min_colour_gain;
> +       } else {
> +               // The statistics reflect the image without digital gain,
> so the final
> +               // total exposure we're aiming for is:
> +               target_.total_exposure = current_.total_exposure_no_dg *
> gain;
> +               // The final target exposure is also limited to what the
> exposure
> +               // mode allows.
> +               double max_total_exposure =
> +                       (status_.fixed_shutter != 0.0
>                          ? status_.fixed_shutter
>                          : exposure_mode_->shutter.back()) *
> -               (status_.fixed_analogue_gain != 0.0
> +                       (status_.fixed_analogue_gain != 0.0
>                          ? status_.fixed_analogue_gain
>                          : exposure_mode_->gain.back());
> -       target_.total_exposure = std::min(target_.total_exposure,
> -                                         max_total_exposure);
> +               target_.total_exposure = std::min(target_.total_exposure,
> +                                                 max_total_exposure);
> +       }
>         LOG(RPiAgc, Debug) << "Target total_exposure " <<
> target_.total_exposure;
>  }
>
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp
> b/src/ipa/raspberrypi/controller/rpi/agc.hpp
> index e7ac480f..859a9650 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp
> @@ -60,6 +60,8 @@ struct AgcConfig {
>         std::string default_exposure_mode;
>         std::string default_constraint_mode;
>         double base_ev;
> +       double default_exposure_time;
> +       double default_analogue_gain;
>  };
>
>  class Agc : public AgcAlgorithm
> --
> 2.20.1
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20201117/8c4de84a/attachment-0001.htm>


More information about the libcamera-devel mailing list