@@ -7,7 +7,12 @@
#include "agc.h"
+#include <variant>
+
#include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
+#include <libipa/histogram.h>
namespace libcamera {
@@ -15,38 +20,119 @@ LOG_DEFINE_CATEGORY(IPASoftExposure)
namespace ipa::soft::algorithms {
-int Agc::init(IPAContext &context, [[maybe_unused]] const ValueNode &tuningData)
+namespace {
+
+class AgcTraits : public AgcMeanLuminance::Traits
{
- return agc_.configure(context.configuration.agc.simple, context.activeState.agc.simple, {
+public:
+ AgcTraits(const SwIspStats &stats)
+ : stats_(stats)
+ {
+ }
+
+ double estimateLuminance(double gain) const override
+ {
+ double sum = 0;
+ double count = 0;
+
+ for (const auto &[i, cnt] : utils::enumerate(stats_.yHistogram)) {
+ sum += std::min(1.0, gain * i / stats_.yHistogram.size()) * cnt;
+ count += cnt;
+ }
+
+ return sum / count;
+ }
+
+private:
+ const SwIspStats &stats_;
+};
+
+}
+
+int Agc::init(IPAContext &context, const ValueNode &tuningData)
+{
+ const AgcAlgorithm::ConfigurationParams config = {
.sensor = context.camHelper.get(),
.sensorInfo = context.sensorInfo,
.sensorControls = context.sensorControls,
.ctrlMap = context.ctrlMap,
.autoAllowed = true,
- });
+ };
+
+ if (config.sensor)
+ agc_.emplace<AgcMeanLuminanceAlgorithm>();
+ else
+ agc_.emplace<AgcSimpleAlgorithm>();
+
+ return std::visit(utils::overloaded {
+ [&](AgcSimpleAlgorithm &impl) {
+ return impl.configure(context.configuration.agc.simple,
+ context.activeState.agc.simple,
+ config);
+ },
+ [&](AgcMeanLuminanceAlgorithm &impl) {
+ int ret = impl.init(tuningData);
+ if (ret)
+ return ret;
+
+ return impl.configure(context.configuration.agc.ml,
+ context.activeState.agc.ml,
+ config);
+ },
+ }, agc_);
}
int Agc::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo)
{
- return agc_.configure(context.configuration.agc.simple, context.activeState.agc.simple, {
+ const AgcAlgorithm::ConfigurationParams config = {
.sensor = context.camHelper.get(),
.sensorInfo = context.sensorInfo,
.sensorControls = context.sensorControls,
.ctrlMap = context.ctrlMap,
- .autoAllowed = true, // \todo not if raw?
- });
+ .autoAllowed = true, // \todo if not raw?
+ };
+
+ return std::visit(utils::overloaded {
+ [&](AgcSimpleAlgorithm &impl) {
+ return impl.configure(context.configuration.agc.simple,
+ context.activeState.agc.simple,
+ config);
+ },
+ [&](AgcMeanLuminanceAlgorithm &impl) {
+ return impl.configure(context.configuration.agc.ml,
+ context.activeState.agc.ml,
+ config);
+ },
+ }, agc_);
}
void Agc::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame, IPAFrameContext &frameContext, const ControlList &controls)
{
- agc_.queueRequest(context.configuration.agc.simple, context.activeState.agc.simple,
- frameContext.agc.simple, controls);
+ std::visit(utils::overloaded {
+ [&](AgcSimpleAlgorithm &impl) {
+ impl.queueRequest(context.configuration.agc.simple,
+ context.activeState.agc.simple,
+ frameContext.agc.simple, controls);
+ },
+ [&](AgcMeanLuminanceAlgorithm &impl) {
+ impl.queueRequest(context.configuration.agc.ml,
+ context.activeState.agc.ml,
+ frameContext.agc.ml, controls);
+ },
+ }, agc_);
}
void Agc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
{
- agc_.prepare(context.activeState.agc.simple, frameContext.agc.simple);
+ std::visit(utils::overloaded {
+ [&](AgcSimpleAlgorithm &impl) {
+ impl.prepare(context.activeState.agc.simple, frameContext.agc.simple);
+ },
+ [&](AgcMeanLuminanceAlgorithm &impl) {
+ impl.prepare(context.activeState.agc.ml, frameContext.agc.ml);
+ },
+ }, agc_);
}
void Agc::process(IPAContext &context,
@@ -55,20 +141,43 @@ void Agc::process(IPAContext &context,
const SwIspStats *stats,
ControlList &metadata)
{
- if (stats->valid) {
- agc_.process(context.configuration.agc.simple, context.activeState.agc.simple, frameContext.agc.simple, {{
- .exposure = frameContext.sensor.exposure,
- .gain = frameContext.sensor.gain,
- .stats = *stats,
- .blackLevel = context.activeState.blc.level,
- }}, metadata);
- } else {
- agc_.process(context.configuration.agc.simple, context.activeState.agc.simple,
- frameContext.agc.simple, {}, metadata);
- }
+ std::visit(utils::overloaded {
+ [&](AgcSimpleAlgorithm &impl) {
+ if (stats->valid) {
+ impl.process(context.configuration.agc.simple, context.activeState.agc.simple, frameContext.agc.simple, {{
+ .exposure = frameContext.sensor.exposure,
+ .gain = frameContext.sensor.gain,
+ .stats = *stats,
+ .blackLevel = context.activeState.blc.level,
+ }}, metadata);
+ } else {
+ impl.process(context.configuration.agc.simple, context.activeState.agc.simple,
+ frameContext.agc.simple, {}, metadata);
+ }
+
+ frameContext.agc.exposure = frameContext.agc.simple.exposure;
+ frameContext.agc.gain = frameContext.agc.simple.gain;
+ },
+ [&](AgcMeanLuminanceAlgorithm &impl) {
+ if (stats->valid) {
+ Histogram hist(stats->yHistogram);
+
+ impl.process(context.configuration.agc.ml, context.activeState.agc.ml, frameContext.agc.ml, {{
+ .traits = AgcTraits(*stats),
+ .hist = hist,
+ .exposure = uint32_t(frameContext.sensor.exposure),
+ .gain = frameContext.sensor.gain,
+ }}, metadata);
+
+ } else {
+ impl.process(context.configuration.agc.ml, context.activeState.agc.ml,
+ frameContext.agc.ml, {}, metadata);
+ }
- frameContext.agc.exposure = frameContext.agc.simple.exposure;
- frameContext.agc.gain = frameContext.agc.simple.gain;
+ frameContext.agc.exposure = frameContext.agc.ml.exposure;
+ frameContext.agc.gain = frameContext.agc.ml.gain;
+ },
+ }, agc_);
}
REGISTER_IPA_ALGORITHM(Agc, "Agc")
@@ -7,6 +7,10 @@
#pragma once
+#include <variant>
+
+#include <libipa/agc_mean_luminance.h>
+
#include "algorithm.h"
#include "agc_simple.h"
@@ -30,7 +34,10 @@ public:
ControlList &metadata) override;
private:
- AgcSimpleAlgorithm agc_;
+ std::variant<
+ AgcSimpleAlgorithm,
+ AgcMeanLuminanceAlgorithm
+ > agc_;
};
} /* namespace ipa::soft::algorithms */
@@ -15,6 +15,7 @@
#include "libcamera/internal/matrix.h"
#include "libcamera/internal/vector.h"
+#include <libipa/agc_mean_luminance.h>
#include <libipa/camera_sensor_helper.h>
#include <libipa/fc_queue.h>
@@ -29,6 +30,7 @@ namespace ipa::soft {
struct IPASessionConfiguration {
struct {
AgcSimpleAlgorithm::Session simple;
+ AgcMeanLuminanceAlgorithm::Session ml;
double again10, againMinStep;
} agc;
struct {
@@ -39,6 +41,7 @@ struct IPASessionConfiguration {
struct IPAActiveState {
struct {
AgcSimpleAlgorithm::ActiveState simple;
+ AgcMeanLuminanceAlgorithm::ActiveState ml;
} agc;
struct {
@@ -67,6 +70,7 @@ struct IPAFrameContext : public FrameContext {
struct {
AgcSimpleAlgorithm::FrameContext simple;
+ AgcMeanLuminanceAlgorithm::FrameContext ml;
int32_t exposure;
double gain;
} agc;
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> --- src/ipa/simple/algorithms/agc.cpp | 153 +++++++++++++++++++++++++----- src/ipa/simple/algorithms/agc.h | 9 +- src/ipa/simple/ipa_context.h | 4 + 3 files changed, 143 insertions(+), 23 deletions(-)