[libcamera-devel] [PATCH v1 4/5] ipa: raspberrypi: Use the generic statistics structure in the algorithms

Naushir Patuck naush at raspberrypi.com
Wed Nov 23 15:53:03 CET 2022


Hi David,

Thank you for your feedback.

On Wed, 23 Nov 2022 at 14:34, David Plowman <david.plowman at raspberrypi.com>
wrote:

> Hi Naush
>
> Thanks for all these updates!
>
> On Tue, 22 Nov 2022 at 11:22, Naushir Patuck via libcamera-devel
> <libcamera-devel at lists.libcamera.org> wrote:
> >
> > Repurpose the StatisticsPtr type from being a
> shared_ptr<bcm2835_isp_stats> to
> > shared_ptr<RPiController::Statistics>. This removes any hardware
> specific header
> > files and structures from the algorithms source code.
> >
> > Add a new function in the Raspberry Pi IPA to populate the generic
> statistics
> > structure from the values provided by the hardware in the
> bcm2835_isp_stats
> > structure.
> >
> > Update the Lux, AWB, AGC, ALCS, Contrast, and Focus algorithms to use the
>
> s/ALCS/ALSC/  I think, I get muddled too!
>
> > generic statistics structure appropriately in their calculations.
> Additionally,
> > remove references to any hardware specific headers and defines in these
> source
> > files.
> >
> > Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
> > ---
> >  src/ipa/raspberrypi/controller/controller.h   |  4 +-
> >  src/ipa/raspberrypi/controller/rpi/agc.cpp    | 26 ++++++-------
> >  src/ipa/raspberrypi/controller/rpi/agc.h      |  2 +-
> >  src/ipa/raspberrypi/controller/rpi/alsc.cpp   | 33 +++++++++-------
> >  src/ipa/raspberrypi/controller/rpi/alsc.h     |  3 +-
> >  src/ipa/raspberrypi/controller/rpi/awb.cpp    | 20 +++++-----
> >  src/ipa/raspberrypi/controller/rpi/awb.h      |  1 +
> >  .../raspberrypi/controller/rpi/contrast.cpp   |  8 ++--
> >  src/ipa/raspberrypi/controller/rpi/focus.cpp  |  7 ++--
> >  src/ipa/raspberrypi/controller/rpi/lux.cpp    | 13 +------
> >  src/ipa/raspberrypi/raspberrypi.cpp           | 39 ++++++++++++++++++-
> >  src/ipa/raspberrypi/statistics.h              |  2 +
> >  12 files changed, 95 insertions(+), 63 deletions(-)
> >
> > diff --git a/src/ipa/raspberrypi/controller/controller.h
> b/src/ipa/raspberrypi/controller/controller.h
> > index 3e1e051703b3..e6c950c3a509 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/agc.cpp
> b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> > index bd54a639d637..79c83e0a9eae 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"
> > @@ -450,7 +448,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);
>
> I suppose "stats.get()" was a bit of a promise that the function
> couldn't possibly acquire another reference or anything like that, but
> I don't think it matters!
>
> >         /* Now compute the target (final) exposure which we think we
> want. */
> >         computeTargetExposure(gain);
> >         /*
> > @@ -584,20 +582,20 @@ 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++) {
> > +               uint32_t counted, uncounted;
> > +               auto s = stats->agcRegions.get(i, counted, uncounted);
> > +               double rAcc = std::min<double>(s.rSum * gain, ((1 <<
> PipelineBits) - 1) * counted);
> > +               double gAcc = std::min<double>(s.gSum * gain, ((1 <<
> PipelineBits) - 1) * counted);
> > +               double bAcc = std::min<double>(s.bSum * gain, ((1 <<
> PipelineBits) - 1) * counted);
> >                 rSum += rAcc * weights[i];
> >                 gSum += gAcc * weights[i];
> >                 bSum += bAcc * weights[i];
> > @@ -623,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 6d6b0e5ad857..0ea71e6d1aa0 100644
> > --- a/src/ipa/raspberrypi/controller/rpi/agc.h
> > +++ b/src/ipa/raspberrypi/controller/rpi/agc.h
> > @@ -98,7 +98,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 a4afaf841c41..d8c650e6faa6 100644
> > --- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp
> > +++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp
> > @@ -310,18 +310,22 @@ 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.numRegions());
> > +
> >         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;
> > +       for (unsigned int i = 0; i < stats->awbRegions.numRegions();
> i++) {
> > +               uint32_t counted, uncounted;
> > +               auto s = stats->awbRegions.get(i, counted, uncounted);
> > +               regions.set(i, { s.rSum /
> static_cast<uint64_t>(rTable[i]),
>
> Just wondering a bit about the casts here, it doesn't look obviously
> the same as what we have above...?
>

I'll cast the result of the div to minimise rounding errors.


>
> > +                                s.gSum /
> static_cast<uint64_t>(gTable[i]),
> > +                                s.bSum /
> static_cast<uint64_t>(bTable[i]) },
> > +                           counted, uncounted);
> >                 /* (don't care about the uncounted value) */
> >         }
> >  }
> > @@ -512,19 +516,20 @@ 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) {
> > +               uint32_t counted, uncounted;
> > +               auto s = awbRegion.get(i, counted, uncounted);
> > +
> > +               if (counted <= minCount || s.gSum / 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.rSum / (double)s.gSum;
> > +               cb[i] = s.bSum / (double)s.gSum;
> >         }
> >  }
> >
> > diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.h
> b/src/ipa/raspberrypi/controller/rpi/alsc.h
> > index a858ef5a6551..9167c9ffa2e3 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 861022014896..901498382c6b 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).
> > @@ -406,17 +403,18 @@ 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 (unsigned int i = 0; i < stats.numRegions(); i++) {
> >                 Awb::RGB zone;
> > -               double counted = stats[i].counted;
> > +               uint32_t counted, uncounted;
> > +               auto s = stats.get(i, counted, uncounted);
> >                 if (counted >= minPixels) {
> > -                       zone.G = stats[i].g_sum / counted;
> > +                       zone.G = s.gSum / counted;
> >                         if (zone.G >= minG) {
> > -                               zone.R = stats[i].r_sum / counted;
> > -                               zone.B = stats[i].b_sum / counted;
> > +                               zone.R = s.rSum / counted;
> > +                               zone.B = s.bSum / counted;
> >                                 zones.push_back(zone);
> >                         }
> >                 }
> > @@ -430,7 +428,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"
> > @@ -646,7 +644,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 30acd89d0969..d81779dd51ff 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 5b37edcbd46a..a4f8c4f04fc4 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 8c5029bd0e95..41afbf43f2b7 100644
> > --- a/src/ipa/raspberrypi/controller/rpi/focus.cpp
> > +++ b/src/ipa/raspberrypi/controller/rpi/focus.cpp
> > @@ -32,9 +32,10 @@ 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;
> > +       uint32_t counted, uncounted;
> > +       for (i = 0; i < stats->focusRegions.numRegions(); i++)
> > +               status.focusMeasures[i] = stats->focusRegions.get(i,
> counted, uncounted);
> > +       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 9759186afacf..a49d402707c7 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,13 @@ 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.total() /
> stats->yHist.bins() + .5;
>
> Is this the same thing? I have a bad feeling this might be the average
> number of pixels per bin, or something. Maybe we need something
> involving yHist.interQuantileMean(0, 1)...?
>

Argh, luckily we never use Lux values :-)
yHist.interQuantileMean(0, 1) will be the right substitute here.

