From 6914fc487f6a861fcce295f37ffe8a5079921b0d Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Tue, 8 Jun 2021 12:03:35 +0100 Subject: ipa: raspberrypi: Switch the AGC/Lux code to use utils::Duration Convert the core AGC and Lux controller code to use utils::Duration for all exposure time related variables and calculations. Convert the exposure/shutter time fields in AgcStatus and DeviceStatus to use utils::Duration. Signed-off-by: Naushir Patuck Reviewed-by: David Plowman Reviewed-by: Jacopo Mondi Signed-off-by: Laurent Pinchart --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 82 ++++++++++++++++-------------- 1 file changed, 45 insertions(+), 37 deletions(-) (limited to 'src/ipa/raspberrypi/controller/rpi/agc.cpp') 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 &metering_modes, return first; } -static int read_double_list(std::vector &list, - boost::property_tree::ptree const ¶ms) +static int read_list(std::vector &list, + boost::property_tree::ptree const ¶ms) { for (auto &p : params) list.push_back(p.second.get_value()); return list.size(); } +static int read_list(std::vector &list, + boost::property_tree::ptree const ¶ms) +{ + for (auto &p : params) + list.push_back(p.second.get_value() * 1us); + return list.size(); +} + void AgcExposureMode::Read(boost::property_tree::ptree const ¶ms) { - 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 ¶ms) params.get("fast_reduce_threshold", 0.4); base_ev = params.get("base_ev", 1.0); // Start with quite a low value as ramping up is easier than ramping down. - default_exposure_time = params.get("default_exposure_time", 1000); + default_exposure_time = params.get("default_exposure_time", 1000) * 1us; default_analogue_gain = params.get("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(); + flicker_period_ = flicker_period; } void Agc::SetMaxShutter(Duration max_shutter) { - max_shutter_ = max_shutter.get(); + max_shutter_ = max_shutter; } void Agc::SetFixedShutter(Duration fixed_shutter) { - fixed_shutter_ = fixed_shutter.get(); + 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("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_); -- cgit v1.2.1