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.cpp732
1 files changed, 354 insertions, 378 deletions
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
index f6a9cb0a..52a41a55 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
@@ -30,7 +30,7 @@ LOG_DEFINE_CATEGORY(RPiAgc)
#define PIPELINE_BITS 13 // seems to be a 13-bit pipeline
-void AgcMeteringMode::Read(boost::property_tree::ptree const &params)
+void AgcMeteringMode::read(boost::property_tree::ptree const &params)
{
int num = 0;
for (auto &p : params.get_child("weights")) {
@@ -43,265 +43,260 @@ void AgcMeteringMode::Read(boost::property_tree::ptree const &params)
}
static std::string
-read_metering_modes(std::map<std::string, AgcMeteringMode> &metering_modes,
- boost::property_tree::ptree const &params)
+readMeteringModes(std::map<std::string, AgcMeteringMode> &meteringModes,
+ boost::property_tree::ptree const &params)
{
std::string first;
for (auto &p : params) {
- AgcMeteringMode metering_mode;
- metering_mode.Read(p.second);
- metering_modes[p.first] = std::move(metering_mode);
+ AgcMeteringMode meteringMode;
+ meteringMode.read(p.second);
+ meteringModes[p.first] = std::move(meteringMode);
if (first.empty())
first = p.first;
}
return first;
}
-static int read_list(std::vector<double> &list,
- boost::property_tree::ptree const &params)
+static int readList(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)
+static int readList(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)
+void AgcExposureMode::read(boost::property_tree::ptree const &params)
{
- 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)
+ int numShutters = readList(shutter, params.get_child("shutter"));
+ int numAgs = readList(gain, params.get_child("gain"));
+ if (numShutters < 2 || numAgs < 2)
throw std::runtime_error(
"AgcConfig: must have at least two entries in exposure profile");
- if (num_shutters != num_ags)
+ if (numShutters != numAgs)
throw std::runtime_error(
"AgcConfig: expect same number of exposure and gain entries in exposure profile");
}
static std::string
-read_exposure_modes(std::map<std::string, AgcExposureMode> &exposure_modes,
- boost::property_tree::ptree const &params)
+readExposureModes(std::map<std::string, AgcExposureMode> &exposureModes,
+ boost::property_tree::ptree const &params)
{
std::string first;
for (auto &p : params) {
- AgcExposureMode exposure_mode;
- exposure_mode.Read(p.second);
- exposure_modes[p.first] = std::move(exposure_mode);
+ AgcExposureMode exposureMode;
+ exposureMode.read(p.second);
+ exposureModes[p.first] = std::move(exposureMode);
if (first.empty())
first = p.first;
}
return first;
}
-void AgcConstraint::Read(boost::property_tree::ptree const &params)
+void AgcConstraint::read(boost::property_tree::ptree const &params)
{
- std::string bound_string = params.get<std::string>("bound", "");
- transform(bound_string.begin(), bound_string.end(),
- bound_string.begin(), ::toupper);
- if (bound_string != "UPPER" && bound_string != "LOWER")
+ std::string boundString = params.get<std::string>("bound", "");
+ transform(boundString.begin(), boundString.end(),
+ boundString.begin(), ::toupper);
+ if (boundString != "UPPER" && boundString != "LOWER")
throw std::runtime_error(
"AGC constraint type should be UPPER or LOWER");
- bound = bound_string == "UPPER" ? Bound::UPPER : Bound::LOWER;
- q_lo = params.get<double>("q_lo");
- q_hi = params.get<double>("q_hi");
- Y_target.Read(params.get_child("y_target"));
+ bound = boundString == "UPPER" ? Bound::UPPER : Bound::LOWER;
+ qLo = params.get<double>("q_lo");
+ qHi = params.get<double>("q_hi");
+ yTarget.read(params.get_child("y_target"));
}
static AgcConstraintMode
-read_constraint_mode(boost::property_tree::ptree const &params)
+readConstraintMode(boost::property_tree::ptree const &params)
{
AgcConstraintMode mode;
for (auto &p : params) {
AgcConstraint constraint;
- constraint.Read(p.second);
+ constraint.read(p.second);
mode.push_back(std::move(constraint));
}
return mode;
}
-static std::string read_constraint_modes(
- std::map<std::string, AgcConstraintMode> &constraint_modes,
- boost::property_tree::ptree const &params)
+static std::string readConstraintModes(std::map<std::string, AgcConstraintMode> &constraintModes,
+ boost::property_tree::ptree const &params)
{
std::string first;
for (auto &p : params) {
- constraint_modes[p.first] = read_constraint_mode(p.second);
+ constraintModes[p.first] = readConstraintMode(p.second);
if (first.empty())
first = p.first;
}
return first;
}
-void AgcConfig::Read(boost::property_tree::ptree const &params)
+void AgcConfig::read(boost::property_tree::ptree const &params)
{
LOG(RPiAgc, Debug) << "AgcConfig";
- default_metering_mode = read_metering_modes(
- metering_modes, params.get_child("metering_modes"));
- default_exposure_mode = read_exposure_modes(
- exposure_modes, params.get_child("exposure_modes"));
- default_constraint_mode = read_constraint_modes(
- constraint_modes, params.get_child("constraint_modes"));
- Y_target.Read(params.get_child("y_target"));
+ defaultMeteringMode = readMeteringModes(meteringModes, params.get_child("metering_modes"));
+ defaultExposureMode = readExposureModes(exposureModes, params.get_child("exposure_modes"));
+ defaultConstraintMode = readConstraintModes(constraintModes, params.get_child("constraint_modes"));
+ yTarget.read(params.get_child("y_target"));
speed = params.get<double>("speed", 0.2);
- startup_frames = params.get<uint16_t>("startup_frames", 10);
- convergence_frames = params.get<unsigned int>("convergence_frames", 6);
- fast_reduce_threshold =
- params.get<double>("fast_reduce_threshold", 0.4);
- base_ev = params.get<double>("base_ev", 1.0);
+ startupFrames = params.get<uint16_t>("startup_frames", 10);
+ convergenceFrames = params.get<unsigned int>("convergence_frames", 6);
+ fastReduceThreshold = params.get<double>("fast_reduce_threshold", 0.4);
+ baseEv = 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) * 1us;
- default_analogue_gain = params.get<double>("default_analogue_gain", 1.0);
+ defaultExposureTime = params.get<double>("default_exposure_time", 1000) * 1us;
+ defaultAnalogueGain = params.get<double>("default_analogueGain", 1.0);
}
Agc::ExposureValues::ExposureValues()
- : shutter(0s), analogue_gain(0),
- total_exposure(0s), total_exposure_no_dg(0s)
+ : shutter(0s), analogueGain(0),
+ totalExposure(0s), totalExposureNoDG(0s)
{
}
Agc::Agc(Controller *controller)
- : AgcAlgorithm(controller), metering_mode_(nullptr),
- exposure_mode_(nullptr), constraint_mode_(nullptr),
- frame_count_(0), lock_count_(0),
- last_target_exposure_(0s), last_sensitivity_(0.0),
- ev_(1.0), flicker_period_(0s),
- max_shutter_(0s), fixed_shutter_(0s), fixed_analogue_gain_(0.0)
+ : AgcAlgorithm(controller), meteringMode_(nullptr),
+ exposureMode_(nullptr), constraintMode_(nullptr),
+ frameCount_(0), lockCount_(0),
+ lastTargetExposure_(0s), lastSensitivity_(0.0),
+ ev_(1.0), flickerPeriod_(0s),
+ maxShutter_(0s), fixedShutter_(0s), fixedAnalogueGain_(0.0)
{
memset(&awb_, 0, sizeof(awb_));
- // Setting status_.total_exposure_value_ to zero initially tells us
+ // Setting status_.totalExposureValue_ to zero initially tells us
// it's not been calculated yet (i.e. Process hasn't yet run).
memset(&status_, 0, sizeof(status_));
status_.ev = ev_;
}
-char const *Agc::Name() const
+char const *Agc::name() const
{
return NAME;
}
-void Agc::Read(boost::property_tree::ptree const &params)
+void Agc::read(boost::property_tree::ptree const &params)
{
LOG(RPiAgc, Debug) << "Agc";
- config_.Read(params);
+ config_.read(params);
// Set the config's defaults (which are the first ones it read) as our
// current modes, until someone changes them. (they're all known to
// exist at this point)
- metering_mode_name_ = config_.default_metering_mode;
- metering_mode_ = &config_.metering_modes[metering_mode_name_];
- exposure_mode_name_ = config_.default_exposure_mode;
- exposure_mode_ = &config_.exposure_modes[exposure_mode_name_];
- constraint_mode_name_ = config_.default_constraint_mode;
- constraint_mode_ = &config_.constraint_modes[constraint_mode_name_];
+ meteringModeName_ = config_.defaultMeteringMode;
+ meteringMode_ = &config_.meteringModes[meteringModeName_];
+ exposureModeName_ = config_.defaultExposureMode;
+ exposureMode_ = &config_.exposureModes[exposureModeName_];
+ constraintModeName_ = config_.defaultConstraintMode;
+ constraintMode_ = &config_.constraintModes[constraintModeName_];
// Set up the "last shutter/gain" values, in case AGC starts "disabled".
- status_.shutter_time = config_.default_exposure_time;
- status_.analogue_gain = config_.default_analogue_gain;
+ status_.shutterTime = config_.defaultExposureTime;
+ status_.analogueGain = config_.defaultAnalogueGain;
}
-bool Agc::IsPaused() const
+bool Agc::isPaused() const
{
return false;
}
-void Agc::Pause()
+void Agc::pause()
{
- fixed_shutter_ = status_.shutter_time;
- fixed_analogue_gain_ = status_.analogue_gain;
+ fixedShutter_ = status_.shutterTime;
+ fixedAnalogueGain_ = status_.analogueGain;
}
-void Agc::Resume()
+void Agc::resume()
{
- fixed_shutter_ = 0s;
- fixed_analogue_gain_ = 0;
+ fixedShutter_ = 0s;
+ fixedAnalogueGain_ = 0;
}
-unsigned int Agc::GetConvergenceFrames() const
+unsigned int Agc::getConvergenceFrames() const
{
// If shutter and gain have been explicitly set, there is no
// convergence to happen, so no need to drop any frames - return zero.
- if (fixed_shutter_ && fixed_analogue_gain_)
+ if (fixedShutter_ && fixedAnalogueGain_)
return 0;
else
- return config_.convergence_frames;
+ return config_.convergenceFrames;
}
-void Agc::SetEv(double ev)
+void Agc::setEv(double ev)
{
ev_ = ev;
}
-void Agc::SetFlickerPeriod(Duration flicker_period)
+void Agc::setFlickerPeriod(Duration flickerPeriod)
{
- flicker_period_ = flicker_period;
+ flickerPeriod_ = flickerPeriod;
}
-void Agc::SetMaxShutter(Duration max_shutter)
+void Agc::setMaxShutter(Duration maxShutter)
{
- max_shutter_ = max_shutter;
+ maxShutter_ = maxShutter;
}
-void Agc::SetFixedShutter(Duration fixed_shutter)
+void Agc::setFixedShutter(Duration fixedShutter)
{
- fixed_shutter_ = fixed_shutter;
+ fixedShutter_ = fixedShutter;
// Set this in case someone calls Pause() straight after.
- status_.shutter_time = clipShutter(fixed_shutter_);
+ status_.shutterTime = clipShutter(fixedShutter_);
}
-void Agc::SetFixedAnalogueGain(double fixed_analogue_gain)
+void Agc::setFixedAnalogueGain(double fixedAnalogueGain)
{
- fixed_analogue_gain_ = fixed_analogue_gain;
+ fixedAnalogueGain_ = fixedAnalogueGain;
// Set this in case someone calls Pause() straight after.
- status_.analogue_gain = fixed_analogue_gain;
+ status_.analogueGain = fixedAnalogueGain;
}
-void Agc::SetMeteringMode(std::string const &metering_mode_name)
+void Agc::setMeteringMode(std::string const &meteringModeName)
{
- metering_mode_name_ = metering_mode_name;
+ meteringModeName_ = meteringModeName;
}
-void Agc::SetExposureMode(std::string const &exposure_mode_name)
+void Agc::setExposureMode(std::string const &exposureModeName)
{
- exposure_mode_name_ = exposure_mode_name;
+ exposureModeName_ = exposureModeName;
}
-void Agc::SetConstraintMode(std::string const &constraint_mode_name)
+void Agc::setConstraintMode(std::string const &constraintModeName)
{
- constraint_mode_name_ = constraint_mode_name;
+ constraintModeName_ = constraintModeName;
}
-void Agc::SwitchMode(CameraMode const &camera_mode,
+void Agc::switchMode(CameraMode const &cameraMode,
Metadata *metadata)
{
/* AGC expects the mode sensitivity always to be non-zero. */
- ASSERT(camera_mode.sensitivity);
+ ASSERT(cameraMode.sensitivity);
housekeepConfig();
- Duration fixed_shutter = clipShutter(fixed_shutter_);
- if (fixed_shutter && fixed_analogue_gain_) {
+ Duration fixedShutter = clipShutter(fixedShutter_);
+ if (fixedShutter && fixedAnalogueGain_) {
// 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);
+ double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
+ ASSERT(minColourGain != 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;
+ target_.totalExposureNoDG = fixedShutter_ * fixedAnalogueGain_;
+ target_.totalExposure = target_.totalExposureNoDG / minColourGain;
// 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) {
+ filtered_.shutter = fixedShutter;
+ filtered_.analogueGain = fixedAnalogueGain_;
+ } else if (status_.totalExposureValue) {
// On a mode switch, various things could happen:
// - the exposure profile might change
// - a fixed exposure or gain might be set
@@ -310,11 +305,11 @@ void Agc::SwitchMode(CameraMode const &camera_mode,
// that we just need to re-divide the exposure/gain according to the
// current exposure profile, which takes care of everything else.
- double ratio = last_sensitivity_ / camera_mode.sensitivity;
- target_.total_exposure_no_dg *= ratio;
- target_.total_exposure *= ratio;
- filtered_.total_exposure_no_dg *= ratio;
- filtered_.total_exposure *= ratio;
+ double ratio = lastSensitivity_ / cameraMode.sensitivity;
+ target_.totalExposureNoDG *= ratio;
+ target_.totalExposure *= ratio;
+ filtered_.totalExposureNoDG *= ratio;
+ filtered_.totalExposure *= ratio;
divideUpExposure();
} else {
@@ -324,114 +319,110 @@ void Agc::SwitchMode(CameraMode const &camera_mode,
// 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;
+ filtered_.shutter = fixedShutter ? fixedShutter : config_.defaultExposureTime;
+ filtered_.analogueGain = fixedAnalogueGain_ ? fixedAnalogueGain_ : config_.defaultAnalogueGain;
}
writeAndFinish(metadata, false);
// We must remember the sensitivity of this mode for the next SwitchMode.
- last_sensitivity_ = camera_mode.sensitivity;
+ lastSensitivity_ = cameraMode.sensitivity;
}
-void Agc::Prepare(Metadata *image_metadata)
+void Agc::prepare(Metadata *imageMetadata)
{
- status_.digital_gain = 1.0;
- fetchAwbStatus(image_metadata); // always fetch it so that Process knows it's been done
+ status_.digitalGain = 1.0;
+ fetchAwbStatus(imageMetadata); // always fetch it so that Process knows it's been done
- if (status_.total_exposure_value) {
+ if (status_.totalExposureValue) {
// Process has run, so we have meaningful values.
- DeviceStatus device_status;
- if (image_metadata->Get("device.status", device_status) == 0) {
- Duration actual_exposure = device_status.shutter_speed *
- device_status.analogue_gain;
- if (actual_exposure) {
- status_.digital_gain =
- status_.total_exposure_value /
- actual_exposure;
- LOG(RPiAgc, Debug) << "Want total exposure " << status_.total_exposure_value;
+ DeviceStatus deviceStatus;
+ if (imageMetadata->get("device.status", deviceStatus) == 0) {
+ Duration actualExposure = deviceStatus.shutterSpeed *
+ deviceStatus.analogueGain;
+ if (actualExposure) {
+ status_.digitalGain = status_.totalExposureValue / actualExposure;
+ LOG(RPiAgc, Debug) << "Want total exposure " << status_.totalExposureValue;
// Never ask for a gain < 1.0, and also impose
// some upper limit. Make it customisable?
- status_.digital_gain = std::max(
- 1.0,
- std::min(status_.digital_gain, 4.0));
- LOG(RPiAgc, Debug) << "Actual exposure " << actual_exposure;
- LOG(RPiAgc, Debug) << "Use digital_gain " << status_.digital_gain;
+ status_.digitalGain = std::max(1.0, std::min(status_.digitalGain, 4.0));
+ LOG(RPiAgc, Debug) << "Actual exposure " << actualExposure;
+ LOG(RPiAgc, Debug) << "Use digitalGain " << status_.digitalGain;
LOG(RPiAgc, Debug) << "Effective exposure "
- << actual_exposure * status_.digital_gain;
+ << actualExposure * status_.digitalGain;
// Decide whether AEC/AGC has converged.
- updateLockStatus(device_status);
+ updateLockStatus(deviceStatus);
}
} else
- LOG(RPiAgc, Warning) << Name() << ": no device metadata";
- image_metadata->Set("agc.status", status_);
+ LOG(RPiAgc, Warning) << name() << ": no device metadata";
+ imageMetadata->set("agc.status", status_);
}
}
-void Agc::Process(StatisticsPtr &stats, Metadata *image_metadata)
+void Agc::process(StatisticsPtr &stats, Metadata *imageMetadata)
{
- frame_count_++;
+ frameCount_++;
// First a little bit of housekeeping, fetching up-to-date settings and
// configuration, that kind of thing.
housekeepConfig();
// Get the current exposure values for the frame that's just arrived.
- fetchCurrentExposure(image_metadata);
+ fetchCurrentExposure(imageMetadata);
// Compute the total gain we require relative to the current exposure.
- double gain, target_Y;
- computeGain(stats.get(), image_metadata, gain, target_Y);
+ double gain, targetY;
+ computeGain(stats.get(), imageMetadata, gain, targetY);
// Now compute the target (final) exposure which we think we want.
computeTargetExposure(gain);
// Some of the exposure has to be applied as digital gain, so work out
// what that is. This function also tells us whether it's decided to
// "desaturate" the image more quickly.
- bool desaturate = applyDigitalGain(gain, target_Y);
+ bool desaturate = applyDigitalGain(gain, targetY);
// The results have to be filtered so as not to change too rapidly.
filterExposure(desaturate);
// The last thing is to divide up the exposure value into a shutter time
- // and analogue_gain, according to the current exposure mode.
+ // and analogue gain, according to the current exposure mode.
divideUpExposure();
// Finally advertise what we've done.
- writeAndFinish(image_metadata, desaturate);
+ writeAndFinish(imageMetadata, desaturate);
}
-void Agc::updateLockStatus(DeviceStatus const &device_status)
+void Agc::updateLockStatus(DeviceStatus const &deviceStatus)
{
- const double ERROR_FACTOR = 0.10; // make these customisable?
- const int MAX_LOCK_COUNT = 5;
- // Reset "lock count" when we exceed this multiple of ERROR_FACTOR
- const double RESET_MARGIN = 1.5;
+ const double errorFactor = 0.10; // make these customisable?
+ const int maxLockCount = 5;
+ // Reset "lock count" when we exceed this multiple of errorFactor
+ const double resetMargin = 1.5;
// Add 200us to the exposure time error to allow for line quantisation.
- Duration exposure_error = last_device_status_.shutter_speed * ERROR_FACTOR + 200us;
- double gain_error = last_device_status_.analogue_gain * ERROR_FACTOR;
- Duration target_error = last_target_exposure_ * ERROR_FACTOR;
+ Duration exposureError = lastDeviceStatus_.shutterSpeed * errorFactor + 200us;
+ double gainError = lastDeviceStatus_.analogueGain * errorFactor;
+ Duration targetError = lastTargetExposure_ * errorFactor;
// 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
// we only insist that we're close to values in the past few frames.
- if (device_status.shutter_speed > last_device_status_.shutter_speed - exposure_error &&
- device_status.shutter_speed < last_device_status_.shutter_speed + exposure_error &&
- device_status.analogue_gain > last_device_status_.analogue_gain - gain_error &&
- device_status.analogue_gain < last_device_status_.analogue_gain + gain_error &&
- status_.target_exposure_value > last_target_exposure_ - target_error &&
- status_.target_exposure_value < last_target_exposure_ + target_error)
- lock_count_ = std::min(lock_count_ + 1, MAX_LOCK_COUNT);
- else if (device_status.shutter_speed < last_device_status_.shutter_speed - RESET_MARGIN * exposure_error ||
- device_status.shutter_speed > last_device_status_.shutter_speed + RESET_MARGIN * exposure_error ||
- device_status.analogue_gain < last_device_status_.analogue_gain - RESET_MARGIN * gain_error ||
- device_status.analogue_gain > last_device_status_.analogue_gain + RESET_MARGIN * gain_error ||
- status_.target_exposure_value < last_target_exposure_ - RESET_MARGIN * target_error ||
- status_.target_exposure_value > last_target_exposure_ + RESET_MARGIN * target_error)
- lock_count_ = 0;
-
- last_device_status_ = device_status;
- last_target_exposure_ = status_.target_exposure_value;
-
- LOG(RPiAgc, Debug) << "Lock count updated to " << lock_count_;
- status_.locked = lock_count_ == MAX_LOCK_COUNT;
-}
-
-static void copy_string(std::string const &s, char *d, size_t size)
+ if (deviceStatus.shutterSpeed > lastDeviceStatus_.shutterSpeed - exposureError &&
+ deviceStatus.shutterSpeed < lastDeviceStatus_.shutterSpeed + exposureError &&
+ deviceStatus.analogueGain > lastDeviceStatus_.analogueGain - gainError &&
+ deviceStatus.analogueGain < lastDeviceStatus_.analogueGain + gainError &&
+ status_.targetExposureValue > lastTargetExposure_ - targetError &&
+ status_.targetExposureValue < lastTargetExposure_ + targetError)
+ lockCount_ = std::min(lockCount_ + 1, maxLockCount);
+ else if (deviceStatus.shutterSpeed < lastDeviceStatus_.shutterSpeed - resetMargin * exposureError ||
+ deviceStatus.shutterSpeed > lastDeviceStatus_.shutterSpeed + resetMargin * exposureError ||
+ deviceStatus.analogueGain < lastDeviceStatus_.analogueGain - resetMargin * gainError ||
+ deviceStatus.analogueGain > lastDeviceStatus_.analogueGain + resetMargin * gainError ||
+ status_.targetExposureValue < lastTargetExposure_ - resetMargin * targetError ||
+ status_.targetExposureValue > lastTargetExposure_ + resetMargin * targetError)
+ lockCount_ = 0;
+
+ lastDeviceStatus_ = deviceStatus;
+ lastTargetExposure_ = status_.targetExposureValue;
+
+ LOG(RPiAgc, Debug) << "Lock count updated to " << lockCount_;
+ status_.locked = lockCount_ == maxLockCount;
+}
+
+static void copyString(std::string const &s, char *d, size_t size)
{
size_t length = s.copy(d, size - 1);
d[length] = '\0';
@@ -441,97 +432,97 @@ void Agc::housekeepConfig()
{
// First fetch all the up-to-date settings, so no one else has to do it.
status_.ev = ev_;
- status_.fixed_shutter = clipShutter(fixed_shutter_);
- status_.fixed_analogue_gain = fixed_analogue_gain_;
- status_.flicker_period = flicker_period_;
- LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixed_shutter "
- << status_.fixed_shutter << " fixed_analogue_gain "
- << status_.fixed_analogue_gain;
+ status_.fixedShutter = clipShutter(fixedShutter_);
+ status_.fixedAnalogueGain = fixedAnalogueGain_;
+ status_.flickerPeriod = flickerPeriod_;
+ LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixedShutter "
+ << status_.fixedShutter << " fixedAnalogueGain "
+ << status_.fixedAnalogueGain;
// Make sure the "mode" pointers point to the up-to-date things, if
// they've changed.
- if (strcmp(metering_mode_name_.c_str(), status_.metering_mode)) {
- auto it = config_.metering_modes.find(metering_mode_name_);
- if (it == config_.metering_modes.end())
+ if (strcmp(meteringModeName_.c_str(), status_.meteringMode)) {
+ auto it = config_.meteringModes.find(meteringModeName_);
+ if (it == config_.meteringModes.end())
throw std::runtime_error("Agc: no metering mode " +
- metering_mode_name_);
- metering_mode_ = &it->second;
- copy_string(metering_mode_name_, status_.metering_mode,
- sizeof(status_.metering_mode));
+ meteringModeName_);
+ meteringMode_ = &it->second;
+ copyString(meteringModeName_, status_.meteringMode,
+ sizeof(status_.meteringMode));
}
- if (strcmp(exposure_mode_name_.c_str(), status_.exposure_mode)) {
- auto it = config_.exposure_modes.find(exposure_mode_name_);
- if (it == config_.exposure_modes.end())
+ if (strcmp(exposureModeName_.c_str(), status_.exposureMode)) {
+ auto it = config_.exposureModes.find(exposureModeName_);
+ if (it == config_.exposureModes.end())
throw std::runtime_error("Agc: no exposure profile " +
- exposure_mode_name_);
- exposure_mode_ = &it->second;
- copy_string(exposure_mode_name_, status_.exposure_mode,
- sizeof(status_.exposure_mode));
+ exposureModeName_);
+ exposureMode_ = &it->second;
+ copyString(exposureModeName_, status_.exposureMode,
+ sizeof(status_.exposureMode));
}
- if (strcmp(constraint_mode_name_.c_str(), status_.constraint_mode)) {
+ if (strcmp(constraintModeName_.c_str(), status_.constraintMode)) {
auto it =
- config_.constraint_modes.find(constraint_mode_name_);
- if (it == config_.constraint_modes.end())
+ config_.constraintModes.find(constraintModeName_);
+ if (it == config_.constraintModes.end())
throw std::runtime_error("Agc: no constraint list " +
- constraint_mode_name_);
- constraint_mode_ = &it->second;
- copy_string(constraint_mode_name_, status_.constraint_mode,
- sizeof(status_.constraint_mode));
+ constraintModeName_);
+ constraintMode_ = &it->second;
+ copyString(constraintModeName_, status_.constraintMode,
+ sizeof(status_.constraintMode));
}
- LOG(RPiAgc, Debug) << "exposure_mode "
- << exposure_mode_name_ << " constraint_mode "
- << constraint_mode_name_ << " metering_mode "
- << metering_mode_name_;
+ LOG(RPiAgc, Debug) << "exposureMode "
+ << exposureModeName_ << " constraintMode "
+ << constraintModeName_ << " meteringMode "
+ << meteringModeName_;
}
-void Agc::fetchCurrentExposure(Metadata *image_metadata)
+void Agc::fetchCurrentExposure(Metadata *imageMetadata)
{
- std::unique_lock<Metadata> lock(*image_metadata);
- DeviceStatus *device_status =
- image_metadata->GetLocked<DeviceStatus>("device.status");
- if (!device_status)
+ std::unique_lock<Metadata> lock(*imageMetadata);
+ DeviceStatus *deviceStatus =
+ imageMetadata->getLocked<DeviceStatus>("device.status");
+ if (!deviceStatus)
throw std::runtime_error("Agc: no device metadata");
- current_.shutter = device_status->shutter_speed;
- 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 : 0s;
- current_.total_exposure_no_dg = current_.shutter * current_.analogue_gain;
+ current_.shutter = deviceStatus->shutterSpeed;
+ current_.analogueGain = deviceStatus->analogueGain;
+ AgcStatus *agcStatus =
+ imageMetadata->getLocked<AgcStatus>("agc.status");
+ current_.totalExposure = agcStatus ? agcStatus->totalExposureValue : 0s;
+ current_.totalExposureNoDG = current_.shutter * current_.analogueGain;
}
-void Agc::fetchAwbStatus(Metadata *image_metadata)
+void Agc::fetchAwbStatus(Metadata *imageMetadata)
{
- awb_.gain_r = 1.0; // in case not found in metadata
- awb_.gain_g = 1.0;
- awb_.gain_b = 1.0;
- if (image_metadata->Get("awb.status", awb_) != 0)
+ awb_.gainR = 1.0; // in case not found in metadata
+ awb_.gainG = 1.0;
+ awb_.gainB = 1.0;
+ if (imageMetadata->get("awb.status", awb_) != 0)
LOG(RPiAgc, Debug) << "Agc: no AWB status found";
}
-static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb,
- double weights[], double gain)
+static double computeInitialY(bcm2835_isp_stats *stats, AwbStatus const &awb,
+ double weights[], double gain)
{
bcm2835_isp_stats_region *regions = stats->agc_stats;
// Note how the calculation below means that equal weights give you
// "average" metering (i.e. all pixels equally important).
- double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0;
+ double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0;
for (int i = 0; i < AGC_STATS_SIZE; i++) {
double counted = regions[i].counted;
- double r_sum = std::min(regions[i].r_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
- double g_sum = std::min(regions[i].g_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
- double b_sum = std::min(regions[i].b_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
- R_sum += r_sum * weights[i];
- G_sum += g_sum * weights[i];
- B_sum += b_sum * weights[i];
- pixel_sum += counted * weights[i];
+ double rAcc = std::min(regions[i].r_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
+ double gAcc = std::min(regions[i].g_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
+ double bAcc = std::min(regions[i].b_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
+ rSum += rAcc * weights[i];
+ gSum += gAcc * weights[i];
+ bSum += bAcc * weights[i];
+ pixelSum += counted * weights[i];
}
- if (pixel_sum == 0.0) {
- LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is zero";
+ if (pixelSum == 0.0) {
+ LOG(RPiAgc, Warning) << "computeInitialY: pixelSum is zero";
return 0;
}
- double Y_sum = R_sum * awb.gain_r * .299 +
- G_sum * awb.gain_g * .587 +
- B_sum * awb.gain_b * .114;
- return Y_sum / pixel_sum / (1 << PIPELINE_BITS);
+ double ySum = rSum * awb.gainR * .299 +
+ gSum * awb.gainG * .587 +
+ bSum * awb.gainB * .114;
+ return ySum / pixelSum / (1 << PIPELINE_BITS);
}
// We handle extra gain through EV by adjusting our Y targets. However, you
@@ -542,108 +533,102 @@ static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb,
#define EV_GAIN_Y_TARGET_LIMIT 0.9
-static double constraint_compute_gain(AgcConstraint &c, Histogram &h,
- double lux, double ev_gain,
- double &target_Y)
+static double constraintComputeGain(AgcConstraint &c, Histogram &h, double lux,
+ double evGain, double &targetY)
{
- target_Y = c.Y_target.Eval(c.Y_target.Domain().Clip(lux));
- target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain);
- double iqm = h.InterQuantileMean(c.q_lo, c.q_hi);
- return (target_Y * NUM_HISTOGRAM_BINS) / iqm;
+ targetY = c.yTarget.eval(c.yTarget.domain().clip(lux));
+ targetY = std::min(EV_GAIN_Y_TARGET_LIMIT, targetY * evGain);
+ double iqm = h.interQuantileMean(c.qLo, c.qHi);
+ return (targetY * NUM_HISTOGRAM_BINS) / iqm;
}
-void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata,
- double &gain, double &target_Y)
+void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata,
+ double &gain, double &targetY)
{
struct LuxStatus lux = {};
lux.lux = 400; // default lux level to 400 in case no metadata found
- if (image_metadata->Get("lux.status", lux) != 0)
+ if (imageMetadata->get("lux.status", lux) != 0)
LOG(RPiAgc, Warning) << "Agc: no lux level found";
Histogram h(statistics->hist[0].g_hist, NUM_HISTOGRAM_BINS);
- double ev_gain = status_.ev * config_.base_ev;
+ double evGain = status_.ev * config_.baseEv;
// The initial gain and target_Y come from some of the regions. After
// that we consider the histogram constraints.
- target_Y =
- config_.Y_target.Eval(config_.Y_target.Domain().Clip(lux.lux));
- target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain);
+ targetY = config_.yTarget.eval(config_.yTarget.domain().clip(lux.lux));
+ targetY = std::min(EV_GAIN_Y_TARGET_LIMIT, targetY * evGain);
// Do this calculation a few times as brightness increase can be
// non-linear when there are saturated regions.
gain = 1.0;
for (int i = 0; i < 8; i++) {
- double initial_Y = compute_initial_Y(statistics, awb_,
- metering_mode_->weights, gain);
- double extra_gain = std::min(10.0, target_Y / (initial_Y + .001));
- gain *= extra_gain;
- LOG(RPiAgc, Debug) << "Initial Y " << initial_Y << " target " << target_Y
+ double initialY = computeInitialY(statistics, awb_, meteringMode_->weights, gain);
+ double extraGain = std::min(10.0, targetY / (initialY + .001));
+ gain *= extraGain;
+ LOG(RPiAgc, Debug) << "Initial Y " << initialY << " target " << targetY
<< " gives gain " << gain;
- if (extra_gain < 1.01) // close enough
+ if (extraGain < 1.01) // close enough
break;
}
- for (auto &c : *constraint_mode_) {
- double new_target_Y;
- double new_gain =
- constraint_compute_gain(c, h, lux.lux, ev_gain,
- new_target_Y);
+ for (auto &c : *constraintMode_) {
+ double newTargetY;
+ double newGain = constraintComputeGain(c, h, lux.lux, evGain, newTargetY);
LOG(RPiAgc, Debug) << "Constraint has target_Y "
- << new_target_Y << " giving gain " << new_gain;
- if (c.bound == AgcConstraint::Bound::LOWER &&
- new_gain > gain) {
+ << newTargetY << " giving gain " << newGain;
+ if (c.bound == AgcConstraint::Bound::LOWER && newGain > gain) {
LOG(RPiAgc, Debug) << "Lower bound constraint adopted";
- gain = new_gain, target_Y = new_target_Y;
- } else if (c.bound == AgcConstraint::Bound::UPPER &&
- new_gain < gain) {
+ gain = newGain;
+ targetY = newTargetY;
+ } else if (c.bound == AgcConstraint::Bound::UPPER && newGain < gain) {
LOG(RPiAgc, Debug) << "Upper bound constraint adopted";
- gain = new_gain, target_Y = new_target_Y;
+ gain = newGain;
+ targetY = newTargetY;
}
}
- LOG(RPiAgc, Debug) << "Final gain " << gain << " (target_Y " << target_Y << " ev "
- << status_.ev << " base_ev " << config_.base_ev
+ LOG(RPiAgc, Debug) << "Final gain " << gain << " (target_Y " << targetY << " ev "
+ << status_.ev << " base_ev " << config_.baseEv
<< ")";
}
void Agc::computeTargetExposure(double gain)
{
- if (status_.fixed_shutter && status_.fixed_analogue_gain) {
+ if (status_.fixedShutter && status_.fixedAnalogueGain) {
// 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
+ // 1/minColourGain. 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;
+ double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
+ ASSERT(minColourGain != 0.0);
+ target_.totalExposure =
+ status_.fixedShutter * status_.fixedAnalogueGain / minColourGain;
} 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;
+ target_.totalExposure = current_.totalExposureNoDG * gain;
// The final target exposure is also limited to what the exposure
// mode allows.
- Duration max_shutter = status_.fixed_shutter
- ? status_.fixed_shutter
- : exposure_mode_->shutter.back();
- max_shutter = clipShutter(max_shutter);
- Duration max_total_exposure =
- max_shutter *
- (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);
+ Duration maxShutter = status_.fixedShutter
+ ? status_.fixedShutter
+ : exposureMode_->shutter.back();
+ maxShutter = clipShutter(maxShutter);
+ Duration maxTotalExposure =
+ maxShutter *
+ (status_.fixedAnalogueGain != 0.0
+ ? status_.fixedAnalogueGain
+ : exposureMode_->gain.back());
+ target_.totalExposure = std::min(target_.totalExposure, maxTotalExposure);
}
- LOG(RPiAgc, Debug) << "Target total_exposure " << target_.total_exposure;
+ LOG(RPiAgc, Debug) << "Target totalExposure " << target_.totalExposure;
}
-bool Agc::applyDigitalGain(double gain, double target_Y)
+bool Agc::applyDigitalGain(double gain, double targetY)
{
- double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 });
- ASSERT(min_colour_gain != 0.0);
- double dg = 1.0 / min_colour_gain;
+ double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
+ ASSERT(minColourGain != 0.0);
+ double dg = 1.0 / minColourGain;
// I think this pipeline subtracts black level and rescales before we
// get the stats, so no need to worry about it.
LOG(RPiAgc, Debug) << "after AWB, target dg " << dg << " gain " << gain
- << " target_Y " << target_Y;
+ << " target_Y " << targetY;
// Finally, if we're trying to reduce exposure but the target_Y is
// "close" to 1.0, then the gain computed for that constraint will be
// only slightly less than one, because the measured Y can never be
@@ -651,13 +636,13 @@ bool Agc::applyDigitalGain(double gain, double target_Y)
// that the exposure can be reduced, de-saturating the image much more
// quickly (and we then approach the correct value more quickly from
// below).
- bool desaturate = target_Y > config_.fast_reduce_threshold &&
- gain < sqrt(target_Y);
+ bool desaturate = targetY > config_.fastReduceThreshold &&
+ gain < sqrt(targetY);
if (desaturate)
- dg /= config_.fast_reduce_threshold;
+ dg /= config_.fastReduceThreshold;
LOG(RPiAgc, Debug) << "Digital gain " << dg << " desaturate? " << desaturate;
- target_.total_exposure_no_dg = target_.total_exposure / dg;
- LOG(RPiAgc, Debug) << "Target total_exposure_no_dg " << target_.total_exposure_no_dg;
+ target_.totalExposureNoDG = target_.totalExposure / dg;
+ LOG(RPiAgc, Debug) << "Target totalExposureNoDG " << target_.totalExposureNoDG;
return desaturate;
}
@@ -666,39 +651,38 @@ void Agc::filterExposure(bool desaturate)
double speed = config_.speed;
// AGC adapts instantly if both shutter and gain are directly specified
// or we're in the startup phase.
- if ((status_.fixed_shutter && status_.fixed_analogue_gain) ||
- frame_count_ <= config_.startup_frames)
+ if ((status_.fixedShutter && status_.fixedAnalogueGain) ||
+ frameCount_ <= config_.startupFrames)
speed = 1.0;
- if (!filtered_.total_exposure) {
- filtered_.total_exposure = target_.total_exposure;
- filtered_.total_exposure_no_dg = target_.total_exposure_no_dg;
+ if (!filtered_.totalExposure) {
+ filtered_.totalExposure = target_.totalExposure;
+ filtered_.totalExposureNoDG = target_.totalExposureNoDG;
} else {
// If close to the result go faster, to save making so many
// micro-adjustments on the way. (Make this customisable?)
- if (filtered_.total_exposure < 1.2 * target_.total_exposure &&
- filtered_.total_exposure > 0.8 * target_.total_exposure)
+ if (filtered_.totalExposure < 1.2 * target_.totalExposure &&
+ filtered_.totalExposure > 0.8 * target_.totalExposure)
speed = sqrt(speed);
- filtered_.total_exposure = speed * target_.total_exposure +
- filtered_.total_exposure * (1.0 - speed);
- // When desaturing, take a big jump down in exposure_no_dg,
+ filtered_.totalExposure = speed * target_.totalExposure +
+ filtered_.totalExposure * (1.0 - speed);
+ // When desaturing, take a big jump down in totalExposureNoDG,
// which we'll hide with digital gain.
if (desaturate)
- filtered_.total_exposure_no_dg =
- target_.total_exposure_no_dg;
+ filtered_.totalExposureNoDG =
+ target_.totalExposureNoDG;
else
- filtered_.total_exposure_no_dg =
- speed * target_.total_exposure_no_dg +
- filtered_.total_exposure_no_dg * (1.0 - speed);
+ filtered_.totalExposureNoDG =
+ speed * target_.totalExposureNoDG +
+ filtered_.totalExposureNoDG * (1.0 - speed);
}
- // We can't let the no_dg exposure deviate too far below the
+ // We can't let the totalExposureNoDG exposure deviate too far below the
// total exposure, as there might not be enough digital gain available
// in the ISP to hide it (which will cause nasty oscillation).
- if (filtered_.total_exposure_no_dg <
- filtered_.total_exposure * config_.fast_reduce_threshold)
- filtered_.total_exposure_no_dg = filtered_.total_exposure *
- config_.fast_reduce_threshold;
- LOG(RPiAgc, Debug) << "After filtering, total_exposure " << filtered_.total_exposure
- << " no dg " << filtered_.total_exposure_no_dg;
+ if (filtered_.totalExposureNoDG <
+ filtered_.totalExposure * config_.fastReduceThreshold)
+ filtered_.totalExposureNoDG = filtered_.totalExposure * config_.fastReduceThreshold;
+ LOG(RPiAgc, Debug) << "After filtering, totalExposure " << filtered_.totalExposure
+ << " no dg " << filtered_.totalExposureNoDG;
}
void Agc::divideUpExposure()
@@ -706,92 +690,84 @@ 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.
- 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);
- analogue_gain = status_.fixed_analogue_gain != 0.0
- ? status_.fixed_analogue_gain
- : exposure_mode_->gain[0];
- if (shutter_time * analogue_gain < exposure_value) {
+ Duration exposureValue = filtered_.totalExposureNoDG;
+ Duration shutterTime;
+ double analogueGain;
+ shutterTime = status_.fixedShutter ? status_.fixedShutter
+ : exposureMode_->shutter[0];
+ shutterTime = clipShutter(shutterTime);
+ analogueGain = status_.fixedAnalogueGain != 0.0 ? status_.fixedAnalogueGain
+ : exposureMode_->gain[0];
+ if (shutterTime * analogueGain < exposureValue) {
for (unsigned int stage = 1;
- stage < exposure_mode_->gain.size(); stage++) {
- if (!status_.fixed_shutter) {
- Duration stage_shutter =
- clipShutter(exposure_mode_->shutter[stage]);
- if (stage_shutter * analogue_gain >=
- exposure_value) {
- shutter_time =
- exposure_value / analogue_gain;
+ stage < exposureMode_->gain.size(); stage++) {
+ if (!status_.fixedShutter) {
+ Duration stageShutter =
+ clipShutter(exposureMode_->shutter[stage]);
+ if (stageShutter * analogueGain >= exposureValue) {
+ shutterTime = exposureValue / analogueGain;
break;
}
- shutter_time = stage_shutter;
+ shutterTime = stageShutter;
}
- if (status_.fixed_analogue_gain == 0.0) {
- if (exposure_mode_->gain[stage] *
- shutter_time >=
- exposure_value) {
- analogue_gain =
- exposure_value / shutter_time;
+ if (status_.fixedAnalogueGain == 0.0) {
+ if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {
+ analogueGain = exposureValue / shutterTime;
break;
}
- analogue_gain = exposure_mode_->gain[stage];
+ analogueGain = exposureMode_->gain[stage];
}
}
}
- LOG(RPiAgc, Debug) << "Divided up shutter and gain are " << shutter_time << " and "
- << analogue_gain;
+ LOG(RPiAgc, Debug) << "Divided up shutter and gain are " << shutterTime << " and "
+ << analogueGain;
// Finally adjust shutter time for flicker avoidance (require both
// shutter and gain not to be fixed).
- if (!status_.fixed_shutter && !status_.fixed_analogue_gain &&
- status_.flicker_period) {
- int flicker_periods = shutter_time / status_.flicker_period;
- if (flicker_periods) {
- Duration new_shutter_time = flicker_periods * status_.flicker_period;
- analogue_gain *= shutter_time / new_shutter_time;
+ if (!status_.fixedShutter && !status_.fixedAnalogueGain &&
+ status_.flickerPeriod) {
+ int flickerPeriods = shutterTime / status_.flickerPeriod;
+ if (flickerPeriods) {
+ Duration newShutterTime = flickerPeriods * status_.flickerPeriod;
+ analogueGain *= shutterTime / newShutterTime;
// We should still not allow the ag to go over the
// largest value in the exposure mode. Note that this
// may force more of the total exposure into the digital
// gain as a side-effect.
- analogue_gain = std::min(analogue_gain,
- exposure_mode_->gain.back());
- shutter_time = new_shutter_time;
+ analogueGain = std::min(analogueGain, exposureMode_->gain.back());
+ shutterTime = newShutterTime;
}
LOG(RPiAgc, Debug) << "After flicker avoidance, shutter "
- << shutter_time << " gain " << analogue_gain;
+ << shutterTime << " gain " << analogueGain;
}
- filtered_.shutter = shutter_time;
- filtered_.analogue_gain = analogue_gain;
+ filtered_.shutter = shutterTime;
+ filtered_.analogueGain = analogueGain;
}
-void Agc::writeAndFinish(Metadata *image_metadata, bool desaturate)
+void Agc::writeAndFinish(Metadata *imageMetadata, bool desaturate)
{
- status_.total_exposure_value = filtered_.total_exposure;
- status_.target_exposure_value = desaturate ? 0s : target_.total_exposure_no_dg;
- status_.shutter_time = filtered_.shutter;
- status_.analogue_gain = filtered_.analogue_gain;
+ status_.totalExposureValue = filtered_.totalExposure;
+ status_.targetExposureValue = desaturate ? 0s : target_.totalExposureNoDG;
+ status_.shutterTime = filtered_.shutter;
+ status_.analogueGain = filtered_.analogueGain;
// Write to metadata as well, in case anyone wants to update the camera
// immediately.
- image_metadata->Set("agc.status", status_);
+ imageMetadata->set("agc.status", status_);
LOG(RPiAgc, Debug) << "Output written, total exposure requested is "
- << filtered_.total_exposure;
+ << filtered_.totalExposure;
LOG(RPiAgc, Debug) << "Camera exposure update: shutter time " << filtered_.shutter
- << " analogue gain " << filtered_.analogue_gain;
+ << " analogue gain " << filtered_.analogueGain;
}
Duration Agc::clipShutter(Duration shutter)
{
- if (max_shutter_)
- shutter = std::min(shutter, max_shutter_);
+ if (maxShutter_)
+ shutter = std::min(shutter, maxShutter_);
return shutter;
}
// Register algorithm with the system.
-static Algorithm *Create(Controller *controller)
+static Algorithm *create(Controller *controller)
{
return (Algorithm *)new Agc(controller);
}
-static RegisterAlgorithm reg(NAME, &Create);
+static RegisterAlgorithm reg(NAME, &create);