ipa: raspberrypi: Change to C style code comments
As part of the on-going refactor efforts for the source files in src/ipa/raspberrypi/, switch all C++ style comments to C style comments. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
177df04d2b
commit
acd5d9979f
55 changed files with 887 additions and 630 deletions
|
@ -28,7 +28,7 @@ LOG_DEFINE_CATEGORY(RPiAgc)
|
|||
|
||||
#define NAME "rpi.agc"
|
||||
|
||||
#define PIPELINE_BITS 13 // seems to be a 13-bit pipeline
|
||||
#define PIPELINE_BITS 13 /* seems to be a 13-bit pipeline */
|
||||
|
||||
void AgcMeteringMode::read(boost::property_tree::ptree const ¶ms)
|
||||
{
|
||||
|
@ -150,7 +150,7 @@ void AgcConfig::read(boost::property_tree::ptree const ¶ms)
|
|||
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.
|
||||
/* Start with quite a low value as ramping up is easier than ramping down. */
|
||||
defaultExposureTime = params.get<double>("default_exposure_time", 1000) * 1us;
|
||||
defaultAnalogueGain = params.get<double>("default_analogueGain", 1.0);
|
||||
}
|
||||
|
@ -170,8 +170,10 @@ Agc::Agc(Controller *controller)
|
|||
maxShutter_(0s), fixedShutter_(0s), fixedAnalogueGain_(0.0)
|
||||
{
|
||||
memset(&awb_, 0, sizeof(awb_));
|
||||
// Setting status_.totalExposureValue_ to zero initially tells us
|
||||
// it's not been calculated yet (i.e. Process hasn't yet run).
|
||||
/*
|
||||
* 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_;
|
||||
}
|
||||
|
@ -185,16 +187,18 @@ void Agc::read(boost::property_tree::ptree const ¶ms)
|
|||
{
|
||||
LOG(RPiAgc, Debug) << "Agc";
|
||||
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)
|
||||
/*
|
||||
* 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)
|
||||
*/
|
||||
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".
|
||||
/* Set up the "last shutter/gain" values, in case AGC starts "disabled". */
|
||||
status_.shutterTime = config_.defaultExposureTime;
|
||||
status_.analogueGain = config_.defaultAnalogueGain;
|
||||
}
|
||||
|
@ -218,8 +222,10 @@ void Agc::resume()
|
|||
|
||||
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 shutter and gain have been explicitly set, there is no
|
||||
* convergence to happen, so no need to drop any frames - return zero.
|
||||
*/
|
||||
if (fixedShutter_ && fixedAnalogueGain_)
|
||||
return 0;
|
||||
else
|
||||
|
@ -244,14 +250,14 @@ void Agc::setMaxShutter(Duration maxShutter)
|
|||
void Agc::setFixedShutter(Duration fixedShutter)
|
||||
{
|
||||
fixedShutter_ = fixedShutter;
|
||||
// Set this in case someone calls Pause() straight after.
|
||||
/* Set this in case someone calls Pause() straight after. */
|
||||
status_.shutterTime = clipShutter(fixedShutter_);
|
||||
}
|
||||
|
||||
void Agc::setFixedAnalogueGain(double fixedAnalogueGain)
|
||||
{
|
||||
fixedAnalogueGain_ = fixedAnalogueGain;
|
||||
// Set this in case someone calls Pause() straight after.
|
||||
/* Set this in case someone calls Pause() straight after. */
|
||||
status_.analogueGain = fixedAnalogueGain;
|
||||
}
|
||||
|
||||
|
@ -280,30 +286,32 @@ void Agc::switchMode(CameraMode const &cameraMode,
|
|||
|
||||
Duration fixedShutter = clipShutter(fixedShutter_);
|
||||
if (fixedShutter && fixedAnalogueGain_) {
|
||||
// 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);
|
||||
double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
|
||||
ASSERT(minColourGain != 0.0);
|
||||
|
||||
// This is the equivalent of computeTargetExposure and applyDigitalGain.
|
||||
/* This is the equivalent of computeTargetExposure and applyDigitalGain. */
|
||||
target_.totalExposureNoDG = fixedShutter_ * fixedAnalogueGain_;
|
||||
target_.totalExposure = target_.totalExposureNoDG / minColourGain;
|
||||
|
||||
// Equivalent of filterExposure. This resets any "history".
|
||||
/* Equivalent of filterExposure. This resets any "history". */
|
||||
filtered_ = target_;
|
||||
|
||||
// Equivalent of divideUpExposure.
|
||||
/* Equivalent of divideUpExposure. */
|
||||
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
|
||||
// - the new mode's sensitivity might be different
|
||||
// We cope with the last of these by scaling the target values. After
|
||||
// that we just need to re-divide the exposure/gain according to the
|
||||
// current exposure profile, which takes care of everything else.
|
||||
/*
|
||||
* On a mode switch, various things could happen:
|
||||
* - the exposure profile might change
|
||||
* - a fixed exposure or gain might be set
|
||||
* - the new mode's sensitivity might be different
|
||||
* We cope with the last of these by scaling the target values. After
|
||||
* that we just need to re-divide the exposure/gain according to the
|
||||
* current exposure profile, which takes care of everything else.
|
||||
*/
|
||||
|
||||
double ratio = lastSensitivity_ / cameraMode.sensitivity;
|
||||
target_.totalExposureNoDG *= ratio;
|
||||
|
@ -313,29 +321,31 @@ void Agc::switchMode(CameraMode const &cameraMode,
|
|||
|
||||
divideUpExposure();
|
||||
} 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.
|
||||
/*
|
||||
* 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.
|
||||
/* Equivalent of divideUpExposure. */
|
||||
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.
|
||||
/* We must remember the sensitivity of this mode for the next SwitchMode. */
|
||||
lastSensitivity_ = cameraMode.sensitivity;
|
||||
}
|
||||
|
||||
void Agc::prepare(Metadata *imageMetadata)
|
||||
{
|
||||
status_.digitalGain = 1.0;
|
||||
fetchAwbStatus(imageMetadata); // always fetch it so that Process knows it's been done
|
||||
fetchAwbStatus(imageMetadata); /* always fetch it so that Process knows it's been done */
|
||||
|
||||
if (status_.totalExposureValue) {
|
||||
// Process has run, so we have meaningful values.
|
||||
/* Process has run, so we have meaningful values. */
|
||||
DeviceStatus deviceStatus;
|
||||
if (imageMetadata->get("device.status", deviceStatus) == 0) {
|
||||
Duration actualExposure = deviceStatus.shutterSpeed *
|
||||
|
@ -343,14 +353,16 @@ void Agc::prepare(Metadata *imageMetadata)
|
|||
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?
|
||||
/*
|
||||
* Never ask for a gain < 1.0, and also impose
|
||||
* some upper limit. Make it customisable?
|
||||
*/
|
||||
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 "
|
||||
<< actualExposure * status_.digitalGain;
|
||||
// Decide whether AEC/AGC has converged.
|
||||
/* Decide whether AEC/AGC has converged. */
|
||||
updateLockStatus(deviceStatus);
|
||||
}
|
||||
} else
|
||||
|
@ -362,44 +374,52 @@ void Agc::prepare(Metadata *imageMetadata)
|
|||
void Agc::process(StatisticsPtr &stats, Metadata *imageMetadata)
|
||||
{
|
||||
frameCount_++;
|
||||
// First a little bit of housekeeping, fetching up-to-date settings and
|
||||
// configuration, that kind of thing.
|
||||
/*
|
||||
* 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.
|
||||
/* Get the current exposure values for the frame that's just arrived. */
|
||||
fetchCurrentExposure(imageMetadata);
|
||||
// Compute the total gain we require relative to the current exposure.
|
||||
/* Compute the total gain we require relative to the current exposure. */
|
||||
double gain, targetY;
|
||||
computeGain(stats.get(), imageMetadata, gain, targetY);
|
||||
// Now compute the target (final) exposure which we think we want.
|
||||
/* 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.
|
||||
/*
|
||||
* 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, targetY);
|
||||
// The results have to be filtered so as not to change too rapidly.
|
||||
/* 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.
|
||||
/*
|
||||
* The last thing is to divide up the exposure value into a shutter time
|
||||
* and analogue gain, according to the current exposure mode.
|
||||
*/
|
||||
divideUpExposure();
|
||||
// Finally advertise what we've done.
|
||||
/* Finally advertise what we've done. */
|
||||
writeAndFinish(imageMetadata, desaturate);
|
||||
}
|
||||
|
||||
void Agc::updateLockStatus(DeviceStatus const &deviceStatus)
|
||||
{
|
||||
const double errorFactor = 0.10; // make these customisable?
|
||||
const double errorFactor = 0.10; /* make these customisable? */
|
||||
const int maxLockCount = 5;
|
||||
// Reset "lock count" when we exceed this multiple of errorFactor
|
||||
/* 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.
|
||||
/* Add 200us to the exposure time error to allow for line quantisation. */
|
||||
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.
|
||||
/*
|
||||
* 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 (deviceStatus.shutterSpeed > lastDeviceStatus_.shutterSpeed - exposureError &&
|
||||
deviceStatus.shutterSpeed < lastDeviceStatus_.shutterSpeed + exposureError &&
|
||||
deviceStatus.analogueGain > lastDeviceStatus_.analogueGain - gainError &&
|
||||
|
@ -430,7 +450,7 @@ static void copyString(std::string const &s, char *d, size_t size)
|
|||
|
||||
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_.fixedShutter = clipShutter(fixedShutter_);
|
||||
status_.fixedAnalogueGain = fixedAnalogueGain_;
|
||||
|
@ -438,8 +458,10 @@ void Agc::housekeepConfig()
|
|||
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.
|
||||
/*
|
||||
* Make sure the "mode" pointers point to the up-to-date things, if
|
||||
* they've changed.
|
||||
*/
|
||||
if (strcmp(meteringModeName_.c_str(), status_.meteringMode)) {
|
||||
auto it = config_.meteringModes.find(meteringModeName_);
|
||||
if (it == config_.meteringModes.end())
|
||||
|
@ -491,7 +513,7 @@ void Agc::fetchCurrentExposure(Metadata *imageMetadata)
|
|||
|
||||
void Agc::fetchAwbStatus(Metadata *imageMetadata)
|
||||
{
|
||||
awb_.gainR = 1.0; // in case not found in metadata
|
||||
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)
|
||||
|
@ -502,8 +524,10 @@ 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).
|
||||
/*
|
||||
* Note how the calculation below means that equal weights give you
|
||||
* "average" metering (i.e. all pixels equally important).
|
||||
*/
|
||||
double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0;
|
||||
for (int i = 0; i < AGC_STATS_SIZE; i++) {
|
||||
double counted = regions[i].counted;
|
||||
|
@ -525,11 +549,13 @@ static double computeInitialY(bcm2835_isp_stats *stats, AwbStatus const &awb,
|
|||
return ySum / pixelSum / (1 << PIPELINE_BITS);
|
||||
}
|
||||
|
||||
// We handle extra gain through EV by adjusting our Y targets. However, you
|
||||
// simply can't monitor histograms once they get very close to (or beyond!)
|
||||
// saturation, so we clamp the Y targets to this value. It does mean that EV
|
||||
// increases don't necessarily do quite what you might expect in certain
|
||||
// (contrived) cases.
|
||||
/*
|
||||
* We handle extra gain through EV by adjusting our Y targets. However, you
|
||||
* simply can't monitor histograms once they get very close to (or beyond!)
|
||||
* saturation, so we clamp the Y targets to this value. It does mean that EV
|
||||
* increases don't necessarily do quite what you might expect in certain
|
||||
* (contrived) cases.
|
||||
*/
|
||||
|
||||
#define EV_GAIN_Y_TARGET_LIMIT 0.9
|
||||
|
||||
|
@ -546,18 +572,22 @@ 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
|
||||
lux.lux = 400; /* default lux level to 400 in case no metadata found */
|
||||
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 evGain = status_.ev * config_.baseEv;
|
||||
// The initial gain and target_Y come from some of the regions. After
|
||||
// that we consider the histogram constraints.
|
||||
/*
|
||||
* The initial gain and target_Y come from some of the regions. After
|
||||
* that we consider the histogram constraints.
|
||||
*/
|
||||
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.
|
||||
/*
|
||||
* 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 initialY = computeInitialY(statistics, awb_, meteringMode_->weights, gain);
|
||||
|
@ -565,7 +595,7 @@ void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata,
|
|||
gain *= extraGain;
|
||||
LOG(RPiAgc, Debug) << "Initial Y " << initialY << " target " << targetY
|
||||
<< " gives gain " << gain;
|
||||
if (extraGain < 1.01) // close enough
|
||||
if (extraGain < 1.01) /* close enough */
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -592,20 +622,23 @@ void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata,
|
|||
void Agc::computeTargetExposure(double 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/minColourGain. Otherwise we'd desaturate channels causing
|
||||
// white to go cyan or magenta.
|
||||
/*
|
||||
* 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/minColourGain. Otherwise we'd desaturate channels causing
|
||||
* white to go cyan or magenta.
|
||||
*/
|
||||
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:
|
||||
/*
|
||||
* The statistics reflect the image without digital gain, so the final
|
||||
* total exposure we're aiming for is:
|
||||
*/
|
||||
target_.totalExposure = current_.totalExposureNoDG * gain;
|
||||
// The final target exposure is also limited to what the exposure
|
||||
// mode allows.
|
||||
/* The final target exposure is also limited to what the exposure mode allows. */
|
||||
Duration maxShutter = status_.fixedShutter
|
||||
? status_.fixedShutter
|
||||
: exposureMode_->shutter.back();
|
||||
|
@ -625,17 +658,21 @@ bool Agc::applyDigitalGain(double gain, double targetY)
|
|||
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.
|
||||
/*
|
||||
* 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 " << 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
|
||||
// larger than 1.0. When this happens, demand a large digital gain so
|
||||
// that the exposure can be reduced, de-saturating the image much more
|
||||
// quickly (and we then approach the correct value more quickly from
|
||||
// below).
|
||||
/*
|
||||
* 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
|
||||
* larger than 1.0. When this happens, demand a large digital gain so
|
||||
* 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 = targetY > config_.fastReduceThreshold &&
|
||||
gain < sqrt(targetY);
|
||||
if (desaturate)
|
||||
|
@ -649,8 +686,10 @@ bool Agc::applyDigitalGain(double gain, double targetY)
|
|||
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.
|
||||
/*
|
||||
* AGC adapts instantly if both shutter and gain are directly specified
|
||||
* or we're in the startup phase.
|
||||
*/
|
||||
if ((status_.fixedShutter && status_.fixedAnalogueGain) ||
|
||||
frameCount_ <= config_.startupFrames)
|
||||
speed = 1.0;
|
||||
|
@ -658,15 +697,19 @@ void Agc::filterExposure(bool desaturate)
|
|||
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 close to the result go faster, to save making so many
|
||||
* micro-adjustments on the way. (Make this customisable?)
|
||||
*/
|
||||
if (filtered_.totalExposure < 1.2 * target_.totalExposure &&
|
||||
filtered_.totalExposure > 0.8 * target_.totalExposure)
|
||||
speed = sqrt(speed);
|
||||
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.
|
||||
/*
|
||||
* When desaturing, take a big jump down in totalExposureNoDG,
|
||||
* which we'll hide with digital gain.
|
||||
*/
|
||||
if (desaturate)
|
||||
filtered_.totalExposureNoDG =
|
||||
target_.totalExposureNoDG;
|
||||
|
@ -675,9 +718,11 @@ void Agc::filterExposure(bool desaturate)
|
|||
speed * target_.totalExposureNoDG +
|
||||
filtered_.totalExposureNoDG * (1.0 - speed);
|
||||
}
|
||||
// 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).
|
||||
/*
|
||||
* 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_.totalExposureNoDG <
|
||||
filtered_.totalExposure * config_.fastReduceThreshold)
|
||||
filtered_.totalExposureNoDG = filtered_.totalExposure * config_.fastReduceThreshold;
|
||||
|
@ -687,9 +732,11 @@ void Agc::filterExposure(bool desaturate)
|
|||
|
||||
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.
|
||||
/*
|
||||
* 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 exposureValue = filtered_.totalExposureNoDG;
|
||||
Duration shutterTime;
|
||||
double analogueGain;
|
||||
|
@ -721,18 +768,22 @@ void Agc::divideUpExposure()
|
|||
}
|
||||
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).
|
||||
/*
|
||||
* Finally adjust shutter time for flicker avoidance (require both
|
||||
* shutter and gain not to be fixed).
|
||||
*/
|
||||
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.
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
analogueGain = std::min(analogueGain, exposureMode_->gain.back());
|
||||
shutterTime = newShutterTime;
|
||||
}
|
||||
|
@ -749,8 +800,10 @@ void Agc::writeAndFinish(Metadata *imageMetadata, bool desaturate)
|
|||
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.
|
||||
/*
|
||||
* Write to metadata as well, in case anyone wants to update the camera
|
||||
* immediately.
|
||||
*/
|
||||
imageMetadata->set("agc.status", status_);
|
||||
LOG(RPiAgc, Debug) << "Output written, total exposure requested is "
|
||||
<< filtered_.totalExposure;
|
||||
|
@ -765,7 +818,7 @@ Duration Agc::clipShutter(Duration shutter)
|
|||
return shutter;
|
||||
}
|
||||
|
||||
// Register algorithm with the system.
|
||||
/* Register algorithm with the system. */
|
||||
static Algorithm *create(Controller *controller)
|
||||
{
|
||||
return (Algorithm *)new Agc(controller);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue