ipa: ipu3: Move IPU3 agc into algorithms

Now that the interface is properly used by the AGC class, move it into
ipa::ipu3::algorithms and let the loops do the calls.
As we need to exchange the exposure_ and gain_ by passing them through the
FrameContext, use the calculated values in setControls() function to
ease the reading.

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:
Jean-Michel Hautbois 2021-08-18 17:54:03 +02:00
parent b145ae4242
commit 93802f600c
5 changed files with 28 additions and 32 deletions

View file

@ -5,7 +5,7 @@
* ipu3_agc.cpp - AGC/AEC control algorithm * ipu3_agc.cpp - AGC/AEC control algorithm
*/ */
#include "ipu3_agc.h" #include "agc.h"
#include <algorithm> #include <algorithm>
#include <chrono> #include <chrono>
@ -21,7 +21,7 @@ namespace libcamera {
using namespace std::literals::chrono_literals; using namespace std::literals::chrono_literals;
namespace ipa::ipu3 { namespace ipa::ipu3::algorithms {
LOG_DEFINE_CATEGORY(IPU3Agc) LOG_DEFINE_CATEGORY(IPU3Agc)
@ -50,14 +50,14 @@ static constexpr double kEvGainTarget = 0.5;
/* A cell is 8 bytes and contains averages for RGB values and saturation ratio */ /* A cell is 8 bytes and contains averages for RGB values and saturation ratio */
static constexpr uint8_t kCellSize = 8; static constexpr uint8_t kCellSize = 8;
IPU3Agc::IPU3Agc() Agc::Agc()
: frameCount_(0), lastFrame_(0), iqMean_(0.0), lineDuration_(0s), : frameCount_(0), lastFrame_(0), iqMean_(0.0), lineDuration_(0s),
maxExposureTime_(0s), prevExposure_(0s), prevExposureNoDg_(0s), maxExposureTime_(0s), prevExposure_(0s), prevExposureNoDg_(0s),
currentExposure_(0s), currentExposureNoDg_(0s) currentExposure_(0s), currentExposureNoDg_(0s)
{ {
} }
int IPU3Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo) int Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo)
{ {
aeGrid_ = context.configuration.grid.bdsGrid; aeGrid_ = context.configuration.grid.bdsGrid;
@ -68,7 +68,7 @@ int IPU3Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo)
return 0; return 0;
} }
void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats) void Agc::processBrightness(const ipu3_uapi_stats_3a *stats)
{ {
const struct ipu3_uapi_grid_config statsAeGrid = stats->stats_4a_config.awb_config.grid; const struct ipu3_uapi_grid_config statsAeGrid = stats->stats_4a_config.awb_config.grid;
Rectangle aeRegion = { statsAeGrid.x_start, Rectangle aeRegion = { statsAeGrid.x_start,
@ -109,7 +109,7 @@ void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats)
iqMean_ = Histogram(Span<uint32_t>(hist)).interQuantileMean(0.98, 1.0); iqMean_ = Histogram(Span<uint32_t>(hist)).interQuantileMean(0.98, 1.0);
} }
void IPU3Agc::filterExposure() void Agc::filterExposure()
{ {
double speed = 0.2; double speed = 0.2;
if (prevExposure_ == 0s) { if (prevExposure_ == 0s) {
@ -143,7 +143,7 @@ void IPU3Agc::filterExposure()
LOG(IPU3Agc, Debug) << "After filtering, total_exposure " << prevExposure_; LOG(IPU3Agc, Debug) << "After filtering, total_exposure " << prevExposure_;
} }
void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain) void Agc::lockExposureGain(uint32_t &exposure, double &gain)
{ {
/* 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 ?
@ -186,7 +186,7 @@ void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain)
lastFrame_ = frameCount_; lastFrame_ = frameCount_;
} }
void IPU3Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats) void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)
{ {
uint32_t &exposure = context.frameContext.agc.exposure; uint32_t &exposure = context.frameContext.agc.exposure;
double &gain = context.frameContext.agc.gain; double &gain = context.frameContext.agc.gain;
@ -195,6 +195,6 @@ void IPU3Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)
frameCount_++; frameCount_++;
} }
} /* namespace ipa::ipu3 */ } /* namespace ipa::ipu3::algorithms */
} /* namespace libcamera */ } /* namespace libcamera */

View file

@ -2,10 +2,10 @@
/* /*
* Copyright (C) 2021, Ideas On Board * Copyright (C) 2021, Ideas On Board
* *
* ipu3_agc.h - IPU3 AGC/AEC control algorithm * agc.h - IPU3 AGC/AEC control algorithm
*/ */
#ifndef __LIBCAMERA_IPU3_AGC_H__ #ifndef __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__
#define __LIBCAMERA_IPU3_AGC_H__ #define __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__
#include <linux/intel-ipu3.h> #include <linux/intel-ipu3.h>
@ -13,21 +13,21 @@
#include <libcamera/geometry.h> #include <libcamera/geometry.h>
#include "algorithms/algorithm.h" #include "algorithm.h"
namespace libcamera { namespace libcamera {
struct IPACameraSensorInfo; struct IPACameraSensorInfo;
namespace ipa::ipu3 { namespace ipa::ipu3::algorithms {
using utils::Duration; using utils::Duration;
class IPU3Agc : public Algorithm class Agc : public Algorithm
{ {
public: public:
IPU3Agc(); Agc();
~IPU3Agc() = default; ~Agc() = default;
int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override; void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override;
@ -53,8 +53,8 @@ private:
Duration currentExposureNoDg_; Duration currentExposureNoDg_;
}; };
} /* namespace ipa::ipu3 */ } /* namespace ipa::ipu3::algorithms */
} /* namespace libcamera */ } /* namespace libcamera */
#endif /* __LIBCAMERA_IPU3_AGC_H__ */ #endif /* __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__ */

View file

@ -1,6 +1,7 @@
# SPDX-License-Identifier: CC0-1.0 # SPDX-License-Identifier: CC0-1.0
ipu3_ipa_algorithms = files([ ipu3_ipa_algorithms = files([
'agc.cpp',
'algorithm.cpp', 'algorithm.cpp',
'awb.cpp', 'awb.cpp',
'tone_mapping.cpp', 'tone_mapping.cpp',

View file

@ -29,10 +29,10 @@
#include "libcamera/internal/mapped_framebuffer.h" #include "libcamera/internal/mapped_framebuffer.h"
#include "algorithms/agc.h"
#include "algorithms/algorithm.h" #include "algorithms/algorithm.h"
#include "algorithms/awb.h" #include "algorithms/awb.h"
#include "algorithms/tone_mapping.h" #include "algorithms/tone_mapping.h"
#include "ipu3_agc.h"
#include "libipa/camera_sensor_helper.h" #include "libipa/camera_sensor_helper.h"
/** /**
@ -187,8 +187,6 @@ private:
uint32_t minGain_; uint32_t minGain_;
uint32_t maxGain_; uint32_t maxGain_;
/* Interface to the AEC/AGC algorithm */
std::unique_ptr<IPU3Agc> agcAlgo_;
/* Interface to the Camera Helper */ /* Interface to the Camera Helper */
std::unique_ptr<CameraSensorHelper> camHelper_; std::unique_ptr<CameraSensorHelper> camHelper_;
@ -268,6 +266,7 @@ int IPAIPU3::init(const IPASettings &settings,
*ipaControls = ControlInfoMap(std::move(controls), controls::controls); *ipaControls = ControlInfoMap(std::move(controls), controls::controls);
/* Construct our Algorithms */ /* Construct our Algorithms */
algorithms_.push_back(std::make_unique<algorithms::Agc>());
algorithms_.push_back(std::make_unique<algorithms::Awb>()); algorithms_.push_back(std::make_unique<algorithms::Awb>());
algorithms_.push_back(std::make_unique<algorithms::ToneMapping>()); algorithms_.push_back(std::make_unique<algorithms::ToneMapping>());
@ -386,9 +385,6 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo)
return ret; return ret;
} }
agcAlgo_ = std::make_unique<IPU3Agc>();
agcAlgo_->configure(context_, configInfo);
return 0; return 0;
} }
@ -476,15 +472,12 @@ void IPAIPU3::parseStatistics(unsigned int frame,
{ {
ControlList ctrls(controls::controls); ControlList ctrls(controls::controls);
for (auto const &algo : algorithms_)
algo->process(context_, stats);
/* \todo These fields should not be written by the IPAIPU3 layer */ /* \todo These fields should not be written by the IPAIPU3 layer */
context_.frameContext.agc.gain = camHelper_->gain(gain_); context_.frameContext.agc.gain = camHelper_->gain(gain_);
context_.frameContext.agc.exposure = exposure_; context_.frameContext.agc.exposure = exposure_;
agcAlgo_->process(context_, stats);
exposure_ = context_.frameContext.agc.exposure; for (auto const &algo : algorithms_)
gain_ = camHelper_->gainCode(context_.frameContext.agc.gain); algo->process(context_, stats);
setControls(frame); setControls(frame);
@ -505,6 +498,9 @@ void IPAIPU3::setControls(unsigned int frame)
IPU3Action op; IPU3Action op;
op.op = ActionSetSensorControls; op.op = ActionSetSensorControls;
exposure_ = context_.frameContext.agc.exposure;
gain_ = camHelper_->gainCode(context_.frameContext.agc.gain);
ControlList ctrls(ctrls_); ControlList ctrls(ctrls_);
ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure_)); ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure_));
ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain_)); ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain_));

View file

@ -6,7 +6,6 @@ ipa_name = 'ipa_ipu3'
ipu3_ipa_sources = files([ ipu3_ipa_sources = files([
'ipu3.cpp', 'ipu3.cpp',
'ipu3_agc.cpp',
]) ])
ipu3_ipa_sources += ipu3_ipa_algorithms ipu3_ipa_sources += ipu3_ipa_algorithms