[v2,06/10] libcamera: software_isp: Normalize statistics sums to 8-bit
diff mbox series

Message ID 20260506230722.1041596-7-devve.3@gmail.com
State New
Headers show
Series
  • OV01A10 sensor support and simple IPA improvements
Related show

Commit Message

devve May 6, 2026, 11:07 p.m. UTC
From: Javier Tia <floss@jetm.me>

The SWSTATS_ACCUMULATE_LINE_STATS() macro divides the luminance value
for the histogram to normalize it to 8-bit range, but does not apply
the same normalization to the RGB sums. For 10-bit and 12-bit unpacked
Bayer formats this means the sums are accumulated at native bit depth
(0-1023 or 0-4095 per pixel) while the AWB algorithm subtracts an
8-bit black level from them, under-correcting by 4x or 16x
respectively.
Fix this by right-shifting the RGB sums in finishFrame() to normalize
them to 8-bit scale, matching the histogram and the 8-bit black level
used by AWB. A per-format sumShift_ value is set in configure():
0 for 8-bit and CSI-2 packed formats (already 8-bit), 2 for 10-bit,
and 4 for 12-bit unpacked formats.
Signed-off-by: Javier Tia <floss@jetm.me>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Signed-off-by: d3vv3 <devve.3@gmail.com>
---
 include/libcamera/internal/software_isp/swstats_cpu.h | 1 +
 src/libcamera/software_isp/swstats_cpu.cpp            | 7 +++++++
 2 files changed, 8 insertions(+)

Patch
diff mbox series

diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h
index 802370bd..2dac6945 100644
--- a/include/libcamera/internal/software_isp/swstats_cpu.h
+++ b/include/libcamera/internal/software_isp/swstats_cpu.h
@@ -116,6 +116,7 @@  private:
 
 	unsigned int xShift_;
 	unsigned int stride_;
+	unsigned int sumShift_;
 
 	std::vector<SwIspStats> stats_;
 	SharedMemObject<SwIspStats> sharedStats_;
diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
index 5366e019..2ed906e1 100644
--- a/src/libcamera/software_isp/swstats_cpu.cpp
+++ b/src/libcamera/software_isp/swstats_cpu.cpp
@@ -362,6 +362,11 @@  void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId)
 			for (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++)
 				sharedStats_->yHistogram[j] += s.yHistogram[j];
 		}
+		if (sumShift_) {
+			sharedStats_->sum_.r() >>= sumShift_;
+			sharedStats_->sum_.g() >>= sumShift_;
+			sharedStats_->sum_.b() >>= sumShift_;
+		}
 	}
 
 	sharedStats_->valid = valid;
@@ -422,6 +427,7 @@  int SwStatsCpu::configure(const StreamConfiguration &inputCfg, unsigned int stat
 	if (bayerFormat.packing == BayerFormat::Packing::None &&
 	    setupStandardBayerOrder(bayerFormat.order) == 0) {
 		processFrame_ = &SwStatsCpu::processBayerFrame2;
+		sumShift_ = bayerFormat.bitDepth - 8;
 		switch (bayerFormat.bitDepth) {
 		case 8:
 			stats0_ = &SwStatsCpu::statsBGGR8Line0;
@@ -442,6 +448,7 @@  int SwStatsCpu::configure(const StreamConfiguration &inputCfg, unsigned int stat
 		/* Skip every 3th and 4th line, sample every other 2x2 block */
 		ySkipMask_ = 0x02;
 		xShift_ = 0;
+		sumShift_ = 0;
 		processFrame_ = &SwStatsCpu::processBayerFrame2;
 
 		switch (bayerFormat.order) {