mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-15 16:35:06 +03:00
ipa: raspberrypi: Pass the maximum allowable shutter speed into the AGC
In order to provide an optimal split between shutter speed and gain, the AGC must know the maximum allowable shutter speed, as limited by the maximum frame duration (either application provided or the default). Add a new API function, SetMaxShutter, to the AgcAlgorithm class. The IPA provides the maximum shutter speed for AGC calculations. This applies to both the manual and auto AGC modes. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
362301b131
commit
47d243c44a
4 changed files with 48 additions and 15 deletions
|
@ -19,6 +19,7 @@ public:
|
||||||
virtual void SetEv(double ev) = 0;
|
virtual void SetEv(double ev) = 0;
|
||||||
virtual void SetFlickerPeriod(double flicker_period) = 0;
|
virtual void SetFlickerPeriod(double flicker_period) = 0;
|
||||||
virtual void SetFixedShutter(double fixed_shutter) = 0; // microseconds
|
virtual void SetFixedShutter(double fixed_shutter) = 0; // microseconds
|
||||||
|
virtual void SetMaxShutter(double max_shutter) = 0; // microseconds
|
||||||
virtual void SetFixedAnalogueGain(double fixed_analogue_gain) = 0;
|
virtual void SetFixedAnalogueGain(double fixed_analogue_gain) = 0;
|
||||||
virtual void SetMeteringMode(std::string const &metering_mode_name) = 0;
|
virtual void SetMeteringMode(std::string const &metering_mode_name) = 0;
|
||||||
virtual void SetExposureMode(std::string const &exposure_mode_name) = 0;
|
virtual void SetExposureMode(std::string const &exposure_mode_name) = 0;
|
||||||
|
|
|
@ -157,7 +157,7 @@ Agc::Agc(Controller *controller)
|
||||||
frame_count_(0), lock_count_(0),
|
frame_count_(0), lock_count_(0),
|
||||||
last_target_exposure_(0.0),
|
last_target_exposure_(0.0),
|
||||||
ev_(1.0), flicker_period_(0.0),
|
ev_(1.0), flicker_period_(0.0),
|
||||||
fixed_shutter_(0), fixed_analogue_gain_(0.0)
|
max_shutter_(0), fixed_shutter_(0), fixed_analogue_gain_(0.0)
|
||||||
{
|
{
|
||||||
memset(&awb_, 0, sizeof(awb_));
|
memset(&awb_, 0, sizeof(awb_));
|
||||||
// Setting status_.total_exposure_value_ to zero initially tells us
|
// Setting status_.total_exposure_value_ to zero initially tells us
|
||||||
|
@ -227,11 +227,16 @@ void Agc::SetFlickerPeriod(double flicker_period)
|
||||||
flicker_period_ = flicker_period;
|
flicker_period_ = flicker_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Agc::SetMaxShutter(double max_shutter)
|
||||||
|
{
|
||||||
|
max_shutter_ = max_shutter;
|
||||||
|
}
|
||||||
|
|
||||||
void Agc::SetFixedShutter(double fixed_shutter)
|
void Agc::SetFixedShutter(double fixed_shutter)
|
||||||
{
|
{
|
||||||
fixed_shutter_ = fixed_shutter;
|
fixed_shutter_ = fixed_shutter;
|
||||||
// Set this in case someone calls Pause() straight after.
|
// Set this in case someone calls Pause() straight after.
|
||||||
status_.shutter_time = fixed_shutter;
|
status_.shutter_time = clipShutter(fixed_shutter_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Agc::SetFixedAnalogueGain(double fixed_analogue_gain)
|
void Agc::SetFixedAnalogueGain(double fixed_analogue_gain)
|
||||||
|
@ -261,7 +266,8 @@ void Agc::SwitchMode([[maybe_unused]] CameraMode const &camera_mode,
|
||||||
{
|
{
|
||||||
housekeepConfig();
|
housekeepConfig();
|
||||||
|
|
||||||
if (fixed_shutter_ != 0.0 && fixed_analogue_gain_ != 0.0) {
|
double fixed_shutter = clipShutter(fixed_shutter_);
|
||||||
|
if (fixed_shutter != 0.0 && fixed_analogue_gain_ != 0.0) {
|
||||||
// We're going to reset the algorithm here with these fixed values.
|
// We're going to reset the algorithm here with these fixed values.
|
||||||
|
|
||||||
fetchAwbStatus(metadata);
|
fetchAwbStatus(metadata);
|
||||||
|
@ -269,14 +275,14 @@ void Agc::SwitchMode([[maybe_unused]] CameraMode const &camera_mode,
|
||||||
ASSERT(min_colour_gain != 0.0);
|
ASSERT(min_colour_gain != 0.0);
|
||||||
|
|
||||||
// This is the equivalent of computeTargetExposure and applyDigitalGain.
|
// This is the equivalent of computeTargetExposure and applyDigitalGain.
|
||||||
target_.total_exposure_no_dg = fixed_shutter_ * fixed_analogue_gain_;
|
target_.total_exposure_no_dg = fixed_shutter * fixed_analogue_gain_;
|
||||||
target_.total_exposure = target_.total_exposure_no_dg / min_colour_gain;
|
target_.total_exposure = target_.total_exposure_no_dg / min_colour_gain;
|
||||||
|
|
||||||
// Equivalent of filterExposure. This resets any "history".
|
// Equivalent of filterExposure. This resets any "history".
|
||||||
filtered_ = target_;
|
filtered_ = target_;
|
||||||
|
|
||||||
// Equivalent of divideUpExposure.
|
// Equivalent of divideUpExposure.
|
||||||
filtered_.shutter = fixed_shutter_;
|
filtered_.shutter = fixed_shutter;
|
||||||
filtered_.analogue_gain = fixed_analogue_gain_;
|
filtered_.analogue_gain = fixed_analogue_gain_;
|
||||||
} else if (status_.total_exposure_value) {
|
} else if (status_.total_exposure_value) {
|
||||||
// On a mode switch, it's possible the exposure profile could change,
|
// On a mode switch, it's possible the exposure profile could change,
|
||||||
|
@ -290,7 +296,7 @@ void Agc::SwitchMode([[maybe_unused]] CameraMode const &camera_mode,
|
||||||
// for any that weren't set.
|
// for any that weren't set.
|
||||||
|
|
||||||
// Equivalent of divideUpExposure.
|
// Equivalent of divideUpExposure.
|
||||||
filtered_.shutter = fixed_shutter_ ? fixed_shutter_ : config_.default_exposure_time;
|
filtered_.shutter = fixed_shutter ? fixed_shutter : config_.default_exposure_time;
|
||||||
filtered_.analogue_gain = fixed_analogue_gain_ ? fixed_analogue_gain_ : config_.default_analogue_gain;
|
filtered_.analogue_gain = fixed_analogue_gain_ ? fixed_analogue_gain_ : config_.default_analogue_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +409,7 @@ void Agc::housekeepConfig()
|
||||||
{
|
{
|
||||||
// First fetch all the up-to-date settings, so no one else has to do it.
|
// First fetch all the up-to-date settings, so no one else has to do it.
|
||||||
status_.ev = ev_;
|
status_.ev = ev_;
|
||||||
status_.fixed_shutter = fixed_shutter_;
|
status_.fixed_shutter = clipShutter(fixed_shutter_);
|
||||||
status_.fixed_analogue_gain = fixed_analogue_gain_;
|
status_.fixed_analogue_gain = fixed_analogue_gain_;
|
||||||
status_.flicker_period = flicker_period_;
|
status_.flicker_period = flicker_period_;
|
||||||
LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixed_shutter "
|
LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixed_shutter "
|
||||||
|
@ -582,13 +588,15 @@ void Agc::computeTargetExposure(double gain)
|
||||||
target_.total_exposure = current_.total_exposure_no_dg * gain;
|
target_.total_exposure = current_.total_exposure_no_dg * gain;
|
||||||
// The final target exposure is also limited to what the exposure
|
// The final target exposure is also limited to what the exposure
|
||||||
// mode allows.
|
// mode allows.
|
||||||
|
double max_shutter = status_.fixed_shutter != 0.0
|
||||||
|
? status_.fixed_shutter
|
||||||
|
: exposure_mode_->shutter.back();
|
||||||
|
max_shutter = clipShutter(max_shutter);
|
||||||
double max_total_exposure =
|
double max_total_exposure =
|
||||||
(status_.fixed_shutter != 0.0
|
max_shutter *
|
||||||
? status_.fixed_shutter
|
|
||||||
: exposure_mode_->shutter.back()) *
|
|
||||||
(status_.fixed_analogue_gain != 0.0
|
(status_.fixed_analogue_gain != 0.0
|
||||||
? status_.fixed_analogue_gain
|
? status_.fixed_analogue_gain
|
||||||
: exposure_mode_->gain.back());
|
: exposure_mode_->gain.back());
|
||||||
target_.total_exposure = std::min(target_.total_exposure,
|
target_.total_exposure = std::min(target_.total_exposure,
|
||||||
max_total_exposure);
|
max_total_exposure);
|
||||||
}
|
}
|
||||||
|
@ -671,6 +679,7 @@ void Agc::divideUpExposure()
|
||||||
shutter_time = status_.fixed_shutter != 0.0
|
shutter_time = status_.fixed_shutter != 0.0
|
||||||
? status_.fixed_shutter
|
? status_.fixed_shutter
|
||||||
: exposure_mode_->shutter[0];
|
: exposure_mode_->shutter[0];
|
||||||
|
shutter_time = clipShutter(shutter_time);
|
||||||
analogue_gain = status_.fixed_analogue_gain != 0.0
|
analogue_gain = status_.fixed_analogue_gain != 0.0
|
||||||
? status_.fixed_analogue_gain
|
? status_.fixed_analogue_gain
|
||||||
: exposure_mode_->gain[0];
|
: exposure_mode_->gain[0];
|
||||||
|
@ -678,14 +687,15 @@ void Agc::divideUpExposure()
|
||||||
for (unsigned int stage = 1;
|
for (unsigned int stage = 1;
|
||||||
stage < exposure_mode_->gain.size(); stage++) {
|
stage < exposure_mode_->gain.size(); stage++) {
|
||||||
if (status_.fixed_shutter == 0.0) {
|
if (status_.fixed_shutter == 0.0) {
|
||||||
if (exposure_mode_->shutter[stage] *
|
double stage_shutter =
|
||||||
analogue_gain >=
|
clipShutter(exposure_mode_->shutter[stage]);
|
||||||
|
if (stage_shutter * analogue_gain >=
|
||||||
exposure_value) {
|
exposure_value) {
|
||||||
shutter_time =
|
shutter_time =
|
||||||
exposure_value / analogue_gain;
|
exposure_value / analogue_gain;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
shutter_time = exposure_mode_->shutter[stage];
|
shutter_time = stage_shutter;
|
||||||
}
|
}
|
||||||
if (status_.fixed_analogue_gain == 0.0) {
|
if (status_.fixed_analogue_gain == 0.0) {
|
||||||
if (exposure_mode_->gain[stage] *
|
if (exposure_mode_->gain[stage] *
|
||||||
|
@ -740,6 +750,13 @@ void Agc::writeAndFinish(Metadata *image_metadata, bool desaturate)
|
||||||
<< " analogue gain " << filtered_.analogue_gain;
|
<< " analogue gain " << filtered_.analogue_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Agc::clipShutter(double shutter)
|
||||||
|
{
|
||||||
|
if (max_shutter_)
|
||||||
|
shutter = std::min(shutter, max_shutter_);
|
||||||
|
return shutter;
|
||||||
|
}
|
||||||
|
|
||||||
// Register algorithm with the system.
|
// Register algorithm with the system.
|
||||||
static Algorithm *Create(Controller *controller)
|
static Algorithm *Create(Controller *controller)
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,6 +78,7 @@ public:
|
||||||
unsigned int GetConvergenceFrames() const override;
|
unsigned int GetConvergenceFrames() const override;
|
||||||
void SetEv(double ev) override;
|
void SetEv(double ev) override;
|
||||||
void SetFlickerPeriod(double flicker_period) override;
|
void SetFlickerPeriod(double flicker_period) override;
|
||||||
|
void SetMaxShutter(double max_shutter) override; // microseconds
|
||||||
void SetFixedShutter(double fixed_shutter) override; // microseconds
|
void SetFixedShutter(double fixed_shutter) override; // microseconds
|
||||||
void SetFixedAnalogueGain(double fixed_analogue_gain) override;
|
void SetFixedAnalogueGain(double fixed_analogue_gain) override;
|
||||||
void SetMeteringMode(std::string const &metering_mode_name) override;
|
void SetMeteringMode(std::string const &metering_mode_name) override;
|
||||||
|
@ -100,6 +101,7 @@ private:
|
||||||
void filterExposure(bool desaturate);
|
void filterExposure(bool desaturate);
|
||||||
void divideUpExposure();
|
void divideUpExposure();
|
||||||
void writeAndFinish(Metadata *image_metadata, bool desaturate);
|
void writeAndFinish(Metadata *image_metadata, bool desaturate);
|
||||||
|
double clipShutter(double shutter);
|
||||||
AgcMeteringMode *metering_mode_;
|
AgcMeteringMode *metering_mode_;
|
||||||
AgcExposureMode *exposure_mode_;
|
AgcExposureMode *exposure_mode_;
|
||||||
AgcConstraintMode *constraint_mode_;
|
AgcConstraintMode *constraint_mode_;
|
||||||
|
@ -126,6 +128,7 @@ private:
|
||||||
std::string constraint_mode_name_;
|
std::string constraint_mode_name_;
|
||||||
double ev_;
|
double ev_;
|
||||||
double flicker_period_;
|
double flicker_period_;
|
||||||
|
double max_shutter_;
|
||||||
double fixed_shutter_;
|
double fixed_shutter_;
|
||||||
double fixed_analogue_gain_;
|
double fixed_analogue_gain_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1065,6 +1065,18 @@ void IPARPi::applyFrameDurations(double minFrameDuration, double maxFrameDuratio
|
||||||
libcameraMetadata_.set(controls::FrameDurations,
|
libcameraMetadata_.set(controls::FrameDurations,
|
||||||
{ static_cast<int64_t>(minFrameDuration_),
|
{ static_cast<int64_t>(minFrameDuration_),
|
||||||
static_cast<int64_t>(maxFrameDuration_) });
|
static_cast<int64_t>(maxFrameDuration_) });
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the maximum exposure time possible for the AGC to use.
|
||||||
|
* GetVBlanking() will update maxShutter with the largest exposure
|
||||||
|
* value possible.
|
||||||
|
*/
|
||||||
|
double maxShutter = std::numeric_limits<double>::max();
|
||||||
|
helper_->GetVBlanking(maxShutter, minFrameDuration_, maxFrameDuration_);
|
||||||
|
|
||||||
|
RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
|
||||||
|
controller_.GetAlgorithm("agc"));
|
||||||
|
agc->SetMaxShutter(maxShutter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
|
void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue