mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-13 15:29:45 +03:00
ipa: ipu3: convert AGC to the new algorithm interface
In preparation for using the AGC through the new algorithm interfaces, convert the existing code to use the new function types. Now that the process call is rewritten, re-enable the compiler flag to warn when a function declaration hides virtual functions from a base class (-Woverloaded-virtual). We never use converged_ so remove its declaration. The controls may not need to be updated at each call, but it should be decided on the context side and not by a specific call by using a lock status in the Agc structure for instance. As the params_ local variable is not useful anymore, remove it here too. Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
4eb4073ec7
commit
16266def40
5 changed files with 45 additions and 38 deletions
|
@ -108,10 +108,6 @@ if cc.has_argument('-Wno-c99-designator')
|
||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Do not warn when a function declaration hides virtual functions from
|
|
||||||
# a base class
|
|
||||||
cpp_arguments += '-Wno-overloaded-virtual'
|
|
||||||
|
|
||||||
c_arguments += common_arguments
|
c_arguments += common_arguments
|
||||||
cpp_arguments += common_arguments
|
cpp_arguments += common_arguments
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,11 @@ struct IPASessionConfiguration {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IPAFrameContext {
|
struct IPAFrameContext {
|
||||||
|
struct {
|
||||||
|
uint32_t exposure;
|
||||||
|
double gain;
|
||||||
|
} agc;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
double red;
|
double red;
|
||||||
|
|
|
@ -92,6 +92,22 @@
|
||||||
* \brief BDS output size configured by the pipeline handler
|
* \brief BDS output size configured by the pipeline handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct IPAFrameContext::agc
|
||||||
|
* \brief Context for the Automatic Gain Control algorithm
|
||||||
|
*
|
||||||
|
* The exposure and gain determined are expected to be applied to the sensor
|
||||||
|
* at the earliest opportunity.
|
||||||
|
*
|
||||||
|
* \var IPAFrameContext::agc::exposure
|
||||||
|
* \brief Exposure time expressed as a number of lines
|
||||||
|
*
|
||||||
|
* \var IPAFrameContext::agc::gain
|
||||||
|
* \brief Analogue gain multiplier
|
||||||
|
*
|
||||||
|
* The gain should be adapted to the sensor specific gain code before applying.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \struct IPAFrameContext::awb
|
* \struct IPAFrameContext::awb
|
||||||
* \brief Context for the Automatic White Balance algorithm
|
* \brief Context for the Automatic White Balance algorithm
|
||||||
|
@ -183,7 +199,6 @@ private:
|
||||||
|
|
||||||
/* Local parameter storage */
|
/* Local parameter storage */
|
||||||
struct IPAContext context_;
|
struct IPAContext context_;
|
||||||
struct ipu3_uapi_params params_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -361,8 +376,7 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo)
|
||||||
|
|
||||||
defVBlank_ = itVBlank->second.def().get<int32_t>();
|
defVBlank_ = itVBlank->second.def().get<int32_t>();
|
||||||
|
|
||||||
/* Clean context and IPU3 parameters at configuration */
|
/* Clean context at configuration */
|
||||||
params_ = {};
|
|
||||||
context_ = {};
|
context_ = {};
|
||||||
|
|
||||||
calculateBdsGrid(configInfo.bdsOutputSize);
|
calculateBdsGrid(configInfo.bdsOutputSize);
|
||||||
|
@ -375,7 +389,7 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo)
|
||||||
|
|
||||||
awbAlgo_ = std::make_unique<IPU3Awb>();
|
awbAlgo_ = std::make_unique<IPU3Awb>();
|
||||||
agcAlgo_ = std::make_unique<IPU3Agc>();
|
agcAlgo_ = std::make_unique<IPU3Agc>();
|
||||||
agcAlgo_->initialise(context_.configuration.grid.bdsGrid, sensorInfo_);
|
agcAlgo_->configure(context_, configInfo);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -450,12 +464,9 @@ void IPAIPU3::processControls([[maybe_unused]] unsigned int frame,
|
||||||
void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params)
|
void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params)
|
||||||
{
|
{
|
||||||
for (auto const &algo : algorithms_)
|
for (auto const &algo : algorithms_)
|
||||||
algo->prepare(context_, ¶ms_);
|
algo->prepare(context_, params);
|
||||||
|
|
||||||
if (agcAlgo_->updateControls())
|
awbAlgo_->prepare(context_, params);
|
||||||
awbAlgo_->prepare(context_, ¶ms_);
|
|
||||||
|
|
||||||
*params = params_;
|
|
||||||
|
|
||||||
IPU3Action op;
|
IPU3Action op;
|
||||||
op.op = ActionParamFilled;
|
op.op = ActionParamFilled;
|
||||||
|
@ -472,13 +483,15 @@ void IPAIPU3::parseStatistics(unsigned int frame,
|
||||||
for (auto const &algo : algorithms_)
|
for (auto const &algo : algorithms_)
|
||||||
algo->process(context_, stats);
|
algo->process(context_, stats);
|
||||||
|
|
||||||
double gain = camHelper_->gain(gain_);
|
/* \todo These fields should not be written by the IPAIPU3 layer */
|
||||||
agcAlgo_->process(stats, exposure_, gain);
|
context_.frameContext.agc.gain = camHelper_->gain(gain_);
|
||||||
gain_ = camHelper_->gainCode(gain);
|
context_.frameContext.agc.exposure = exposure_;
|
||||||
|
agcAlgo_->process(context_, stats);
|
||||||
|
exposure_ = context_.frameContext.agc.exposure;
|
||||||
|
gain_ = camHelper_->gainCode(context_.frameContext.agc.gain);
|
||||||
|
|
||||||
awbAlgo_->process(context_, stats);
|
awbAlgo_->process(context_, stats);
|
||||||
|
|
||||||
if (agcAlgo_->updateControls())
|
|
||||||
setControls(frame);
|
setControls(frame);
|
||||||
|
|
||||||
/* \todo Use VBlank value calculated from each frame exposure. */
|
/* \todo Use VBlank value calculated from each frame exposure. */
|
||||||
|
|
|
@ -51,20 +51,21 @@ static constexpr double kEvGainTarget = 0.5;
|
||||||
static constexpr uint8_t kCellSize = 8;
|
static constexpr uint8_t kCellSize = 8;
|
||||||
|
|
||||||
IPU3Agc::IPU3Agc()
|
IPU3Agc::IPU3Agc()
|
||||||
: frameCount_(0), lastFrame_(0), converged_(false),
|
: frameCount_(0), lastFrame_(0), iqMean_(0.0), lineDuration_(0s),
|
||||||
updateControls_(false), iqMean_(0.0),
|
maxExposureTime_(0s), prevExposure_(0s), prevExposureNoDg_(0s),
|
||||||
lineDuration_(0s), maxExposureTime_(0s),
|
|
||||||
prevExposure_(0s), prevExposureNoDg_(0s),
|
|
||||||
currentExposure_(0s), currentExposureNoDg_(0s)
|
currentExposure_(0s), currentExposureNoDg_(0s)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPU3Agc::initialise(struct ipu3_uapi_grid_config &bdsGrid, const IPACameraSensorInfo &sensorInfo)
|
int IPU3Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo)
|
||||||
{
|
{
|
||||||
aeGrid_ = bdsGrid;
|
aeGrid_ = context.configuration.grid.bdsGrid;
|
||||||
|
|
||||||
lineDuration_ = sensorInfo.lineLength * 1.0s / sensorInfo.pixelRate;
|
lineDuration_ = configInfo.sensorInfo.lineLength * 1.0s
|
||||||
|
/ configInfo.sensorInfo.pixelRate;
|
||||||
maxExposureTime_ = kMaxExposure * lineDuration_;
|
maxExposureTime_ = kMaxExposure * lineDuration_;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats)
|
void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats)
|
||||||
|
@ -144,8 +145,6 @@ void IPU3Agc::filterExposure()
|
||||||
|
|
||||||
void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain)
|
void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain)
|
||||||
{
|
{
|
||||||
updateControls_ = false;
|
|
||||||
|
|
||||||
/* Algorithm initialization should wait for first valid frames */
|
/* Algorithm initialization should wait for first valid frames */
|
||||||
/* \todo - have a number of frames given by DelayedControls ?
|
/* \todo - have a number of frames given by DelayedControls ?
|
||||||
* - implement a function for IIR */
|
* - implement a function for IIR */
|
||||||
|
@ -155,7 +154,6 @@ void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain)
|
||||||
/* Are we correctly exposed ? */
|
/* Are we correctly exposed ? */
|
||||||
if (std::abs(iqMean_ - kEvGainTarget * knumHistogramBins) <= 1) {
|
if (std::abs(iqMean_ - kEvGainTarget * knumHistogramBins) <= 1) {
|
||||||
LOG(IPU3Agc, Debug) << "!!! Good exposure with iqMean = " << iqMean_;
|
LOG(IPU3Agc, Debug) << "!!! Good exposure with iqMean = " << iqMean_;
|
||||||
converged_ = true;
|
|
||||||
} else {
|
} else {
|
||||||
double newGain = kEvGainTarget * knumHistogramBins / iqMean_;
|
double newGain = kEvGainTarget * knumHistogramBins / iqMean_;
|
||||||
|
|
||||||
|
@ -178,20 +176,20 @@ void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain)
|
||||||
exposure = std::clamp(static_cast<uint32_t>(exposure * currentExposure_ / currentExposureNoDg_), kMinExposure, kMaxExposure);
|
exposure = std::clamp(static_cast<uint32_t>(exposure * currentExposure_ / currentExposureNoDg_), kMinExposure, kMaxExposure);
|
||||||
newExposure = currentExposure_ / exposure;
|
newExposure = currentExposure_ / exposure;
|
||||||
gain = std::clamp(static_cast<uint32_t>(gain * currentExposure_ / newExposure), kMinGain, kMaxGain);
|
gain = std::clamp(static_cast<uint32_t>(gain * currentExposure_ / newExposure), kMinGain, kMaxGain);
|
||||||
updateControls_ = true;
|
|
||||||
} else if (currentShutter >= maxExposureTime_) {
|
} else if (currentShutter >= maxExposureTime_) {
|
||||||
gain = std::clamp(static_cast<uint32_t>(gain * currentExposure_ / currentExposureNoDg_), kMinGain, kMaxGain);
|
gain = std::clamp(static_cast<uint32_t>(gain * currentExposure_ / currentExposureNoDg_), kMinGain, kMaxGain);
|
||||||
newExposure = currentExposure_ / gain;
|
newExposure = currentExposure_ / gain;
|
||||||
exposure = std::clamp(static_cast<uint32_t>(exposure * currentExposure_ / newExposure), kMinExposure, kMaxExposure);
|
exposure = std::clamp(static_cast<uint32_t>(exposure * currentExposure_ / newExposure), kMinExposure, kMaxExposure);
|
||||||
updateControls_ = true;
|
|
||||||
}
|
}
|
||||||
LOG(IPU3Agc, Debug) << "Adjust exposure " << exposure * lineDuration_ << " and gain " << gain;
|
LOG(IPU3Agc, Debug) << "Adjust exposure " << exposure * lineDuration_ << " and gain " << gain;
|
||||||
}
|
}
|
||||||
lastFrame_ = frameCount_;
|
lastFrame_ = frameCount_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPU3Agc::process(const ipu3_uapi_stats_3a *stats, uint32_t &exposure, double &gain)
|
void IPU3Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)
|
||||||
{
|
{
|
||||||
|
uint32_t &exposure = context.frameContext.agc.exposure;
|
||||||
|
double &gain = context.frameContext.agc.gain;
|
||||||
processBrightness(stats);
|
processBrightness(stats);
|
||||||
lockExposureGain(exposure, gain);
|
lockExposureGain(exposure, gain);
|
||||||
frameCount_++;
|
frameCount_++;
|
||||||
|
|
|
@ -29,10 +29,8 @@ public:
|
||||||
IPU3Agc();
|
IPU3Agc();
|
||||||
~IPU3Agc() = default;
|
~IPU3Agc() = default;
|
||||||
|
|
||||||
void initialise(struct ipu3_uapi_grid_config &bdsGrid, const IPACameraSensorInfo &sensorInfo);
|
int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
|
||||||
void process(const ipu3_uapi_stats_3a *stats, uint32_t &exposure, double &gain);
|
void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override;
|
||||||
bool converged() { return converged_; }
|
|
||||||
bool updateControls() { return updateControls_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processBrightness(const ipu3_uapi_stats_3a *stats);
|
void processBrightness(const ipu3_uapi_stats_3a *stats);
|
||||||
|
@ -44,9 +42,6 @@ private:
|
||||||
uint64_t frameCount_;
|
uint64_t frameCount_;
|
||||||
uint64_t lastFrame_;
|
uint64_t lastFrame_;
|
||||||
|
|
||||||
bool converged_;
|
|
||||||
bool updateControls_;
|
|
||||||
|
|
||||||
double iqMean_;
|
double iqMean_;
|
||||||
|
|
||||||
Duration lineDuration_;
|
Duration lineDuration_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue