From patchwork Mon Jun 8 15:03:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26859 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 482BAC328C for ; Mon, 8 Jun 2026 15:04:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F2DF761F37; Mon, 8 Jun 2026 17:04:42 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Tx5WEudA"; 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 EE88561F0F for ; Mon, 8 Jun 2026 17:04:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780931079; 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=7SsbtO8egQymtUpgnE/ezOZ9vnLT1vLbyMEOW3CMceQ=; b=Tx5WEudAY6x+VnPQIT2W15uV03Kc3H6dVKBJUffnLTMDrSfqbKmmMg60Hxg6xpLFgz4Un7 tJ7oFZp8UYXj3Hzwgv9WNtWSbQV1IjXTmGNfF9np7Lab1VDN3tMTNDqBXF7GdJveoIObgH ImJ3Up4znJtwIyvcT7H1AG49Ywf0HiU= 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-492-Mk2iwlmsOQuiku_BvfqtYA-1; Mon, 08 Jun 2026 11:04:37 -0400 X-MC-Unique: Mk2iwlmsOQuiku_BvfqtYA-1 X-Mimecast-MFC-AGG-ID: Mk2iwlmsOQuiku_BvfqtYA_1780931076 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 CCF93180075E; Mon, 8 Jun 2026 15:04:36 +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 BB6DA1800351; Mon, 8 Jun 2026 15:04:34 +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 16/17] libcamera: software_isp: Share statistics buffers with IPA Date: Mon, 8 Jun 2026 17:03:45 +0200 Message-ID: <20260608150349.134371-17-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: K716Wd0B4-gzt9tZ4t-d1A1ptZXVGYhfhaqSkph4z9s_1780931076 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 7a66c9367..4ec13c4da 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 8f8b2d6b1..e018567f4 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 15eca4769..2f490af51 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 @@ -407,21 +393,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); }