From patchwork Mon Jun 8 15:03:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26857 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 09BD2C328C for ; Mon, 8 Jun 2026 15:04:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A456B61F17; Mon, 8 Jun 2026 17:04:39 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="HCXHLClf"; 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 8FD7961F17 for ; Mon, 8 Jun 2026 17:04:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780931076; 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=zWeLxjDraEA849kiojcF/8v79ehP0dh5ZDYofMM4Ksk=; b=HCXHLClfSTrnX28RF+tlJr7PKLd2W6OBon4yBpilMkHipJULBQc14rNRPaXRuzoisbZFs3 JsjZzGPzdJwNUYC5DuXp4r6/eGSWXBsssdwgefRNKuhvC3eXFG0q4NoyhIJwo0yiUMxw0U 4XdbGWdFdBHnjuRRBUAQP15M/uenfVY= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-507-GN0p5DgMNfWq-7D05UGImg-1; Mon, 08 Jun 2026 11:04:32 -0400 X-MC-Unique: GN0p5DgMNfWq-7D05UGImg-1 X-Mimecast-MFC-AGG-ID: GN0p5DgMNfWq-7D05UGImg_1780931071 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7E0F91801BDB; Mon, 8 Jun 2026 15:04:31 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.48.51]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 70998180058F; Mon, 8 Jun 2026 15:04:29 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , johannes.goede@oss.qualcomm.com Subject: [RFC PATCH v4 14/17] libcamera: software_isp: Allocate statistics buffers Date: Mon, 8 Jun 2026 17:03:43 +0200 Message-ID: <20260608150349.134371-15-mzamazal@redhat.com> In-Reply-To: <20260608150349.134371-1-mzamazal@redhat.com> References: <20260608150349.134371-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: y-QcyD1bi5-qHSilh6r3vJJePVNjGj4AyLFQtk-ddx8_1780931071 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 | 11 ++--- src/libcamera/software_isp/software_isp.cpp | 44 ++++++++++++++++--- src/libcamera/software_isp/swstats_cpu.cpp | 26 ++++++----- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 3e879c630..451596163 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -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 allocateStatsBuffers( + const CameraManager &cm, + std::map &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); diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 4356eb826..7a66c9367 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -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 @@ -11,6 +11,7 @@ #pragma once +#include #include #include @@ -35,7 +36,7 @@ struct StreamConfiguration; class SwStatsCpu { public: - SwStatsCpu(const CameraManager &cm); + SwStatsCpu(const CameraManager &cm, std::unique_ptr>> 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_; } @@ -122,7 +123,7 @@ private: unsigned int sumShift_; std::vector stats_; - SharedMemObject sharedStats_; + std::unique_ptr>> sharedStats_; Benchmark bench_; }; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index c44e035b8..c4da647e8 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -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(cm); - if (!stats->isValid()) { - LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object"; - return; - } - stats->statsReady.connect(this, &SoftwareIsp::statsReady); - std::map fdParams; for (auto &[bufferId, item] : sharedParams_) fdParams[bufferId] = item.fd(); + std::map fdStats; + auto stats = allocateStatsBuffers(cm, fdStats, bufferCount); + if (!stats) + return; + #if HAVE_DEBAYER_EGL const GlobalConfiguration &configuration = cm._d()->configuration(); std::optional softISPMode = configuration.option({ "software_isp", "mode" }); @@ -203,6 +206,33 @@ bool SoftwareIsp::allocateParamsBuffers(const unsigned int bufferCount) return true; } +std::unique_ptr SoftwareIsp::allocateStatsBuffers( + const CameraManager &cm, + std::map &fdStats, + const unsigned int bufferCount) +{ + auto sharedStats = std::make_unique>>(); + for (unsigned int bufferId = 0; bufferId < bufferCount; bufferId++) { + auto shared = SharedMemObject("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(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 diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index a10535004..15eca4769 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 CameraManager &cm) + * \fn SwStatsCpu::SwStatsCpu(const CameraManager &cm, std::unique_ptr>> 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>> 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 */ @@ -406,20 +407,21 @@ void SwStatsCpu::finishFrame(uint32_t frame, const uint32_t statsBufferId) { bool valid = frame % kStatPerNumFrames == 0; + SharedMemObject &stats = sharedStats_->at(statsBufferId); if (valid) { - sharedStats_->sum_ = RGB({ 0, 0, 0 }); - sharedStats_->yHistogram.fill(0); + stats->sum_ = RGB({ 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); }