[RFC,v3,16/17] libcamera: software_isp: Share statistics buffers with IPA
diff mbox series

Message ID 20260604095105.68798-21-mzamazal@redhat.com
State New
Headers show
Series
  • Software ISP: Share params and stats buffers
Related show

Commit Message

Milan Zamazal June 4, 2026, 9:51 a.m. UTC
The last step to complete statistics buffer sharing is to pass all the
allocated statistics buffers to the IPA and refer to them using their ids.
This allows to remove the buffer copying in SwStatsCpu::finishFrame.

We can also remove now the methods that served for handling the former
single buffer shared between debayering and IPA.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 .../internal/software_isp/swstats_cpu.h       |  5 +--
 include/libcamera/ipa/soft.mojom              |  2 +-
 src/ipa/simple/soft_simple.cpp                | 42 +++++++++----------
 src/libcamera/software_isp/debayer.cpp        | 10 -----
 src/libcamera/software_isp/debayer.h          |  2 -
 src/libcamera/software_isp/debayer_cpu.h      |  1 -
 src/libcamera/software_isp/debayer_egl.h      |  2 -
 src/libcamera/software_isp/software_isp.cpp   |  2 +-
 src/libcamera/software_isp/swstats_cpu.cpp    | 28 ++++---------
 9 files changed, 31 insertions(+), 63 deletions(-)

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 cf2f88fcb..74d70bd20 100644
--- a/include/libcamera/internal/software_isp/swstats_cpu.h
+++ b/include/libcamera/internal/software_isp/swstats_cpu.h
@@ -12,6 +12,7 @@ 
 #pragma once
 
 #include <map>
+#include <memory>
 #include <stdint.h>
 #include <vector>
 
@@ -47,10 +48,6 @@  public:
 	 */
 	static constexpr uint32_t kStatPerNumFrames = 4;
 
-	bool isValid() const { return sharedStats_->begin()->second.fd().isValid(); }
-
-	const SharedFD &getStatsFD() { return sharedStats_->begin()->second.fd(); }
-
 	const Size &patternSize() { return patternSize_; }
 
 	int configure(const StreamConfiguration &inputCfg, unsigned int statsBufferCount = 1);
diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom
index c2c5fe382..a3739de00 100644
--- a/include/libcamera/ipa/soft.mojom
+++ b/include/libcamera/ipa/soft.mojom
@@ -14,7 +14,7 @@  struct IPAConfigInfo {
 
 interface IPASoftInterface {
 	init(libcamera.IPASettings settings,
-	     libcamera.SharedFD fdStats,
+	     map<uint32, libcamera.SharedFD> fdStats,
 	     map<uint32, libcamera.SharedFD> fdParams,
 	     libcamera.IPACameraSensorInfo sensorInfo,
 	     libcamera.ControlInfoMap sensorControls)
diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
index ded75a970..ff585b75e 100644
--- a/src/ipa/simple/soft_simple.cpp
+++ b/src/ipa/simple/soft_simple.cpp
@@ -52,7 +52,7 @@  public:
 	~IPASoftSimple();
 
 	int init(const IPASettings &settings,
-		 const SharedFD &fdStats,
+		 const std::map<uint32_t, SharedFD> &fdStats,
 		 const std::map<uint32_t, SharedFD> &fdParams,
 		 const IPACameraSensorInfo &sensorInfo,
 		 const ControlInfoMap &sensorControls,
@@ -76,7 +76,7 @@  private:
 	void updateExposure(double exposureMSV);
 
 	std::map<unsigned int, DebayerParams *> paramsBuffers_;
-	SwIspStats *stats_;
+	std::map<unsigned int, SwIspStats *> statsBuffers_;
 	std::unique_ptr<CameraSensorHelper> camHelper_;
 	ControlInfoMap sensorInfoMap_;
 
@@ -86,14 +86,14 @@  private:
 
 IPASoftSimple::~IPASoftSimple()
 {
-	if (stats_)
-		munmap(stats_, sizeof(SwIspStats));
+	for (auto &item : statsBuffers_)
+		munmap(item.second, sizeof(SwIspStats));
 	for (auto &item : paramsBuffers_)
 		munmap(item.second, sizeof(DebayerParams));
 }
 
 int IPASoftSimple::init(const IPASettings &settings,
-			const SharedFD &fdStats,
+			const std::map<uint32_t, SharedFD> &fdStats,
 			const std::map<uint32_t, SharedFD> &fdParams,
 			const IPACameraSensorInfo &sensorInfo,
 			const ControlInfoMap &sensorControls,
@@ -137,11 +137,20 @@  int IPASoftSimple::init(const IPASettings &settings,
 		return ret;
 
 	*ccmEnabled = context_.ccmEnabled;
-	stats_ = nullptr;
+	for (auto &[bufferId, sharedFd] : fdStats) {
+		if (!sharedFd.isValid()) {
+			LOG(IPASoft, Error) << "Invalid Statistics handle";
+			return -ENODEV;
+		}
+
+		void *mem = mmap(nullptr, sizeof(SwIspStats), PROT_READ,
+				 MAP_SHARED, sharedFd.get(), 0);
+		if (mem == MAP_FAILED) {
+			LOG(IPASoft, Error) << "Unable to map Statistics";
+			return -errno;
+		}
 
-	if (!fdStats.isValid()) {
-		LOG(IPASoft, Error) << "Invalid Statistics handle";
-		return -ENODEV;
+		statsBuffers_[bufferId] = static_cast<SwIspStats *>(mem);
 	}
 
 	for (auto &[bufferId, sharedFd] : fdParams) {
@@ -166,17 +175,6 @@  int IPASoftSimple::init(const IPASettings &settings,
 		paramsBuffers_[bufferId] = params;
 	}
 
-	{
-		void *mem = mmap(nullptr, sizeof(SwIspStats), PROT_READ,
-				 MAP_SHARED, fdStats.get(), 0);
-		if (mem == MAP_FAILED) {
-			LOG(IPASoft, Error) << "Unable to map Statistics";
-			return -errno;
-		}
-
-		stats_ = static_cast<SwIspStats *>(mem);
-	}
-
 	ControlInfoMap::Map ctrlMap = context_.ctrlMap;
 	*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
 
@@ -303,6 +301,8 @@  void IPASoftSimple::processStats(const uint32_t frame,
 {
 	IPAFrameContext &frameContext = context_.frameContexts.get(frame);
 
+	const SwIspStats *stats = statsBuffers_.at(statsBufferId);
+
 	frameContext.sensor.exposure =
 		sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
 	int32_t again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
@@ -310,7 +310,7 @@  void IPASoftSimple::processStats(const uint32_t frame,
 
 	ControlList metadata(controls::controls);
 	for (const auto &algo : algorithms())
-		algo->process(context_, frame, frameContext, stats_, metadata);
+		algo->process(context_, frame, frameContext, stats, metadata);
 	metadataReady.emit(frame, metadata);
 	statsProcessed.emit(statsBufferId);
 
diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp
index 341930e5b..533311200 100644
--- a/src/libcamera/software_isp/debayer.cpp
+++ b/src/libcamera/software_isp/debayer.cpp
@@ -138,16 +138,6 @@  Debayer::~Debayer()
  * \return The valid size ranges or an empty range if there are none
  */
 
-/**
- * \fn const SharedFD &Debayer::getStatsFD()
- * \brief Get the file descriptor for the statistics
- *
- * This file descriptor provides access to the output statistics buffer
- * associated with the current debayering process.
- *
- * \return The file descriptor pointing to the statistics data
- */
-
 /**
  * \fn unsigned int Debayer::frameSize()
  * \brief Get the output frame size
diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h
index 259261b1a..b0a1ed151 100644
--- a/src/libcamera/software_isp/debayer.h
+++ b/src/libcamera/software_isp/debayer.h
@@ -57,8 +57,6 @@  public:
 
 	virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0;
 
-	virtual const SharedFD &getStatsFD() = 0;
-
 	unsigned int frameSize() { return outputConfig_.frameSize; }
 
 	Signal<FrameBuffer *> inputBufferReady;
diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
index 37e45e9ea..62b43c4a9 100644
--- a/src/libcamera/software_isp/debayer_cpu.h
+++ b/src/libcamera/software_isp/debayer_cpu.h
@@ -53,7 +53,6 @@  public:
 	int start() override;
 	void stop() override;
 	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;
-	const SharedFD &getStatsFD() override { return stats_->getStatsFD(); }
 
 private:
 	friend class DebayerCpuThread;
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index 36c856c10..d7d1bc618 100644
--- a/src/libcamera/software_isp/debayer_egl.h
+++ b/src/libcamera/software_isp/debayer_egl.h
@@ -61,8 +61,6 @@  public:
 	int start() override;
 	void stop() override;
 
-	const SharedFD &getStatsFD() override { return stats_->getStatsFD(); }
-
 	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;
 
 private:
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index 2a019e6bc..020226585 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -162,7 +162,7 @@  SoftwareIsp::SoftwareIsp(PipelineHandler *pipe,
 	}
 
 	ret = ipa_->init(IPASettings{ ipaTuningFile, sensor->model() },
-			 debayer_->getStatsFD(),
+			 fdStats,
 			 fdParams,
 			 sensorInfo,
 			 sensor->controls(),
diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
index e6beb9692..0269e8249 100644
--- a/src/libcamera/software_isp/swstats_cpu.cpp
+++ b/src/libcamera/software_isp/swstats_cpu.cpp
@@ -48,20 +48,6 @@  namespace libcamera {
  * exchange.
  */
 
-/**
- * \fn bool SwStatsCpu::isValid() const
- * \brief Gets whether the statistics object is valid
- *
- * \return True if it's valid, false otherwise
- */
-
-/**
- * \fn const SharedFD &SwStatsCpu::getStatsFD()
- * \brief Get the file descriptor for the statistics
- *
- * \return The file descriptor
- */
-
 /**
  * \fn const Size &SwStatsCpu::patternSize()
  * \brief Get the pattern size
@@ -355,21 +341,21 @@  void SwStatsCpu::finishFrame(uint32_t frame,
 			     const uint32_t statsBufferId)
 {
 	bool valid = frame % kStatPerNumFrames == 0;
-	SharedMemObject<SwIspStats> &stats = sharedStats_->at(statsBufferId);
+	SharedMemObject<SwIspStats> &shared = sharedStats_->at(statsBufferId);
 
 	if (valid) {
-		stats->sum_ = RGB<uint64_t>({ 0, 0, 0 });
-		stats->yHistogram.fill(0);
+		shared->sum_ = RGB<uint64_t>({ 0, 0, 0 });
+		shared->yHistogram.fill(0);
 		for (const auto &s : stats_) {
-			stats->sum_ += s.sum_;
+			shared->sum_ += s.sum_;
 			for (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++)
-				stats->yHistogram[j] += s.yHistogram[j];
+				shared->yHistogram[j] += s.yHistogram[j];
 		}
 
-		stats->sum_ >>= sumShift_;
+		shared->sum_ >>= sumShift_;
 	}
 
-	stats->valid = valid;
+	shared->valid = valid;
 	statsReady.emit(frame, statsBufferId);
 }