[RFC,v2,11/14] libcamera: software_isp: Allocate statistics buffers
diff mbox series

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

Commit Message

Milan Zamazal Feb. 16, 2026, 8:30 p.m. UTC
In order to be able to use multiple shared statistics buffers, we must
allocate them.  They are allocated in SoftwareIsp and passed to
SwIspStats.  This changes the previous behavior when the (single) shared
statistics buffer was created in SwIspStats.  Centralizing it to
SoftwareIsp makes sharing multiple buffers with IPA easier.

Currently only one of the allocated buffers is used.  This will be
changed once the buffers are shared with IPA in a followup patch.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 .../internal/software_isp/software_isp.h      |  5 +++
 .../internal/software_isp/swstats_cpu.h       |  9 ++--
 src/libcamera/software_isp/software_isp.cpp   | 45 ++++++++++++++++---
 src/libcamera/software_isp/swstats_cpu.cpp    | 15 ++++---
 4 files changed, 56 insertions(+), 18 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h
index 519dfc71a..1f3eb75f6 100644
--- a/include/libcamera/internal/software_isp/software_isp.h
+++ b/include/libcamera/internal/software_isp/software_isp.h
@@ -34,6 +34,7 @@ 
 #include "libcamera/internal/pipeline_handler.h"
 #include "libcamera/internal/shared_mem_object.h"
 #include "libcamera/internal/software_isp/debayer_params.h"
+#include "libcamera/internal/software_isp/swstats_cpu.h"
 
 namespace libcamera {
 
@@ -103,6 +104,10 @@  private:
 	DebayerParams debayerParams_;
 	std::queue<uint32_t> availableParams_;
 	bool allocateParamsBuffers(const unsigned int bufferCount);
+	std::unique_ptr<SwStatsCpu> allocateStatsBuffers(
+		const GlobalConfiguration &configuration,
+		std::vector<SharedFD> &fdStats,
+		const unsigned int bufferCount);
 	DmaBufAllocator dmaHeap_;
 	bool ccmEnabled_;
 
diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h
index ae8ce1e59..050b13ec1 100644
--- a/include/libcamera/internal/software_isp/swstats_cpu.h
+++ b/include/libcamera/internal/software_isp/swstats_cpu.h
@@ -11,6 +11,7 @@ 
 
 #pragma once
 
+#include <map>
 #include <stdint.h>
 
 #include <libcamera/base/signal.h>
@@ -34,7 +35,7 @@  struct StreamConfiguration;
 class SwStatsCpu
 {
 public:
-	SwStatsCpu(const GlobalConfiguration &configuration);
+	SwStatsCpu(const GlobalConfiguration &configuration, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats);
 	~SwStatsCpu() = default;
 
 	/*
@@ -45,9 +46,9 @@  public:
 	 */
 	static constexpr uint32_t kStatPerNumFrames = 4;
 
-	bool isValid() const { return sharedStats_.fd().isValid(); }
+	bool isValid() const { return sharedStats_->begin()->second.fd().isValid(); }
 
-	const SharedFD &getStatsFD() { return sharedStats_.fd(); }
+	const SharedFD &getStatsFD() { return sharedStats_->begin()->second.fd(); }
 
 	const Size &patternSize() { return patternSize_; }
 
@@ -116,7 +117,7 @@  private:
 	unsigned int xShift_;
 	unsigned int stride_;
 
-	SharedMemObject<SwIspStats> sharedStats_;
+	std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats_;
 	SwIspStats stats_;
 	Benchmark bench_;
 };
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index 04aaf7a8c..a1a9ddbf4 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -12,6 +12,8 @@ 
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <utility>
+#include <vector>
 
 #include <libcamera/base/log.h>
 #include <libcamera/base/shared_fd.h>
@@ -24,7 +26,9 @@ 
 
 #include "libcamera/internal/framebuffer.h"
 #include "libcamera/internal/ipa_manager.h"
+#include "libcamera/internal/shared_mem_object.h"
 #include "libcamera/internal/software_isp/debayer_params.h"
+#include "libcamera/internal/software_isp/swisp_stats.h"
 
 #include "debayer_cpu.h"
 #if HAVE_DEBAYER_EGL
@@ -95,17 +99,15 @@  SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 
 	const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration();
 
-	auto stats = std::make_unique<SwStatsCpu>(configuration);
-	if (!stats->isValid()) {
-		LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object";
-		return;
-	}
-	stats->statsReady.connect(this, &SoftwareIsp::statsReady);
-
 	std::vector<SharedFD> fdParams;
 	for (auto &item : sharedParams_)
 		fdParams.emplace_back(item.second.fd());
 
+	std::vector<SharedFD> fdStats;
+	auto stats = allocateStatsBuffers(configuration, fdStats, bufferCount);
+	if (!stats)
+		return;
+
 #if HAVE_DEBAYER_EGL
 	std::optional<std::string> softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" });
 	if (softISPMode) {
@@ -199,6 +201,35 @@  bool SoftwareIsp::allocateParamsBuffers(const unsigned int bufferCount)
 	return true;
 }
 
+std::unique_ptr<SwStatsCpu> SoftwareIsp::allocateStatsBuffers(
+	const GlobalConfiguration &configuration,
+	std::vector<SharedFD> &fdStats,
+	const unsigned int bufferCount)
+{
+	auto sharedStats = std::make_unique<std::map<uint32_t, SharedMemObject<SwIspStats>>>();
+	for (unsigned int i = 0; i < bufferCount; i++) {
+		auto shared = SharedMemObject<SwIspStats>("softIsp_stats");
+		if (!shared) {
+			LOG(SoftwareIsp, Error) << "Failed to create shared memory for statistics";
+			return std::unique_ptr<SwStatsCpu>();
+		}
+		if (!shared.fd().isValid()) {
+			LOG(SoftwareIsp, Error) << "Invalid fd of shared statistics";
+			return std::unique_ptr<SwStatsCpu>();
+		}
+
+		ASSERT(shared.fd().get() >= 0);
+		unsigned int bufferId = shared.fd().get();
+		fdStats.emplace_back(shared.fd());
+		sharedStats->emplace(bufferId, std::move(shared));
+	}
+
+	auto stats = std::make_unique<SwStatsCpu>(configuration, std::move(sharedStats));
+	stats->statsReady.connect(this, &SoftwareIsp::statsReady);
+
+	return stats;
+}
+
 /**
  * \fn int SoftwareIsp::loadConfiguration([[maybe_unused]] const std::string &filename)
  * \brief Load a configuration from a file
diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
index a3b11c443..b9f36b383 100644
--- a/src/libcamera/software_isp/swstats_cpu.cpp
+++ b/src/libcamera/software_isp/swstats_cpu.cpp
@@ -11,6 +11,8 @@ 
 
 #include "libcamera/internal/software_isp/swstats_cpu.h"
 
+#include <memory>
+
 #include <libcamera/base/log.h>
 
 #include <libcamera/stream.h>
@@ -36,9 +38,11 @@  namespace libcamera {
  */
 
 /**
- * \fn SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration)
+ * \fn SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats)
  * \brief Construct a SwStatsCpu object
  * \param[in] configuration Global configuration reference
+ * \param [in] sharedStats Mapping of statistics buffer ids to statistics
+ *   instances that are shared with the IPA
  *
  * Creates a SwStatsCpu object and initialises shared memory for statistics
  * exchange.
@@ -154,12 +158,9 @@  namespace libcamera {
 
 LOG_DEFINE_CATEGORY(SwStatsCpu)
 
-SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration)
-	: sharedStats_("softIsp_stats"), bench_(configuration)
+SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats)
+	: sharedStats_(std::move(sharedStats)), bench_(configuration)
 {
-	if (!sharedStats_)
-		LOG(SwStatsCpu, Error)
-			<< "Failed to create shared memory for statistics";
 }
 
 static constexpr unsigned int kRedYMul = 77; /* 0.299 * 256 */
@@ -348,7 +349,7 @@  void SwStatsCpu::finishFrame(uint32_t frame,
 			     const uint32_t statsBufferId)
 {
 	stats_.valid = frame % kStatPerNumFrames == 0;
-	*sharedStats_ = stats_;
+	*(sharedStats_->at(statsBufferId)) = stats_;
 	statsReady.emit(frame, statsBufferId);
 }