summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/raspberrypi/controller')
-rw-r--r--src/ipa/raspberrypi/controller/controller.h4
-rw-r--r--src/ipa/raspberrypi/controller/rpi/af.cpp10
-rw-r--r--src/ipa/raspberrypi/controller/rpi/af.h8
-rw-r--r--src/ipa/raspberrypi/controller/rpi/agc.cpp27
-rw-r--r--src/ipa/raspberrypi/controller/rpi/agc.h2
-rw-r--r--src/ipa/raspberrypi/controller/rpi/alsc.cpp32
-rw-r--r--src/ipa/raspberrypi/controller/rpi/alsc.h3
-rw-r--r--src/ipa/raspberrypi/controller/rpi/awb.cpp20
-rw-r--r--src/ipa/raspberrypi/controller/rpi/awb.h1
-rw-r--r--src/ipa/raspberrypi/controller/rpi/contrast.cpp8
-rw-r--r--src/ipa/raspberrypi/controller/rpi/focus.cpp7
-rw-r--r--src/ipa/raspberrypi/controller/rpi/lux.cpp14
12 files changed, 62 insertions, 74 deletions
diff --git a/src/ipa/raspberrypi/controller/controller.h b/src/ipa/raspberrypi/controller/controller.h
index 3e1e0517..e6c950c3 100644
--- a/src/ipa/raspberrypi/controller/controller.h
+++ b/src/ipa/raspberrypi/controller/controller.h
@@ -15,19 +15,17 @@
#include <vector>
#include <string>
-#include <linux/bcm2835-isp.h>
-
#include "libcamera/internal/yaml_parser.h"
#include "camera_mode.h"
#include "device_status.h"
#include "metadata.h"
+#include "statistics.h"
namespace RPiController {
class Algorithm;
typedef std::unique_ptr<Algorithm> AlgorithmPtr;
-typedef std::shared_ptr<bcm2835_isp_stats> StatisticsPtr;
/*
* The Controller holds a pointer to some global_metadata, which is how
diff --git a/src/ipa/raspberrypi/controller/rpi/af.cpp b/src/ipa/raspberrypi/controller/rpi/af.cpp
index 2e72f239..a6236518 100644
--- a/src/ipa/raspberrypi/controller/rpi/af.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/af.cpp
@@ -352,14 +352,12 @@ bool Af::getPhase(PdafData const &data, double &phase, double &conf) const
}
}
-double Af::getContrast(struct bcm2835_isp_stats_focus const focus_stats[FOCUS_REGIONS]) const
+double Af::getContrast(const FocusRegions &focusStats) const
{
uint32_t sumWc = 0;
- for (unsigned i = 0; i < FOCUS_REGIONS; ++i) {
- unsigned w = contrastWeights_[i];
- sumWc += w * (focus_stats[i].contrast_val[1][1] >> 10);
- }
+ for (unsigned i = 0; i < focusStats.numRegions(); ++i)
+ sumWc += contrastWeights_[i] * focusStats.get(i).val;
return (sumWeights_ == 0) ? 0.0 : (double)sumWc / (double)sumWeights_;
}
@@ -666,7 +664,7 @@ void Af::prepare(Metadata *imageMetadata)
void Af::process(StatisticsPtr &stats, [[maybe_unused]] Metadata *imageMetadata)
{
(void)imageMetadata;
- prevContrast_ = getContrast(stats->focus_stats);
+ prevContrast_ = getContrast(stats->focusRegions);
}
/* Controls */
diff --git a/src/ipa/raspberrypi/controller/rpi/af.h b/src/ipa/raspberrypi/controller/rpi/af.h
index f7baf897..7959371b 100644
--- a/src/ipa/raspberrypi/controller/rpi/af.h
+++ b/src/ipa/raspberrypi/controller/rpi/af.h
@@ -12,6 +12,12 @@
#include "../pwl.h"
/*
+ * \todo FOCUS_REGIONS is taken from bcm2835-isp.h, but should be made as a
+ * generic RegionStats structure.
+ */
+#define FOCUS_REGIONS 12
+
+/*
* This algorithm implements a hybrid of CDAF and PDAF, favouring PDAF.
*
* Whenever PDAF is available, it is used in a continuous feedback loop.
@@ -117,7 +123,7 @@ private:
void computeWeights();
bool getPhase(PdafData const &data, double &phase, double &conf) const;
- double getContrast(struct bcm2835_isp_stats_focus const focus_stats[FOCUS_REGIONS]) const;
+ double getContrast(const FocusRegions &focusStats) const;
void doPDAF(double phase, double conf);
bool earlyTerminationByPhase(double phase);
double findPeak(unsigned index) const;
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
index 46dcc81a..868c30f0 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
@@ -9,8 +9,6 @@
#include <map>
#include <tuple>
-#include <linux/bcm2835-isp.h>
-
#include <libcamera/base/log.h>
#include "../awb_status.h"
@@ -451,7 +449,7 @@ void Agc::process(StatisticsPtr &stats, Metadata *imageMetadata)
fetchCurrentExposure(imageMetadata);
/* Compute the total gain we require relative to the current exposure. */
double gain, targetY;
- computeGain(stats.get(), imageMetadata, gain, targetY);
+ computeGain(stats, imageMetadata, gain, targetY);
/* Now compute the target (final) exposure which we think we want. */
computeTargetExposure(gain);
/*
@@ -585,24 +583,23 @@ void Agc::fetchAwbStatus(Metadata *imageMetadata)
LOG(RPiAgc, Debug) << "No AWB status found";
}
-static double computeInitialY(bcm2835_isp_stats *stats, AwbStatus const &awb,
+static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb,
double weights[], double gain)
{
- bcm2835_isp_stats_region *regions = stats->agc_stats;
/*
* Note how the calculation below means that equal weights give you
* "average" metering (i.e. all pixels equally important).
*/
double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0;
- for (unsigned int i = 0; i < AgcStatsSize; i++) {
- double counted = regions[i].counted;
- double rAcc = std::min(regions[i].r_sum * gain, ((1 << PipelineBits) - 1) * counted);
- double gAcc = std::min(regions[i].g_sum * gain, ((1 << PipelineBits) - 1) * counted);
- double bAcc = std::min(regions[i].b_sum * gain, ((1 << PipelineBits) - 1) * counted);
+ for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) {
+ auto &region = stats->agcRegions.get(i);
+ double rAcc = std::min<double>(region.val.rSum * gain, ((1 << PipelineBits) - 1) * region.counted);
+ double gAcc = std::min<double>(region.val.gSum * gain, ((1 << PipelineBits) - 1) * region.counted);
+ double bAcc = std::min<double>(region.val.bSum * gain, ((1 << PipelineBits) - 1) * region.counted);
rSum += rAcc * weights[i];
gSum += gAcc * weights[i];
bSum += bAcc * weights[i];
- pixelSum += counted * weights[i];
+ pixelSum += region.counted * weights[i];
}
if (pixelSum == 0.0) {
LOG(RPiAgc, Warning) << "computeInitialY: pixelSum is zero";
@@ -624,23 +621,23 @@ static double computeInitialY(bcm2835_isp_stats *stats, AwbStatus const &awb,
static constexpr double EvGainYTargetLimit = 0.9;
-static double constraintComputeGain(AgcConstraint &c, Histogram &h, double lux,
+static double constraintComputeGain(AgcConstraint &c, const Histogram &h, double lux,
double evGain, double &targetY)
{
targetY = c.yTarget.eval(c.yTarget.domain().clip(lux));
targetY = std::min(EvGainYTargetLimit, targetY * evGain);
double iqm = h.interQuantileMean(c.qLo, c.qHi);
- return (targetY * NUM_HISTOGRAM_BINS) / iqm;
+ return (targetY * h.bins()) / iqm;
}
-void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata,
+void Agc::computeGain(StatisticsPtr &statistics, Metadata *imageMetadata,
double &gain, double &targetY)
{
struct LuxStatus lux = {};
lux.lux = 400; /* default lux level to 400 in case no metadata found */
if (imageMetadata->get("lux.status", lux) != 0)
LOG(RPiAgc, Warning) << "No lux level found";
- Histogram h(statistics->hist[0].g_hist, NUM_HISTOGRAM_BINS);
+ const Histogram &h = statistics->yHist;
double evGain = status_.ev * config_.baseEv;
/*
* The initial gain and target_Y come from some of the regions. After
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.h b/src/ipa/raspberrypi/controller/rpi/agc.h
index cf04da19..f04896ca 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.h
+++ b/src/ipa/raspberrypi/controller/rpi/agc.h
@@ -96,7 +96,7 @@ private:
void housekeepConfig();
void fetchCurrentExposure(Metadata *imageMetadata);
void fetchAwbStatus(Metadata *imageMetadata);
- void computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata,
+ void computeGain(StatisticsPtr &statistics, Metadata *imageMetadata,
double &gain, double &targetY);
void computeTargetExposure(double gain);
bool applyDigitalGain(double gain, double targetY);
diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.cpp b/src/ipa/raspberrypi/controller/rpi/alsc.cpp
index a4afaf84..eb4e2f94 100644
--- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp
@@ -310,19 +310,21 @@ double getCt(Metadata *metadata, double defaultCt)
return awbStatus.temperatureK;
}
-static void copyStats(bcm2835_isp_stats_region regions[XY], StatisticsPtr &stats,
+static void copyStats(RgbyRegions &regions, StatisticsPtr &stats,
AlscStatus const &status)
{
- bcm2835_isp_stats_region *inputRegions = stats->awb_stats;
+ if (!regions.numRegions())
+ regions.init(stats->awbRegions.size());
+
double *rTable = (double *)status.r;
double *gTable = (double *)status.g;
double *bTable = (double *)status.b;
- for (int i = 0; i < XY; i++) {
- regions[i].r_sum = inputRegions[i].r_sum / rTable[i];
- regions[i].g_sum = inputRegions[i].g_sum / gTable[i];
- regions[i].b_sum = inputRegions[i].b_sum / bTable[i];
- regions[i].counted = inputRegions[i].counted;
- /* (don't care about the uncounted value) */
+ for (unsigned int i = 0; i < stats->awbRegions.numRegions(); i++) {
+ auto r = stats->awbRegions.get(i);
+ r.val.rSum = static_cast<uint64_t>(r.val.rSum / rTable[i]);
+ r.val.gSum = static_cast<uint64_t>(r.val.gSum / gTable[i]);
+ r.val.bSum = static_cast<uint64_t>(r.val.bSum / bTable[i]);
+ regions.set(i, r);
}
}
@@ -512,19 +514,19 @@ void resampleCalTable(double const calTableIn[XY],
}
/* Calculate chrominance statistics (R/G and B/G) for each region. */
-static_assert(XY == AWB_REGIONS, "ALSC/AWB statistics region mismatch");
-static void calculateCrCb(bcm2835_isp_stats_region *awbRegion, double cr[XY],
+static void calculateCrCb(const RgbyRegions &awbRegion, double cr[XY],
double cb[XY], uint32_t minCount, uint16_t minG)
{
for (int i = 0; i < XY; i++) {
- bcm2835_isp_stats_region &zone = awbRegion[i];
- if (zone.counted <= minCount ||
- zone.g_sum / zone.counted <= minG) {
+ auto s = awbRegion.get(i);
+
+ if (s.counted <= minCount || s.val.gSum / s.counted <= minG) {
cr[i] = cb[i] = InsufficientData;
continue;
}
- cr[i] = zone.r_sum / (double)zone.g_sum;
- cb[i] = zone.b_sum / (double)zone.g_sum;
+
+ cr[i] = s.val.rSum / (double)s.val.gSum;
+ cb[i] = s.val.bSum / (double)s.val.gSum;
}
}
diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.h b/src/ipa/raspberrypi/controller/rpi/alsc.h
index a858ef5a..9167c9ff 100644
--- a/src/ipa/raspberrypi/controller/rpi/alsc.h
+++ b/src/ipa/raspberrypi/controller/rpi/alsc.h
@@ -12,6 +12,7 @@
#include "../algorithm.h"
#include "../alsc_status.h"
+#include "../statistics.h"
namespace RPiController {
@@ -98,7 +99,7 @@ private:
/* copy out the results from the async thread so that it can be restarted */
void fetchAsyncResults();
double ct_;
- bcm2835_isp_stats_region statistics_[AlscCellsY * AlscCellsX];
+ RgbyRegions statistics_;
double asyncResults_[3][AlscCellsY][AlscCellsX];
double asyncLambdaR_[AlscCellsX * AlscCellsY];
double asyncLambdaB_[AlscCellsX * AlscCellsY];
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp
index 04d1c878..ef3435d6 100644
--- a/src/ipa/raspberrypi/controller/rpi/awb.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/awb.cpp
@@ -21,9 +21,6 @@ LOG_DEFINE_CATEGORY(RPiAwb)
#define NAME "rpi.awb"
-static constexpr unsigned int AwbStatsSizeX = DEFAULT_AWB_REGIONS_X;
-static constexpr unsigned int AwbStatsSizeY = DEFAULT_AWB_REGIONS_Y;
-
/*
* todo - the locking in this algorithm needs some tidying up as has been done
* elsewhere (ALSC and AGC).
@@ -401,17 +398,16 @@ void Awb::asyncFunc()
}
static void generateStats(std::vector<Awb::RGB> &zones,
- bcm2835_isp_stats_region *stats, double minPixels,
+ RgbyRegions &stats, double minPixels,
double minG)
{
- for (unsigned int i = 0; i < AwbStatsSizeX * AwbStatsSizeY; i++) {
+ for (auto const &region : stats) {
Awb::RGB zone;
- double counted = stats[i].counted;
- if (counted >= minPixels) {
- zone.G = stats[i].g_sum / counted;
+ if (region.counted >= minPixels) {
+ zone.G = region.val.gSum / region.counted;
if (zone.G >= minG) {
- zone.R = stats[i].r_sum / counted;
- zone.B = stats[i].b_sum / counted;
+ zone.R = region.val.rSum / region.counted;
+ zone.B = region.val.bSum / region.counted;
zones.push_back(zone);
}
}
@@ -425,7 +421,7 @@ void Awb::prepareStats()
* LSC has already been applied to the stats in this pipeline, so stop
* any LSC compensation. We also ignore config_.fast in this version.
*/
- generateStats(zones_, statistics_->awb_stats, config_.minPixels,
+ generateStats(zones_, statistics_->awbRegions, config_.minPixels,
config_.minG);
/*
* apply sensitivities, so values appear to come from our "canonical"
@@ -641,7 +637,7 @@ void Awb::awbBayes()
* valid... not entirely sure about this.
*/
Pwl prior = interpolatePrior();
- prior *= zones_.size() / (double)(AwbStatsSizeX * AwbStatsSizeY);
+ prior *= zones_.size() / (double)(statistics_->awbRegions.numRegions());
prior.map([](double x, double y) {
LOG(RPiAwb, Debug) << "(" << x << "," << y << ")";
});
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.h b/src/ipa/raspberrypi/controller/rpi/awb.h
index 2254c3ed..e7d49cd8 100644
--- a/src/ipa/raspberrypi/controller/rpi/awb.h
+++ b/src/ipa/raspberrypi/controller/rpi/awb.h
@@ -13,6 +13,7 @@
#include "../awb_algorithm.h"
#include "../pwl.h"
#include "../awb_status.h"
+#include "../statistics.h"
namespace RPiController {
diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.cpp b/src/ipa/raspberrypi/controller/rpi/contrast.cpp
index 5b37edcb..a4f8c4f0 100644
--- a/src/ipa/raspberrypi/controller/rpi/contrast.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/contrast.cpp
@@ -106,7 +106,7 @@ Pwl computeStretchCurve(Histogram const &histogram,
* bit.
*/
double histLo = histogram.quantile(config.loHistogram) *
- (65536 / NUM_HISTOGRAM_BINS);
+ (65536 / histogram.bins());
double levelLo = config.loLevel * 65536;
LOG(RPiContrast, Debug)
<< "Move histogram point " << histLo << " to " << levelLo;
@@ -119,7 +119,7 @@ Pwl computeStretchCurve(Histogram const &histogram,
* Keep the mid-point (median) in the same place, though, to limit the
* apparent amount of global brightness shift.
*/
- double mid = histogram.quantile(0.5) * (65536 / NUM_HISTOGRAM_BINS);
+ double mid = histogram.quantile(0.5) * (65536 / histogram.bins());
enhance.append(mid, mid);
/*
@@ -127,7 +127,7 @@ Pwl computeStretchCurve(Histogram const &histogram,
* there up.
*/
double histHi = histogram.quantile(config.hiHistogram) *
- (65536 / NUM_HISTOGRAM_BINS);
+ (65536 / histogram.bins());
double levelHi = config.hiLevel * 65536;
LOG(RPiContrast, Debug)
<< "Move histogram point " << histHi << " to " << levelHi;
@@ -158,7 +158,7 @@ Pwl applyManualContrast(Pwl const &gammaCurve, double brightness,
void Contrast::process(StatisticsPtr &stats,
[[maybe_unused]] Metadata *imageMetadata)
{
- Histogram histogram(stats->hist[0].g_hist, NUM_HISTOGRAM_BINS);
+ Histogram &histogram = stats->yHist;
/*
* We look at the histogram and adjust the gamma curve in the following
* ways: 1. Adjust the gamma curve so as to pull the start of the
diff --git a/src/ipa/raspberrypi/controller/rpi/focus.cpp b/src/ipa/raspberrypi/controller/rpi/focus.cpp
index 8c5029bd..ea3cc00e 100644
--- a/src/ipa/raspberrypi/controller/rpi/focus.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/focus.cpp
@@ -31,10 +31,9 @@ char const *Focus::name() const
void Focus::process(StatisticsPtr &stats, Metadata *imageMetadata)
{
FocusStatus status;
- unsigned int i;
- for (i = 0; i < FOCUS_REGIONS; i++)
- status.focusMeasures[i] = stats->focus_stats[i].contrast_val[1][1] / 1000;
- status.num = i;
+ for (unsigned int i = 0; i < stats->focusRegions.numRegions(); i++)
+ status.focusMeasures[i] = stats->focusRegions.get(i).val;
+ status.num = stats->focusRegions.numRegions();
imageMetadata->set("focus.status", status);
LOG(RPiFocus, Debug)
diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp
index 9759186a..06625f3a 100644
--- a/src/ipa/raspberrypi/controller/rpi/lux.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp
@@ -6,8 +6,6 @@
*/
#include <math.h>
-#include <linux/bcm2835-isp.h>
-
#include <libcamera/base/log.h>
#include "../device_status.h"
@@ -83,20 +81,12 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata)
if (imageMetadata->get("device.status", deviceStatus) == 0) {
double currentGain = deviceStatus.analogueGain;
double currentAperture = deviceStatus.aperture.value_or(currentAperture_);
- uint64_t sum = 0;
- uint32_t num = 0;
- uint32_t *bin = stats->hist[0].g_hist;
- const int numBins = sizeof(stats->hist[0].g_hist) /
- sizeof(stats->hist[0].g_hist[0]);
- for (int i = 0; i < numBins; i++)
- sum += bin[i] * (uint64_t)i, num += bin[i];
- /* add .5 to reflect the mid-points of bins */
- double currentY = sum / (double)num + .5;
+ double currentY = stats->yHist.interQuantileMean(0, 1);
double gainRatio = referenceGain_ / currentGain;
double shutterSpeedRatio =
referenceShutterSpeed_ / deviceStatus.shutterSpeed;
double apertureRatio = referenceAperture_ / currentAperture;
- double yRatio = currentY * (65536 / numBins) / referenceY_;
+ double yRatio = currentY * (65536 / stats->yHist.bins()) / referenceY_;
double estimatedLux = shutterSpeedRatio * gainRatio *
apertureRatio * apertureRatio *
yRatio * referenceLux_;