ipa: raspberrypi: Switch the AGC/Lux code to use utils::Duration

Convert the core AGC and Lux controller code to use
utils::Duration for all exposure time related variables and
calculations.

Convert the exposure/shutter time fields in AgcStatus and DeviceStatus
to use utils::Duration.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Naushir Patuck 2021-06-08 12:03:35 +01:00 committed by Laurent Pinchart
parent 2db8a767ca
commit 6914fc487f
8 changed files with 93 additions and 73 deletions

View file

@ -184,7 +184,7 @@ void CamHelper::parseEmbeddedData(Span<const uint8_t> buffer,
return; return;
} }
deviceStatus.shutter_speed = Exposure(exposureLines).get<std::micro>(); deviceStatus.shutter_speed = Exposure(exposureLines);
deviceStatus.analogue_gain = Gain(gainCode); deviceStatus.analogue_gain = Gain(gainCode);
LOG(IPARPI, Debug) << "Metadata updated - Exposure : " LOG(IPARPI, Debug) << "Metadata updated - Exposure : "

View file

@ -6,6 +6,8 @@
*/ */
#pragma once #pragma once
#include "libcamera/internal/utils.h"
// The AGC algorithm should post the following structure into the image's // The AGC algorithm should post the following structure into the image's
// "agc.status" metadata. // "agc.status" metadata.
@ -18,17 +20,17 @@ extern "C" {
// ignored until then. // ignored until then.
struct AgcStatus { struct AgcStatus {
double total_exposure_value; // value for all exposure and gain for this image libcamera::utils::Duration total_exposure_value; // value for all exposure and gain for this image
double target_exposure_value; // (unfiltered) target total exposure AGC is aiming for libcamera::utils::Duration target_exposure_value; // (unfiltered) target total exposure AGC is aiming for
double shutter_time; libcamera::utils::Duration shutter_time;
double analogue_gain; double analogue_gain;
char exposure_mode[32]; char exposure_mode[32];
char constraint_mode[32]; char constraint_mode[32];
char metering_mode[32]; char metering_mode[32];
double ev; double ev;
double flicker_period; libcamera::utils::Duration flicker_period;
int floating_region_enable; int floating_region_enable;
double fixed_shutter; libcamera::utils::Duration fixed_shutter;
double fixed_analogue_gain; double fixed_analogue_gain;
double digital_gain; double digital_gain;
int locked; int locked;

View file

@ -6,6 +6,8 @@
*/ */
#pragma once #pragma once
#include "libcamera/internal/utils.h"
// Definition of "device metadata" which stores things like shutter time and // Definition of "device metadata" which stores things like shutter time and
// analogue gain that downstream control algorithms will want to know. // analogue gain that downstream control algorithms will want to know.
@ -14,8 +16,8 @@ extern "C" {
#endif #endif
struct DeviceStatus { struct DeviceStatus {
// time shutter is open, in microseconds // time shutter is open
double shutter_speed; libcamera::utils::Duration shutter_speed;
double analogue_gain; double analogue_gain;
// 1.0/distance-in-metres, or 0 if unknown // 1.0/distance-in-metres, or 0 if unknown
double lens_position; double lens_position;

View file

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

View file

@ -9,6 +9,8 @@
#include <vector> #include <vector>
#include <mutex> #include <mutex>
#include "libcamera/internal/utils.h"
#include "../agc_algorithm.hpp" #include "../agc_algorithm.hpp"
#include "../agc_status.h" #include "../agc_status.h"
#include "../pwl.hpp" #include "../pwl.hpp"
@ -22,13 +24,15 @@
namespace RPiController { namespace RPiController {
using namespace std::literals::chrono_literals;
struct AgcMeteringMode { struct AgcMeteringMode {
double weights[AGC_STATS_SIZE]; double weights[AGC_STATS_SIZE];
void Read(boost::property_tree::ptree const &params); void Read(boost::property_tree::ptree const &params);
}; };
struct AgcExposureMode { struct AgcExposureMode {
std::vector<double> shutter; std::vector<libcamera::utils::Duration> shutter;
std::vector<double> gain; std::vector<double> gain;
void Read(boost::property_tree::ptree const &params); void Read(boost::property_tree::ptree const &params);
}; };
@ -61,7 +65,7 @@ struct AgcConfig {
std::string default_exposure_mode; std::string default_exposure_mode;
std::string default_constraint_mode; std::string default_constraint_mode;
double base_ev; double base_ev;
double default_exposure_time; libcamera::utils::Duration default_exposure_time;
double default_analogue_gain; double default_analogue_gain;
}; };
@ -101,19 +105,19 @@ private:
void filterExposure(bool desaturate); void filterExposure(bool desaturate);
void divideUpExposure(); void divideUpExposure();
void writeAndFinish(Metadata *image_metadata, bool desaturate); void writeAndFinish(Metadata *image_metadata, bool desaturate);
double clipShutter(double shutter); libcamera::utils::Duration clipShutter(libcamera::utils::Duration shutter);
AgcMeteringMode *metering_mode_; AgcMeteringMode *metering_mode_;
AgcExposureMode *exposure_mode_; AgcExposureMode *exposure_mode_;
AgcConstraintMode *constraint_mode_; AgcConstraintMode *constraint_mode_;
uint64_t frame_count_; uint64_t frame_count_;
AwbStatus awb_; AwbStatus awb_;
struct ExposureValues { struct ExposureValues {
ExposureValues() : shutter(0), analogue_gain(0), ExposureValues() : shutter(0s), analogue_gain(0),
total_exposure(0), total_exposure_no_dg(0) {} total_exposure(0s), total_exposure_no_dg(0s) {}
double shutter; libcamera::utils::Duration shutter;
double analogue_gain; double analogue_gain;
double total_exposure; libcamera::utils::Duration total_exposure;
double total_exposure_no_dg; // without digital gain libcamera::utils::Duration total_exposure_no_dg; // without digital gain
}; };
ExposureValues current_; // values for the current frame ExposureValues current_; // values for the current frame
ExposureValues target_; // calculate the values we want here ExposureValues target_; // calculate the values we want here
@ -121,15 +125,15 @@ private:
AgcStatus status_; AgcStatus status_;
int lock_count_; int lock_count_;
DeviceStatus last_device_status_; DeviceStatus last_device_status_;
double last_target_exposure_; libcamera::utils::Duration last_target_exposure_;
// Below here the "settings" that applications can change. // Below here the "settings" that applications can change.
std::string metering_mode_name_; std::string metering_mode_name_;
std::string exposure_mode_name_; std::string exposure_mode_name_;
std::string constraint_mode_name_; std::string constraint_mode_name_;
double ev_; double ev_;
double flicker_period_; libcamera::utils::Duration flicker_period_;
double max_shutter_; libcamera::utils::Duration max_shutter_;
double fixed_shutter_; libcamera::utils::Duration fixed_shutter_;
double fixed_analogue_gain_; double fixed_analogue_gain_;
}; };

View file

@ -16,6 +16,7 @@
using namespace RPiController; using namespace RPiController;
using namespace libcamera; using namespace libcamera;
using namespace std::literals::chrono_literals;
LOG_DEFINE_CATEGORY(RPiLux) LOG_DEFINE_CATEGORY(RPiLux)
@ -38,7 +39,7 @@ char const *Lux::Name() const
void Lux::Read(boost::property_tree::ptree const &params) void Lux::Read(boost::property_tree::ptree const &params)
{ {
reference_shutter_speed_ = reference_shutter_speed_ =
params.get<double>("reference_shutter_speed"); params.get<double>("reference_shutter_speed") * 1.0us;
reference_gain_ = params.get<double>("reference_gain"); reference_gain_ = params.get<double>("reference_gain");
reference_aperture_ = params.get<double>("reference_aperture", 1.0); reference_aperture_ = params.get<double>("reference_aperture", 1.0);
reference_Y_ = params.get<double>("reference_Y"); reference_Y_ = params.get<double>("reference_Y");
@ -60,15 +61,15 @@ void Lux::Prepare(Metadata *image_metadata)
void Lux::Process(StatisticsPtr &stats, Metadata *image_metadata) void Lux::Process(StatisticsPtr &stats, Metadata *image_metadata)
{ {
// set some initial values to shut the compiler up // set some initial values to shut the compiler up
DeviceStatus device_status = DeviceStatus device_status = {
{ .shutter_speed = 1.0, .shutter_speed = 1.0ms,
.analogue_gain = 1.0, .analogue_gain = 1.0,
.lens_position = 0.0, .lens_position = 0.0,
.aperture = 0.0, .aperture = 0.0,
.flash_intensity = 0.0 }; .flash_intensity = 0.0
};
if (image_metadata->Get("device.status", device_status) == 0) { if (image_metadata->Get("device.status", device_status) == 0) {
double current_gain = device_status.analogue_gain; double current_gain = device_status.analogue_gain;
double current_shutter_speed = device_status.shutter_speed;
double current_aperture = device_status.aperture; double current_aperture = device_status.aperture;
if (current_aperture == 0) if (current_aperture == 0)
current_aperture = current_aperture_; current_aperture = current_aperture_;
@ -83,7 +84,7 @@ void Lux::Process(StatisticsPtr &stats, Metadata *image_metadata)
double current_Y = sum / (double)num + .5; double current_Y = sum / (double)num + .5;
double gain_ratio = reference_gain_ / current_gain; double gain_ratio = reference_gain_ / current_gain;
double shutter_speed_ratio = double shutter_speed_ratio =
reference_shutter_speed_ / current_shutter_speed; reference_shutter_speed_ / device_status.shutter_speed;
double aperture_ratio = reference_aperture_ / current_aperture; double aperture_ratio = reference_aperture_ / current_aperture;
double Y_ratio = current_Y * (65536 / num_bins) / reference_Y_; double Y_ratio = current_Y * (65536 / num_bins) / reference_Y_;
double estimated_lux = shutter_speed_ratio * gain_ratio * double estimated_lux = shutter_speed_ratio * gain_ratio *

View file

@ -8,6 +8,8 @@
#include <mutex> #include <mutex>
#include "libcamera/internal/utils.h"
#include "../lux_status.h" #include "../lux_status.h"
#include "../algorithm.hpp" #include "../algorithm.hpp"
@ -28,7 +30,7 @@ public:
private: private:
// These values define the conditions of the reference image, against // These values define the conditions of the reference image, against
// which we compare the new image. // which we compare the new image.
double reference_shutter_speed_; // in micro-seconds libcamera::utils::Duration reference_shutter_speed_;
double reference_gain_; double reference_gain_;
double reference_aperture_; // units of 1/f double reference_aperture_; // units of 1/f
double reference_Y_; // out of 65536 double reference_Y_; // out of 65536

View file

@ -222,11 +222,11 @@ void IPARPi::start(const ControlList &controls, ipa::RPi::StartConfig *startConf
/* SwitchMode may supply updated exposure/gain values to use. */ /* SwitchMode may supply updated exposure/gain values to use. */
AgcStatus agcStatus; AgcStatus agcStatus;
agcStatus.shutter_time = 0.0; agcStatus.shutter_time = 0.0s;
agcStatus.analogue_gain = 0.0; agcStatus.analogue_gain = 0.0;
metadata.Get("agc.status", agcStatus); metadata.Get("agc.status", agcStatus);
if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) { if (agcStatus.shutter_time && agcStatus.analogue_gain) {
ControlList ctrls(sensorCtrls_); ControlList ctrls(sensorCtrls_);
applyAGC(&agcStatus, ctrls); applyAGC(&agcStatus, ctrls);
startConfig->controls = std::move(ctrls); startConfig->controls = std::move(ctrls);
@ -389,7 +389,7 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo,
/* Supply initial values for gain and exposure. */ /* Supply initial values for gain and exposure. */
ControlList ctrls(sensorCtrls_); ControlList ctrls(sensorCtrls_);
AgcStatus agcStatus; AgcStatus agcStatus;
agcStatus.shutter_time = DefaultExposureTime.get<std::micro>(); agcStatus.shutter_time = DefaultExposureTime;
agcStatus.analogue_gain = DefaultAnalogueGain; agcStatus.analogue_gain = DefaultAnalogueGain;
applyAGC(&agcStatus, ctrls); applyAGC(&agcStatus, ctrls);
@ -461,7 +461,8 @@ void IPARPi::reportMetadata()
*/ */
DeviceStatus *deviceStatus = rpiMetadata_.GetLocked<DeviceStatus>("device.status"); DeviceStatus *deviceStatus = rpiMetadata_.GetLocked<DeviceStatus>("device.status");
if (deviceStatus) { if (deviceStatus) {
libcameraMetadata_.set(controls::ExposureTime, deviceStatus->shutter_speed); libcameraMetadata_.set(controls::ExposureTime,
deviceStatus->shutter_speed.get<std::micro>());
libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogue_gain); libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogue_gain);
} }
@ -1014,7 +1015,7 @@ void IPARPi::fillDeviceStatus(const ControlList &sensorControls)
int32_t exposureLines = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); int32_t exposureLines = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
int32_t gainCode = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); int32_t gainCode = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
deviceStatus.shutter_speed = helper_->Exposure(exposureLines).get<std::micro>(); deviceStatus.shutter_speed = helper_->Exposure(exposureLines);
deviceStatus.analogue_gain = helper_->Gain(gainCode); deviceStatus.analogue_gain = helper_->Gain(gainCode);
LOG(IPARPI, Debug) << "Metadata - Exposure : " LOG(IPARPI, Debug) << "Metadata - Exposure : "
@ -1099,7 +1100,7 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
int32_t gainCode = helper_->GainCode(agcStatus->analogue_gain); int32_t gainCode = helper_->GainCode(agcStatus->analogue_gain);
/* GetVBlanking might clip exposure time to the fps limits. */ /* GetVBlanking might clip exposure time to the fps limits. */
Duration exposure = agcStatus->shutter_time * 1.0us; Duration exposure = agcStatus->shutter_time;
int32_t vblanking = helper_->GetVBlanking(exposure, minFrameDuration_, maxFrameDuration_); int32_t vblanking = helper_->GetVBlanking(exposure, minFrameDuration_, maxFrameDuration_);
int32_t exposureLines = helper_->ExposureLines(exposure); int32_t exposureLines = helper_->ExposureLines(exposure);