[RFC 4/4] libcamera: swstats_cpu: Add processFrame() method

Hans de Goede hdegoede at redhat.com
Wed Oct 9 22:01:10 CEST 2024


Add a method to the SwstatsCpu class to process a whole Framebuffer in
one go, rather then line by line. This is useful for gathering stats
when debayering is not necessary or is not done on the CPU.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 src/libcamera/software_isp/swstats_cpu.cpp | 72 ++++++++++++++++++++++
 src/libcamera/software_isp/swstats_cpu.h   | 10 +++
 2 files changed, 82 insertions(+)

diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
index 5e4246a9..117147c2 100644
--- a/src/libcamera/software_isp/swstats_cpu.cpp
+++ b/src/libcamera/software_isp/swstats_cpu.cpp
@@ -16,6 +16,7 @@
 #include <libcamera/stream.h>
 
 #include "libcamera/internal/bayer_format.h"
+#include "libcamera/internal/mapped_framebuffer.h"
 
 namespace libcamera {
 
@@ -363,8 +364,11 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
 	BayerFormat bayerFormat =
 		BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
 
+	stride_ = inputCfg.stride;
+
 	if (bayerFormat.packing == BayerFormat::Packing::None &&
 	    setupStandardBayerOrder(bayerFormat.order) == 0) {
+		bpp_ = (bayerFormat.bitDepth + 7) & ~7;
 		switch (bayerFormat.bitDepth) {
 		case 8:
 			stats0_ = &SwStatsCpu::statsBGGR8Line0;
@@ -385,6 +389,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
 		/* Skip every 3th and 4th line, sample every other 2x2 block */
 		ySkipMask_ = 0x02;
 		xShift_ = 0;
+		bpp_ = 10;
 
 		switch (bayerFormat.order) {
 		case BayerFormat::BGGR:
@@ -425,4 +430,71 @@ void SwStatsCpu::setWindow(const Rectangle &window)
 	window_.height &= ~(patternSize_.height - 1);
 }
 
+void SwStatsCpu::processFrame2(const uint8_t *src)
+{
+	unsigned int yEnd = window_.y + window_.height;
+	const uint8_t *linePointers[3];
+
+	/* Adjust src to top left corner of the window */
+	src += window_.y * stride_ + window_.x * bpp_ / 8;
+
+	for (unsigned int y = window_.y; y < yEnd; y += 2) {
+		if (y & ySkipMask_) {
+			src += stride_ * 2;
+			continue;
+		}
+
+		/* linePointers[0] is not used by any stats0_ functions */
+		linePointers[1] = src;
+		linePointers[2] = src + stride_;
+		(this->*stats0_)(linePointers);
+		src += stride_ * 2;
+	}
+}
+
+void SwStatsCpu::processFrame4(const uint8_t *src)
+{
+	const unsigned int yEnd = window_.y + window_.height;
+	const uint8_t *linePointers[4];
+
+	/* Adjust src to top left corner of the window */
+	src += window_.y * stride_ + window_.x * bpp_ / 8;
+
+	for (unsigned int y = window_.y; y < yEnd; y += 4) {
+		if (y & ySkipMask_) {
+			src += stride_ * 4;
+			continue;
+		}
+
+		/* linePointers[0] and [1] are not used by 4 line pattern stats0_ functions */
+		linePointers[2] = src;
+		linePointers[3] = src + stride_;
+		(this->*stats0_)(linePointers);
+		src += stride_ * 2;
+
+		linePointers[2] = src;
+		linePointers[3] = src + stride_;
+		(this->*stats2_)(linePointers);
+		src += stride_ * 2;
+	}
+}
+
+void SwStatsCpu::processFrame(FrameBuffer *input)
+{
+	bench_.startFrame();
+
+	MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read);
+	if (!in.isValid()) {
+		LOG(SwStatsCpu, Error) << "mmap-ing buffer(s) failed";
+		return;
+	}
+
+	if (patternSize_.height == 2)
+		processFrame2(in.planes()[0].data());
+	else
+		processFrame4(in.planes()[0].data());
+
+	bench_.finishFrame();
+}
+
 } /* namespace libcamera */
diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h
index 26a2f462..bb178a04 100644
--- a/src/libcamera/software_isp/swstats_cpu.h
+++ b/src/libcamera/software_isp/swstats_cpu.h
@@ -18,9 +18,12 @@
 #include <libcamera/geometry.h>
 
 #include "libcamera/internal/bayer_format.h"
+#include "libcamera/internal/framebuffer.h"
 #include "libcamera/internal/shared_mem_object.h"
 #include "libcamera/internal/software_isp/swisp_stats.h"
 
+#include "benchmark.h"
+
 namespace libcamera {
 
 class PixelFormat;
@@ -42,6 +45,7 @@ public:
 	void setWindow(const Rectangle &window);
 	void startFrame();
 	void finishFrame(uint32_t frame, uint32_t bufferId);
+	void processFrame(FrameBuffer *input);
 
 	void processLine0(unsigned int y, const uint8_t *src[])
 	{
@@ -77,6 +81,9 @@ private:
 	void statsBGGR10PLine0(const uint8_t *src[]);
 	void statsGBRG10PLine0(const uint8_t *src[]);
 
+	void processFrame2(const uint8_t *src);
+	void processFrame4(const uint8_t *src);
+
 	/* Variables set by configure(), used every line */
 	statsProcessFn stats0_;
 	statsProcessFn stats2_;
@@ -89,9 +96,12 @@ private:
 	Size patternSize_;
 
 	unsigned int xShift_;
+	unsigned int bpp_; /* Memory used per pixel, not precision */
+	unsigned int stride_;
 
 	SharedMemObject<SwIspStats> sharedStats_;
 	SwIspStats stats_;
+	Benchmark bench_;
 };
 
 } /* namespace libcamera */
-- 
2.46.2



More information about the libcamera-devel mailing list