summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller/rpi/agc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/raspberrypi/controller/rpi/agc.cpp')
-rw-r--r--src/ipa/raspberrypi/controller/rpi/agc.cpp82
1 files changed, 45 insertions, 37 deletions
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
index fd3359a7..55e80ac7 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
@@ -56,19 +56,26 @@ read_metering_modes(std::map<std::string, AgcMeteringMode> &metering_modes,
return first;
}
-static int read_double_list(std::vector<double> &list,
- boost::property_tree::ptree const &params)
+static int read_list(std::vector<double> &list,
+ boost::property_tree::ptree const &params)
{
for (auto &p : params)
list.push_back(p.second.get_value<double>());
return list.size();
}
+static int read_list(std::vector<Duration> &list,
+ boost::property_tree::ptree const &params)
+{
+ for (auto &p : params)
+ list.push_back(p.second.get_value<double>() * 1us);
+ return list.size();
+}
+
void AgcExposureMode::Read(boost::property_tree::ptree const &params)
{
- int num_shutters =
- read_double_list(shutter, params.get_child("shutter"));
- int num_ags = read_double_list(gain, params.get_child("gain"));
+ int num_shutters = read_list(shutter, params.get_child("shutter"));
+ int num_ags = read_list(gain, params.get_child("gain"));
if (num_shutters < 2 || num_ags < 2)
throw std::runtime_error(
"AgcConfig: must have at least two entries in exposure profile");
@@ -148,7 +155,7 @@ void AgcConfig::Read(boost::property_tree::ptree const &params)
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_exposure_time = params.get<double>("default_exposure_time", 1000) * 1us;
default_analogue_gain = params.get<double>("default_analogue_gain", 1.0);
}
@@ -156,9 +163,9 @@ Agc::Agc(Controller *controller)
: AgcAlgorithm(controller), metering_mode_(nullptr),
exposure_mode_(nullptr), constraint_mode_(nullptr),
frame_count_(0), lock_count_(0),
- last_target_exposure_(0.0),
- ev_(1.0), flicker_period_(0.0),
- max_shutter_(0), fixed_shutter_(0), fixed_analogue_gain_(0.0)
+ last_target_exposure_(0s),
+ ev_(1.0), flicker_period_(0s),
+ max_shutter_(0s), fixed_shutter_(0s), fixed_analogue_gain_(0.0)
{
memset(&awb_, 0, sizeof(awb_));
// Setting status_.total_exposure_value_ to zero initially tells us
@@ -204,7 +211,7 @@ void Agc::Pause()
void Agc::Resume()
{
- fixed_shutter_ = 0;
+ fixed_shutter_ = 0s;
fixed_analogue_gain_ = 0;
}
@@ -225,17 +232,17 @@ void Agc::SetEv(double ev)
void Agc::SetFlickerPeriod(Duration flicker_period)
{
- flicker_period_ = flicker_period.get<std::micro>();
+ flicker_period_ = flicker_period;
}
void Agc::SetMaxShutter(Duration max_shutter)
{
- max_shutter_ = max_shutter.get<std::micro>();
+ max_shutter_ = max_shutter;
}
void Agc::SetFixedShutter(Duration fixed_shutter)
{
- fixed_shutter_ = fixed_shutter.get<std::micro>();
+ fixed_shutter_ = fixed_shutter;
// Set this in case someone calls Pause() straight after.
status_.shutter_time = clipShutter(fixed_shutter_);
}
@@ -267,8 +274,8 @@ void Agc::SwitchMode([[maybe_unused]] CameraMode const &camera_mode,
{
housekeepConfig();
- double fixed_shutter = clipShutter(fixed_shutter_);
- if (fixed_shutter != 0.0 && fixed_analogue_gain_ != 0.0) {
+ Duration fixed_shutter = clipShutter(fixed_shutter_);
+ if (fixed_shutter && fixed_analogue_gain_) {
// We're going to reset the algorithm here with these fixed values.
fetchAwbStatus(metadata);
@@ -313,8 +320,8 @@ void Agc::Prepare(Metadata *image_metadata)
// Process has run, so we have meaningful values.
DeviceStatus device_status;
if (image_metadata->Get("device.status", device_status) == 0) {
- double actual_exposure = device_status.shutter_speed *
- device_status.analogue_gain;
+ Duration actual_exposure = device_status.shutter_speed *
+ device_status.analogue_gain;
if (actual_exposure) {
status_.digital_gain =
status_.total_exposure_value /
@@ -327,7 +334,8 @@ void Agc::Prepare(Metadata *image_metadata)
std::min(status_.digital_gain, 4.0));
LOG(RPiAgc, Debug) << "Actual exposure " << actual_exposure;
LOG(RPiAgc, Debug) << "Use digital_gain " << status_.digital_gain;
- LOG(RPiAgc, Debug) << "Effective exposure " << actual_exposure * status_.digital_gain;
+ LOG(RPiAgc, Debug) << "Effective exposure "
+ << actual_exposure * status_.digital_gain;
// Decide whether AEC/AGC has converged.
updateLockStatus(device_status);
}
@@ -371,9 +379,9 @@ void Agc::updateLockStatus(DeviceStatus const &device_status)
const double RESET_MARGIN = 1.5;
// Add 200us to the exposure time error to allow for line quantisation.
- double exposure_error = last_device_status_.shutter_speed * ERROR_FACTOR + 200;
+ Duration exposure_error = last_device_status_.shutter_speed * ERROR_FACTOR + 200us;
double gain_error = last_device_status_.analogue_gain * ERROR_FACTOR;
- double target_error = last_target_exposure_ * ERROR_FACTOR;
+ Duration target_error = last_target_exposure_ * ERROR_FACTOR;
// Note that we don't know the exposure/gain limits of the sensor, so
// the values we keep requesting may be unachievable. For this reason
@@ -463,7 +471,7 @@ void Agc::fetchCurrentExposure(Metadata *image_metadata)
current_.analogue_gain = device_status->analogue_gain;
AgcStatus *agc_status =
image_metadata->GetLocked<AgcStatus>("agc.status");
- current_.total_exposure = agc_status ? agc_status->total_exposure_value : 0;
+ current_.total_exposure = agc_status ? agc_status->total_exposure_value : 0s;
current_.total_exposure_no_dg = current_.shutter * current_.analogue_gain;
}
@@ -574,7 +582,7 @@ void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata,
void Agc::computeTargetExposure(double gain)
{
- if (status_.fixed_shutter != 0.0 && status_.fixed_analogue_gain != 0.0) {
+ if (status_.fixed_shutter && status_.fixed_analogue_gain) {
// 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
@@ -589,11 +597,11 @@ void Agc::computeTargetExposure(double gain)
target_.total_exposure = current_.total_exposure_no_dg * gain;
// The final target exposure is also limited to what the exposure
// mode allows.
- double max_shutter = status_.fixed_shutter != 0.0
+ Duration max_shutter = status_.fixed_shutter
? status_.fixed_shutter
: exposure_mode_->shutter.back();
max_shutter = clipShutter(max_shutter);
- double max_total_exposure =
+ Duration max_total_exposure =
max_shutter *
(status_.fixed_analogue_gain != 0.0
? status_.fixed_analogue_gain
@@ -638,7 +646,7 @@ void Agc::filterExposure(bool desaturate)
if ((status_.fixed_shutter && status_.fixed_analogue_gain) ||
frame_count_ <= config_.startup_frames)
speed = 1.0;
- if (filtered_.total_exposure == 0.0) {
+ if (!filtered_.total_exposure) {
filtered_.total_exposure = target_.total_exposure;
filtered_.total_exposure_no_dg = target_.total_exposure_no_dg;
} else {
@@ -675,9 +683,10 @@ void Agc::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.
- double exposure_value = filtered_.total_exposure_no_dg;
- double shutter_time, analogue_gain;
- shutter_time = status_.fixed_shutter != 0.0
+ Duration exposure_value = filtered_.total_exposure_no_dg;
+ Duration shutter_time;
+ double analogue_gain;
+ shutter_time = status_.fixed_shutter
? status_.fixed_shutter
: exposure_mode_->shutter[0];
shutter_time = clipShutter(shutter_time);
@@ -687,8 +696,8 @@ void Agc::divideUpExposure()
if (shutter_time * analogue_gain < exposure_value) {
for (unsigned int stage = 1;
stage < exposure_mode_->gain.size(); stage++) {
- if (status_.fixed_shutter == 0.0) {
- double stage_shutter =
+ if (!status_.fixed_shutter) {
+ Duration stage_shutter =
clipShutter(exposure_mode_->shutter[stage]);
if (stage_shutter * analogue_gain >=
exposure_value) {
@@ -714,12 +723,11 @@ void Agc::divideUpExposure()
<< analogue_gain;
// Finally adjust shutter time for flicker avoidance (require both
// shutter and gain not to be fixed).
- if (status_.fixed_shutter == 0.0 &&
- status_.fixed_analogue_gain == 0.0 &&
- status_.flicker_period != 0.0) {
+ if (!status_.fixed_shutter && !status_.fixed_analogue_gain &&
+ status_.flicker_period) {
int flicker_periods = shutter_time / status_.flicker_period;
- if (flicker_periods > 0) {
- double new_shutter_time = flicker_periods * status_.flicker_period;
+ if (flicker_periods) {
+ Duration new_shutter_time = flicker_periods * status_.flicker_period;
analogue_gain *= shutter_time / new_shutter_time;
// We should still not allow the ag to go over the
// largest value in the exposure mode. Note that this
@@ -739,7 +747,7 @@ void Agc::divideUpExposure()
void Agc::writeAndFinish(Metadata *image_metadata, bool desaturate)
{
status_.total_exposure_value = filtered_.total_exposure;
- status_.target_exposure_value = desaturate ? 0 : target_.total_exposure_no_dg;
+ status_.target_exposure_value = desaturate ? 0s : target_.total_exposure_no_dg;
status_.shutter_time = filtered_.shutter;
status_.analogue_gain = filtered_.analogue_gain;
// Write to metadata as well, in case anyone wants to update the camera
@@ -751,7 +759,7 @@ void Agc::writeAndFinish(Metadata *image_metadata, bool desaturate)
<< " analogue gain " << filtered_.analogue_gain;
}
-double Agc::clipShutter(double shutter)
+Duration Agc::clipShutter(Duration shutter)
{
if (max_shutter_)
shutter = std::min(shutter, max_shutter_);