[v3,03/11] software-isp: Align statistics with the visible sensor crop
diff mbox series

Message ID 20261016202818.1405645-4-halfline@gmail.com
State New
Headers show
Series
  • software-isp: Align crops, statistics and metadata
Related show

Commit Message

Ray Strode Oct. 16, 2026, 8:28 p.m. UTC
From: Ray Strode <rstrode@redhat.com>

This commit changes statistics gathering to follow the sensor area
visible in the GPU output.

The GPU debayer path fills the requested output with a centered crop
of the sensor image. CPU statistics read the original sensor buffer,
but their window uses the output dimensions and starts at the buffer's
origin. A centered origin is calculated but never passed to the
statistics engine. Metering therefore covers a different sensor region
when the image is cropped or scaled.

The window is now derived in sensor coordinates, accounting for Bayer
border removal and cropping to the output aspect ratio, and centered
in the sensor buffer. Changing resolution without changing aspect ratio
leaves the rectangle unchanged. The statistics engine retains its
existing Bayer alignment.

Signed-off-by: Ray Strode <rstrode@redhat.com>
---
 .../internal/software_isp/debayer_geometry.h        |  8 ++++++++
 src/libcamera/software_isp/debayer_egl.cpp          | 13 +++----------
 src/libcamera/software_isp/debayer_egl.h            |  1 -
 3 files changed, 11 insertions(+), 11 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/internal/software_isp/debayer_geometry.h b/include/libcamera/internal/software_isp/debayer_geometry.h
index 70ae6a8b..46721753 100644
--- a/include/libcamera/internal/software_isp/debayer_geometry.h
+++ b/include/libcamera/internal/software_isp/debayer_geometry.h
@@ -40,4 +40,12 @@  inline std::array<float, 16> debayerProjection(const Size &inputSize,
 	/* clang-format on */
 }
 
+/* Return the visible sensor rectangle, before statistics Bayer alignment. */
+inline Rectangle debayerCrop(const Size &inputSize, const Size &nativeSize,
+			     const Size &outputSize)
+{
+	const Size visibleSize = nativeSize.boundedToAspectRatio(outputSize);
+	return visibleSize.centeredTo(Rectangle(inputSize).center());
+}
+
 } /* namespace libcamera */
diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index 1a7ad25c..9f3dc752 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -323,18 +323,11 @@  int DebayerEGL::configure(const StreamConfiguration &inputCfg,
 	outputSize_ = outputCfg.size;
 	nativeOutputSize_ = outSizeRange.max;
 
-	window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &
-		    ~(inputConfig_.patternSize.width - 1);
-	window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) &
-		    ~(inputConfig_.patternSize.height - 1);
-	window_.width = outputCfg.size.width;
-	window_.height = outputCfg.size.height;
-
 	/*
-	 * Don't pass x,y from window_ since process() already adjusts for it.
-	 * But crop the window to 2/3 of its width and height for speedup.
+	 * The GPU scales the visible sensor crop to outputSize_. Statistics
+	 * consume the original input buffer, so use sensor coordinates here.
 	 */
-	stats_->setWindow(Rectangle(window_.size()));
+	stats_->setWindow(debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_));
 
 	inputBufferCount_ = inputCfg.bufferCount;
 	outputBufferCount_ = outputCfg.bufferCount;
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index 30e51a47..52b8aa07 100644
--- a/src/libcamera/software_isp/debayer_egl.h
+++ b/src/libcamera/software_isp/debayer_egl.h
@@ -111,7 +111,6 @@  private:
 	GLint contrastExpUniformDataIn_;
 
 	Size nativeOutputSize_;
-	Rectangle window_;
 	std::unique_ptr<SwStatsCpu> stats_;
 	eGL egl_;
 	uint32_t width_;