mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-15 08:25:07 +03:00
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:
parent
2db8a767ca
commit
6914fc487f
8 changed files with 93 additions and 73 deletions
|
@ -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 : "
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ¶ms)
|
boost::property_tree::ptree const ¶ms)
|
||||||
{
|
{
|
||||||
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 ¶ms)
|
||||||
|
{
|
||||||
|
for (auto &p : params)
|
||||||
|
list.push_back(p.second.get_value<double>() * 1us);
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
void AgcExposureMode::Read(boost::property_tree::ptree const ¶ms)
|
void AgcExposureMode::Read(boost::property_tree::ptree const ¶ms)
|
||||||
{
|
{
|
||||||
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 ¶ms)
|
||||||
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_);
|
||||||
|
|
|
@ -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 ¶ms);
|
void Read(boost::property_tree::ptree const ¶ms);
|
||||||
};
|
};
|
||||||
|
|
||||||
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 ¶ms);
|
void Read(boost::property_tree::ptree const ¶ms);
|
||||||
};
|
};
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 ¶ms)
|
void Lux::Read(boost::property_tree::ptree const ¶ms)
|
||||||
{
|
{
|
||||||
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 *
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue