@@ -33,6 +33,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 {
@@ -91,6 +92,10 @@ public:
private:
void paramsBufferReady(const uint32_t paramsBufferId);
bool allocateParamsBuffers(const unsigned int bufferCount);
+ std::unique_ptr<SwStatsCpu> allocateStatsBuffers(
+ const CameraManager &cm,
+ std::map<uint32_t, SharedFD> &fdStats,
+ const unsigned int bufferCount);
void setSensorCtrls(const ControlList &sensorControls);
void statsReady(uint32_t frame, const uint32_t statsBufferId);
void statsProcessed(const uint32_t statsBufferId);
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2023, Linaro Ltd
- * Copyright (C) 2023, Red Hat Inc.
+ * Copyright (C) 2023-2026 Red Hat Inc.
*
* Authors:
* Hans de Goede <hdegoede@redhat.com>
@@ -11,6 +11,7 @@
#pragma once
+#include <map>
#include <stdint.h>
#include <vector>
@@ -35,7 +36,7 @@ struct StreamConfiguration;
class SwStatsCpu
{
public:
- SwStatsCpu(const CameraManager &cm);
+ SwStatsCpu(const CameraManager &cm, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats);
~SwStatsCpu() = default;
/*
@@ -46,9 +47,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_; }
@@ -119,7 +120,7 @@ private:
unsigned int sumShift_;
std::vector<SwIspStats> stats_;
- SharedMemObject<SwIspStats> sharedStats_;
+ std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats_;
Benchmark bench_;
};
@@ -14,6 +14,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>
@@ -26,7 +28,10 @@
#include "libcamera/internal/bayer_format.h"
#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
@@ -99,17 +104,15 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe,
const CameraManager &cm = *pipe->cameraManager();
- auto stats = std::make_unique<SwStatsCpu>(cm);
- if (!stats->isValid()) {
- LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object";
- return;
- }
- stats->statsReady.connect(this, &SoftwareIsp::statsReady);
-
std::map<uint32_t, SharedFD> fdParams;
for (auto &[bufferId, item] : sharedParams_)
fdParams[bufferId] = item.fd();
+ std::map<uint32_t, SharedFD> fdStats;
+ auto stats = allocateStatsBuffers(cm, fdStats, bufferCount);
+ if (!stats)
+ return;
+
#if HAVE_DEBAYER_EGL
const GlobalConfiguration &configuration = cm._d()->configuration();
std::optional<std::string> softISPMode = configuration.option<std::string>({ "software_isp", "mode" });
@@ -203,6 +206,33 @@ bool SoftwareIsp::allocateParamsBuffers(const unsigned int bufferCount)
return true;
}
+std::unique_ptr<SwStatsCpu> SoftwareIsp::allocateStatsBuffers(
+ const CameraManager &cm,
+ std::map<uint32_t, SharedFD> &fdStats,
+ const unsigned int bufferCount)
+{
+ auto sharedStats = std::make_unique<std::map<uint32_t, SharedMemObject<SwIspStats>>>();
+ for (unsigned int bufferId = 0; bufferId < bufferCount; bufferId++) {
+ auto shared = SharedMemObject<SwIspStats>("softIsp_stats");
+ if (!shared) {
+ LOG(SoftwareIsp, Error) << "Failed to create shared memory for statistics";
+ return nullptr;
+ }
+ if (!shared.fd().isValid()) {
+ LOG(SoftwareIsp, Error) << "Invalid fd of shared statistics";
+ return nullptr;
+ }
+
+ fdStats[bufferId] = shared.fd();
+ sharedStats->emplace(bufferId, std::move(shared));
+ }
+
+ auto stats = std::make_unique<SwStatsCpu>(cm, 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
@@ -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 CameraManager &cm)
+ * \fn SwStatsCpu::SwStatsCpu(const CameraManager &cm, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats)
* \brief Construct a SwStatsCpu object
* \param[in] cm The camera manager
+ * \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.
@@ -159,12 +163,9 @@ namespace libcamera {
LOG_DEFINE_CATEGORY(SwStatsCpu)
-SwStatsCpu::SwStatsCpu(const CameraManager &cm)
- : sharedStats_("softIsp_stats"), bench_(cm, "CPU stats")
+SwStatsCpu::SwStatsCpu(const CameraManager &cm, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats)
+ : sharedStats_(std::move(sharedStats)), bench_(cm, "CPU stats")
{
- if (!sharedStats_)
- LOG(SwStatsCpu, Error)
- << "Failed to create shared memory for statistics";
}
static constexpr unsigned int kRedYMul = 77; /* 0.299 * 256 */
@@ -354,20 +355,21 @@ void SwStatsCpu::finishFrame(uint32_t frame,
const uint32_t statsBufferId)
{
bool valid = frame % kStatPerNumFrames == 0;
+ SharedMemObject<SwIspStats> &stats = sharedStats_->at(statsBufferId);
if (valid) {
- sharedStats_->sum_ = RGB<uint64_t>({ 0, 0, 0 });
- sharedStats_->yHistogram.fill(0);
+ stats->sum_ = RGB<uint64_t>({ 0, 0, 0 });
+ stats->yHistogram.fill(0);
for (const auto &s : stats_) {
- sharedStats_->sum_ += s.sum_;
+ stats->sum_ += s.sum_;
for (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++)
- sharedStats_->yHistogram[j] += s.yHistogram[j];
+ stats->yHistogram[j] += s.yHistogram[j];
}
- sharedStats_->sum_ >>= sumShift_;
+ stats->sum_ >>= sumShift_;
}
- sharedStats_->valid = valid;
+ stats->valid = valid;
statsReady.emit(frame, statsBufferId);
}
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 | 11 ++--- src/libcamera/software_isp/software_isp.cpp | 44 ++++++++++++++++--- src/libcamera/software_isp/swstats_cpu.cpp | 26 ++++++----- 4 files changed, 62 insertions(+), 24 deletions(-)