From patchwork Mon Feb 16 20:30:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26180 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 49CB4C3240 for ; Mon, 16 Feb 2026 20:31:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EDFC86222C; Mon, 16 Feb 2026 21:31:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="eydUWpuS"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 265DD62224 for ; Mon, 16 Feb 2026 21:31:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273862; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8t55nI6D1EYbu6IgY5PHIuQ7Fz+F54TF3djZPCk9duM=; b=eydUWpuSA20ZRA7ilr9FGZJXvwWsWsr30ISv6ct4BADUbvkw0RgW8zNCL4/iekmKYU84vs PurrDngvSj2SIAHfOJlmRPnMHLiDslv0Ci4Xq+2IKxQKyQ54IovT5dEoeGoJ8xORSbzVu8 eHihxA0AJQKhLT7Qn1Nt1rsP9ychkH0= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-687-QlIaCc4PMh6aAPZD6NmqyQ-1; Mon, 16 Feb 2026 15:31:01 -0500 X-MC-Unique: QlIaCc4PMh6aAPZD6NmqyQ-1 X-Mimecast-MFC-AGG-ID: QlIaCc4PMh6aAPZD6NmqyQ_1771273860 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BDE4B1955D7A for ; Mon, 16 Feb 2026 20:31:00 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.25]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CF5471800464; Mon, 16 Feb 2026 20:30:59 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 11/14] libcamera: software_isp: Allocate statistics buffers Date: Mon, 16 Feb 2026 21:30:30 +0100 Message-ID: <20260216203034.27558-12-mzamazal@redhat.com> In-Reply-To: <20260216203034.27558-1-mzamazal@redhat.com> References: <20260216203034.27558-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: fqEfazGj2z0u9lXfPjExe1yTLe4mJp-8i7QxlVowlo0_1771273860 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- .../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(-) 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 availableParams_; bool allocateParamsBuffers(const unsigned int bufferCount); + std::unique_ptr allocateStatsBuffers( + const GlobalConfiguration &configuration, + std::vector &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 #include #include @@ -34,7 +35,7 @@ struct StreamConfiguration; class SwStatsCpu { public: - SwStatsCpu(const GlobalConfiguration &configuration); + SwStatsCpu(const GlobalConfiguration &configuration, std::unique_ptr>> 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 sharedStats_; + std::unique_ptr>> 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 #include #include +#include +#include #include #include @@ -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(configuration); - if (!stats->isValid()) { - LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object"; - return; - } - stats->statsReady.connect(this, &SoftwareIsp::statsReady); - std::vector fdParams; for (auto &item : sharedParams_) fdParams.emplace_back(item.second.fd()); + std::vector fdStats; + auto stats = allocateStatsBuffers(configuration, fdStats, bufferCount); + if (!stats) + return; + #if HAVE_DEBAYER_EGL std::optional 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 SoftwareIsp::allocateStatsBuffers( + const GlobalConfiguration &configuration, + std::vector &fdStats, + const unsigned int bufferCount) +{ + auto sharedStats = std::make_unique>>(); + for (unsigned int i = 0; i < bufferCount; i++) { + auto shared = SharedMemObject("softIsp_stats"); + if (!shared) { + LOG(SoftwareIsp, Error) << "Failed to create shared memory for statistics"; + return std::unique_ptr(); + } + if (!shared.fd().isValid()) { + LOG(SoftwareIsp, Error) << "Invalid fd of shared statistics"; + return std::unique_ptr(); + } + + 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(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 + #include #include @@ -36,9 +38,11 @@ namespace libcamera { */ /** - * \fn SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration) + * \fn SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration, std::unique_ptr>> 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>> 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); }