From patchwork Thu Jun 4 09:51:02 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26840 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 A2F22C328C for ; Thu, 4 Jun 2026 09:52:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5A2096374E; Thu, 4 Jun 2026 11:52:08 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="DKFdrE9i"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 238FF63282 for ; Thu, 4 Jun 2026 11:52:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780566726; 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=BP/CI+Knz7wRLzbuGBA2ELDt8uLx0ag7k7fD9ZXPSE4=; b=DKFdrE9il2Y01leDVR7yrFPikvR7Qka741LcD41bfPNLZ1X0gMvWKiexLx3+rQbtTtLO4S XlP7mPrO30BwevGSQK0G+Or8gD2wY2Q7quG38j26V21XAAOjPOVFlUfVpDvfD3JCq58D2Q W4JWb4+HDWvxT+CWM52NtK+kKilXj7g= Received: from mx-prod-mc-06.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-322-HH73T_iWOCaCmv-zWXH0BQ-1; Thu, 04 Jun 2026 05:52:01 -0400 X-MC-Unique: HH73T_iWOCaCmv-zWXH0BQ-1 X-Mimecast-MFC-AGG-ID: HH73T_iWOCaCmv-zWXH0BQ_1780566720 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 597431800350; Thu, 4 Jun 2026 09:52:00 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.34.156]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DC40C30001A1; Thu, 4 Jun 2026 09:51:58 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , =?utf-8?b?QmFybmFiw6FzIFDFkWN6?= =?utf-8?q?e?= , johannes.goede@oss.qualcomm.com Subject: [RFC PATCH v3 16/17] libcamera: software_isp: Share statistics buffers with IPA Date: Thu, 4 Jun 2026 11:51:02 +0200 Message-ID: <20260604095105.68798-21-mzamazal@redhat.com> In-Reply-To: <20260604095105.68798-1-mzamazal@redhat.com> References: <20260604095105.68798-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: qYXt8pm0NZ8OEn2gnnZopTQE9mH6pVf7ODnwoweGqlM_1780566720 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" 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 --- .../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(-) 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 +#include #include #include @@ -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 fdStats, map 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 &fdStats, const std::map &fdParams, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, @@ -76,7 +76,7 @@ private: void updateExposure(double exposureMSV); std::map paramsBuffers_; - SwIspStats *stats_; + std::map statsBuffers_; std::unique_ptr 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 &fdStats, const std::map &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(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(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 again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get(); @@ -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 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 &stats = sharedStats_->at(statsBufferId); + SharedMemObject &shared = sharedStats_->at(statsBufferId); if (valid) { - stats->sum_ = RGB({ 0, 0, 0 }); - stats->yHistogram.fill(0); + shared->sum_ = RGB({ 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); }