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:
Naushir Patuck 2022-07-27 09:55:18 +01:00 committed by Laurent Pinchart
parent 177df04d2b
commit acd5d9979f
55 changed files with 887 additions and 630 deletions

View file

@ -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 &params)
{
@ -150,7 +150,7 @@ void AgcConfig::read(boost::property_tree::ptree const &params)
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 &params)
{
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);