From 503bebd0ed80886569629e7ce11d40fa28721c84 Mon Sep 17 00:00:00 2001 From: David Plowman Date: Wed, 3 May 2023 13:20:32 +0100 Subject: [PATCH] ipa: raspberrypi: agc: Move weights out of AGC The region weights for the the AGC zones are handled by the AGC algorithm. Apply them directly in the IPA (vc4.cpp) to the statistics that we pass to the AGC. Signed-off-by: David Plowman Signed-off-by: Naushir Patuck Reviewed-by: Jacopo Mondi Signed-off-by: Laurent Pinchart --- src/ipa/rpi/controller/agc_algorithm.h | 3 +++ src/ipa/rpi/controller/rpi/agc.cpp | 27 +++++++++++++++++--------- src/ipa/rpi/controller/rpi/agc.h | 1 + src/ipa/rpi/vc4/vc4.cpp | 26 ++++++++++++++++++------- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/ipa/rpi/controller/agc_algorithm.h b/src/ipa/rpi/controller/agc_algorithm.h index 36e6c1105..b6949daa7 100644 --- a/src/ipa/rpi/controller/agc_algorithm.h +++ b/src/ipa/rpi/controller/agc_algorithm.h @@ -6,6 +6,8 @@ */ #pragma once +#include + #include #include "algorithm.h" @@ -18,6 +20,7 @@ public: AgcAlgorithm(Controller *controller) : Algorithm(controller) {} /* An AGC algorithm must provide the following: */ virtual unsigned int getConvergenceFrames() const = 0; + virtual std::vector const &getWeights() const = 0; virtual void setEv(double ev) = 0; virtual void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) = 0; virtual void setFixedShutter(libcamera::utils::Duration fixedShutter) = 0; diff --git a/src/ipa/rpi/controller/rpi/agc.cpp b/src/ipa/rpi/controller/rpi/agc.cpp index e6fb7b8db..e79c82e2e 100644 --- a/src/ipa/rpi/controller/rpi/agc.cpp +++ b/src/ipa/rpi/controller/rpi/agc.cpp @@ -292,6 +292,18 @@ unsigned int Agc::getConvergenceFrames() const return config_.convergenceFrames; } +std::vector const &Agc::getWeights() const +{ + /* + * In case someone calls setMeteringMode and then this before the + * algorithm has run and updated the meteringMode_ pointer. + */ + auto it = config_.meteringModes.find(meteringModeName_); + if (it == config_.meteringModes.end()) + return meteringMode_->weights; + return it->second.weights; +} + void Agc::setEv(double ev) { ev_ = ev; @@ -595,19 +607,16 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, ASSERT(weights.size() == stats->agcRegions.numRegions()); /* - * Note how the calculation below means that equal weights give you - * "average" metering (i.e. all pixels equally important). + * Note that the weights are applied by the IPA to the statistics directly, + * before they are given to us here. */ double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0; for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) { auto ®ion = stats->agcRegions.get(i); - double rAcc = std::min(region.val.rSum * gain, (maxVal - 1) * region.counted); - double gAcc = std::min(region.val.gSum * gain, (maxVal - 1) * region.counted); - double bAcc = std::min(region.val.bSum * gain, (maxVal - 1) * region.counted); - rSum += rAcc * weights[i]; - gSum += gAcc * weights[i]; - bSum += bAcc * weights[i]; - pixelSum += region.counted * weights[i]; + rSum += std::min(region.val.rSum * gain, (maxVal - 1) * region.counted); + gSum += std::min(region.val.gSum * gain, (maxVal - 1) * region.counted); + bSum += std::min(region.val.bSum * gain, (maxVal - 1) * region.counted); + pixelSum += region.counted; } if (pixelSum == 0.0) { LOG(RPiAgc, Warning) << "computeInitialY: pixelSum is zero"; diff --git a/src/ipa/rpi/controller/rpi/agc.h b/src/ipa/rpi/controller/rpi/agc.h index 4e5f272fa..939f97295 100644 --- a/src/ipa/rpi/controller/rpi/agc.h +++ b/src/ipa/rpi/controller/rpi/agc.h @@ -69,6 +69,7 @@ public: char const *name() const override; int read(const libcamera::YamlObject ¶ms) override; unsigned int getConvergenceFrames() const override; + std::vector const &getWeights() const override; void setEv(double ev) override; void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) override; void setMaxShutter(libcamera::utils::Duration maxShutter) override; diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp index a32db9bca..e38024ac5 100644 --- a/src/ipa/rpi/vc4/vc4.cpp +++ b/src/ipa/rpi/vc4/vc4.cpp @@ -211,13 +211,25 @@ RPiController::StatisticsPtr IpaVc4::platformProcessStats(Span mem) stats->awb_stats[i].counted, stats->awb_stats[i].notcounted }); - statistics->agcRegions.init(hw.agcRegions); - for (i = 0; i < statistics->agcRegions.numRegions(); i++) - statistics->agcRegions.set(i, { { stats->agc_stats[i].r_sum << scale, - stats->agc_stats[i].g_sum << scale, - stats->agc_stats[i].b_sum << scale }, - stats->agc_stats[i].counted, - stats->awb_stats[i].notcounted }); + RPiController::AgcAlgorithm *agc = dynamic_cast( + controller_.getAlgorithm("agc")); + if (!agc) { + LOG(IPARPI, Debug) << "No AGC algorithm - not copying statistics"; + statistics->agcRegions.init(0); + } else { + statistics->agcRegions.init(hw.agcRegions); + const std::vector &weights = agc->getWeights(); + for (i = 0; i < statistics->agcRegions.numRegions(); i++) { + uint64_t rSum = (stats->agc_stats[i].r_sum << scale) * weights[i]; + uint64_t gSum = (stats->agc_stats[i].g_sum << scale) * weights[i]; + uint64_t bSum = (stats->agc_stats[i].b_sum << scale) * weights[i]; + uint32_t counted = stats->agc_stats[i].counted * weights[i]; + uint32_t notcounted = stats->agc_stats[i].notcounted * weights[i]; + statistics->agcRegions.set(i, { { rSum, gSum, bSum }, + counted, + notcounted }); + } + } statistics->focusRegions.init(hw.focusRegions); for (i = 0; i < statistics->focusRegions.numRegions(); i++)