Naush



>
> Thanks!
> David
>
> >                 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_;
> > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp
> b/src/ipa/raspberrypi/raspberrypi.cpp
> > index b74f1ecf738f..8fcfa0b3ea50 100644
> > --- a/src/ipa/raspberrypi/raspberrypi.cpp
> > +++ b/src/ipa/raspberrypi/raspberrypi.cpp
> > @@ -51,6 +51,7 @@
> >  #include "metadata.h"
> >  #include "sharpen_algorithm.h"
> >  #include "sharpen_status.h"
> > +#include "statistics.h"
> >
> >  namespace libcamera {
> >
> > @@ -136,6 +137,7 @@ private:
> >         void prepareISP(const ISPConfig &data);
> >         void reportMetadata();
> >         void fillDeviceStatus(const ControlList &sensorControls);
> > +       RPiController::StatisticsPtr fillStatistics(bcm2835_isp_stats
> *stats) const;
> >         void processStats(unsigned int bufferId);
> >         void applyFrameDurations(Duration minFrameDuration, Duration
> maxFrameDuration);
> >         void applyAGC(const struct AgcStatus *agcStatus, ControlList
> &ctrls);
> > @@ -1119,6 +1121,41 @@ void IPARPi::fillDeviceStatus(const ControlList
> &sensorControls)
> >         rpiMetadata_.set("device.status", deviceStatus);
> >  }
> >
> > +RPiController::StatisticsPtr IPARPi::fillStatistics(bcm2835_isp_stats
> *stats) const
> > +{
> > +       using namespace RPiController;
> > +
> > +       unsigned int i;
> > +       StatisticsPtr statistics =
> > +
>  std::make_unique<Statistics>(Statistics::AgcStatsPos::PreWb,
> Statistics::ColourStatsPos::PostLsc);
> > +
> > +       /* RGB histograms are not used, so do not populate them. */
> > +       statistics->yHist =
> std::move(RPiController::Histogram(stats->hist[0].g_hist,
> NUM_HISTOGRAM_BINS));
> > +
> > +       statistics->awbRegions.init(DEFAULT_AWB_REGIONS_X,
> DEFAULT_AWB_REGIONS_Y);
> > +       for (i = 0; i < statistics->awbRegions.numRegions(); i++)
> > +               statistics->awbRegions.set(i, {
> stats->awb_stats[i].r_sum,
> > +
>  stats->awb_stats[i].g_sum,
> > +
>  stats->awb_stats[i].b_sum },
> > +                                          stats->awb_stats[i].counted,
> stats->awb_stats[i].notcounted);
> > +
> > +       /* There are only ever 15 regions computed by the firmware, but
> the HW defines AGC_REGIONS == 16! */
> > +       statistics->agcRegions.init(15);
> > +       for (i = 0; i < statistics->agcRegions.numRegions(); i++)
> > +               statistics->agcRegions.set(i, {
> stats->agc_stats[i].r_sum,
> > +
>  stats->agc_stats[i].g_sum,
> > +
>  stats->agc_stats[i].b_sum },
> > +                                          stats->agc_stats[i].counted,
> 0);
> > +
> > +       statistics->focusRegions.init(4, 3);
> > +       for (i = 0; i < FOCUS_REGIONS; i++)
> > +               statistics->focusRegions.set(i,
> stats->focus_stats[i].contrast_val[1][1] / 1000,
> > +
> stats->focus_stats[i].contrast_val_num[1][1],
> > +
> stats->focus_stats[i].contrast_val_num[1][0]);
> > +
> > +       return statistics;
> > +}
> > +
> >  void IPARPi::processStats(unsigned int bufferId)
> >  {
> >         auto it = buffers_.find(bufferId);
> > @@ -1129,7 +1166,7 @@ void IPARPi::processStats(unsigned int bufferId)
> >
> >         Span<uint8_t> mem = it->second.planes()[0];
> >         bcm2835_isp_stats *stats = reinterpret_cast<bcm2835_isp_stats
> *>(mem.data());
> > -       RPiController::StatisticsPtr statistics =
> std::make_shared<bcm2835_isp_stats>(*stats);
> > +       RPiController::StatisticsPtr statistics = fillStatistics(stats);
> >         helper_->process(statistics, rpiMetadata_);
> >         controller_.process(statistics, &rpiMetadata_);
> >
> > diff --git a/src/ipa/raspberrypi/statistics.h
> b/src/ipa/raspberrypi/statistics.h
> > index a762bf3d41aa..affb7272c963 100644
> > --- a/src/ipa/raspberrypi/statistics.h
> > +++ b/src/ipa/raspberrypi/statistics.h
> > @@ -67,4 +67,6 @@ struct Statistics {
> >         FocusRegions focusRegions;
> >  };
> >
> > +using StatisticsPtr = std::shared_ptr<Statistics>;
> > +
> >  } /* namespace RPiController */
> > --
> > 2.25.1
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20221123/444ba630/attachment.htm>


More information about the libcamera-devel mailing list