From patchwork Mon Feb 16 20:30:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26170 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 61765C0DA4 for ; Mon, 16 Feb 2026 20:30:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1A86F621F6; Mon, 16 Feb 2026 21:30:49 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="bM5wJweI"; 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 9425362084 for ; Mon, 16 Feb 2026 21:30:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273845; 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=pRlOwYPxy3cv6I+YKyAFEaVWDGDb6Gw3JzrXIGhcDhY=; b=bM5wJweIA/9Icgz1VOaJVLO+1e3wNrI0tKquYmOuLdLGBaXswDKil/ScTb/jEc68cD7aC8 ceOnfu5IkgkvhWoJvRSUrhw5ssW4kvqJlDL10edh4wyNNpvTfRCP5P7aIs9G3qmwKKkKDS oAvF5u/9V+O6SlyPR+yJbUjbfflYmec= Received: from mx-prod-mc-03.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-479-P6w0omiJM0OJ5PQ0ED7zpQ-1; Mon, 16 Feb 2026 15:30:43 -0500 X-MC-Unique: P6w0omiJM0OJ5PQ0ED7zpQ-1 X-Mimecast-MFC-AGG-ID: P6w0omiJM0OJ5PQ0ED7zpQ_1771273843 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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E6D7419560B5 for ; Mon, 16 Feb 2026 20:30:42 +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 9287B1800464; Mon, 16 Feb 2026 20:30:41 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 01/14] libcamera: software_isp: Remove initializer_list include Date: Mon, 16 Feb 2026 21:30:20 +0100 Message-ID: <20260216203034.27558-2-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: zA0r_74whFIefqtDf6VJk2JZtoOeMq4jq9QF7AfAbWY_1771273843 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" It is not used anywhere in software_isp.h. Signed-off-by: Milan Zamazal --- include/libcamera/internal/software_isp/software_isp.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index ad89c9b3c..2ec14a3c7 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -9,7 +9,6 @@ #include #include -#include #include #include #include From patchwork Mon Feb 16 20:30:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26171 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 F0FBBC0DA4 for ; Mon, 16 Feb 2026 20:30:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A7A5362210; Mon, 16 Feb 2026 21:30:50 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="F5+YO2KW"; 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 A0BC562210 for ; Mon, 16 Feb 2026 21:30:48 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273847; 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=069YiV6lPTQgWn+eLaNl2jQZJ/ZO4zAzYLy+OVbyFyA=; b=F5+YO2KWILJwmET0brdz+z8yfEnU9K+uhAIs5JO9ILtxNWhuUsERaOvJnWEiJNJm3S1WLy SfhgLWr/DbMruYbzXxIIvZjs2HtNam3ZFRLEK58RIuJOF1Ycjog6KgX9+/29WSLiLsgct3 /FZ8W/j7W7z+wjO8QlAwNtnjNOEunoQ= 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-359-u8gMOLENM-CUVP2BdTjDYA-1; Mon, 16 Feb 2026 15:30:45 -0500 X-MC-Unique: u8gMOLENM-CUVP2BdTjDYA-1 X-Mimecast-MFC-AGG-ID: u8gMOLENM-CUVP2BdTjDYA_1771273845 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 DB86B195608A for ; Mon, 16 Feb 2026 20:30:44 +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 AA02D180066B; Mon, 16 Feb 2026 20:30:43 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 02/14] libcamera: software_isp: Introduce arguments for parameters buffers Date: Mon, 16 Feb 2026 21:30:21 +0100 Message-ID: <20260216203034.27558-3-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: aSVcvaSdaFnord6MnUnGx4bItifpnJ3I6egYBDLx93E_1771273845 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" Processing parameters in software ISP are currently passed by value. This is unlike hardware pipelines, which use a ring of buffers for the purpose and pass references to the buffers currently selected from the ring rather than passing the whole parameters buffers. This is a preparatory patch to introduce a similar mechanism in software ISP, in order to resolve TODO #5. It adds a new argument paramsBufferId for the future parameters buffer ids passed to the calls. The buffer ids must be passed to the following groups of methods: - IPASoftSimple::prepare, in order to create the parameters in the given buffer for the corresponding frame processing. - SoftwareIsp::saveParams, in order to signal that the parameters are set by the IPA. - Debayer::process, in order to get the buffer with the processing parameters. - SoftwareIsp::releaseIspParams, in order to signal that the selected parameters buffer from the ring is no longer needed for the given frame and can be reused. This is a newly introduced signal. The type of the buffer id parameter is set to uint32_t because: - It can be used in mojom. - It is consistent with the similar types in the hardware pipelines. - It covers file descriptor number range, which will be used as buffer ids (more on this in followup patches). This patch doesn't do more than adding the arguments, to keep the patch simple. The buffer handling will be implemented in the followup patches. Signed-off-by: Milan Zamazal --- .../libcamera/internal/software_isp/software_isp.h | 3 ++- include/libcamera/ipa/soft.mojom | 4 ++-- src/ipa/simple/soft_simple.cpp | 9 ++++++--- src/libcamera/software_isp/debayer.cpp | 6 +++++- src/libcamera/software_isp/debayer.h | 6 +++++- src/libcamera/software_isp/debayer_cpu.cpp | 6 +++++- src/libcamera/software_isp/debayer_cpu.h | 4 +++- src/libcamera/software_isp/debayer_egl.cpp | 5 ++++- src/libcamera/software_isp/debayer_egl.h | 4 +++- src/libcamera/software_isp/software_isp.cpp | 13 ++++++++++--- 10 files changed, 45 insertions(+), 15 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 2ec14a3c7..30b25cddf 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -88,7 +88,8 @@ public: Signal setSensorControls; private: - void saveIspParams(); + void saveIspParams(uint32_t paramsBufferId); + void releaseIspParams(uint32_t paramsBufferId); void setSensorCtrls(const ControlList &sensorControls); void statsReady(uint32_t frame, uint32_t bufferId); void inputReady(FrameBuffer *input); diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index 77328c5fd..f37c1e747 100644 --- a/include/libcamera/ipa/soft.mojom +++ b/include/libcamera/ipa/soft.mojom @@ -25,7 +25,7 @@ interface IPASoftInterface { => (int32 ret); [async] queueRequest(uint32 frame, libcamera.ControlList sensorControls); - [async] computeParams(uint32 frame); + [async] computeParams(uint32 frame, uint32 paramsBufferId); [async] processStats(uint32 frame, uint32 bufferId, libcamera.ControlList sensorControls); @@ -33,6 +33,6 @@ interface IPASoftInterface { interface IPASoftEventInterface { setSensorControls(libcamera.ControlList sensorControls); - setIspParams(); + setIspParams(uint32 paramsBufferId); metadataReady(uint32 frame, libcamera.ControlList metadata); }; diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index 6bef597c8..1e8b5334c 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -64,7 +64,9 @@ public: void stop() override; void queueRequest(const uint32_t frame, const ControlList &controls) override; - void computeParams(const uint32_t frame) override; + void computeParams(const uint32_t frame, + const uint32_t + paramsBufferId) override; void processStats(const uint32_t frame, const uint32_t bufferId, const ControlList &sensorControls) override; @@ -283,7 +285,8 @@ void IPASoftSimple::queueRequest(const uint32_t frame, const ControlList &contro algo->queueRequest(context_, frame, frameContext, controls); } -void IPASoftSimple::computeParams(const uint32_t frame) +void IPASoftSimple::computeParams(const uint32_t frame, + const uint32_t paramsBufferId) { context_.activeState.combinedMatrix = Matrix::identity(); @@ -292,7 +295,7 @@ void IPASoftSimple::computeParams(const uint32_t frame) algo->prepare(context_, frame, frameContext, params_); params_->combinedMatrix = context_.activeState.combinedMatrix; - setIspParams.emit(); + setIspParams.emit(paramsBufferId); } void IPASoftSimple::processStats(const uint32_t frame, diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index dccdd86b4..e2e294d3e 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -105,9 +105,10 @@ Debayer::~Debayer() */ /** - * \fn void Debayer::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) + * \fn void Debayer::process(uint32_t frame, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output, DebayerParams params) * \brief Process the bayer data into the requested format * \param[in] frame The frame number + * \param[in] paramsBufferId The id of the params buffer in use * \param[in] input The input buffer * \param[in] output The output buffer * \param[in] params The parameters to be used in debayering @@ -176,6 +177,9 @@ Debayer::~Debayer() * * \var Debayer::DebayerInputConfig::outputFormats * List of pixel formats supported as output for this input configuration. + * + * \var Signal Debayer::releaseIspParams + * \brief Signals when the processing params are no longer needed */ /** diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index ce9350b7b..0c9627d30 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -47,7 +47,10 @@ public: virtual std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0; - virtual void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) = 0; + virtual void process(uint32_t frame, + const uint32_t paramsBufferId, + FrameBuffer *input, FrameBuffer *output, + const DebayerParams ¶ms) = 0; virtual int start() { return 0; } virtual void stop() {} @@ -59,6 +62,7 @@ public: Signal inputBufferReady; Signal outputBufferReady; + Signal releaseIspParams; struct DebayerInputConfig { Size patternSize; diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index d09883577..5d0e780f7 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -842,7 +842,9 @@ void DebayerCpu::updateLookupTables(const DebayerParams ¶ms) params_ = params; } -void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) +void DebayerCpu::process(uint32_t frame, const uint32_t paramsBufferId, + FrameBuffer *input, FrameBuffer *output, + const DebayerParams ¶ms) { bench_.startFrame(); @@ -852,6 +854,8 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output updateLookupTables(params); + releaseIspParams.emit(paramsBufferId); + /* Copy metadata from the input buffer */ FrameMetadata &metadata = output->_d()->metadata(); metadata.status = input->metadata().status; diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 7a6517462..13253f999 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -39,7 +39,9 @@ public: std::vector formats(PixelFormat input); std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); - void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms); + void process(uint32_t frame, + const uint32_t paramsBufferId, + FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms); SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); const SharedFD &getStatsFD() { return stats_->getStatsFD(); } diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 93f7c6946..947c05c07 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -533,7 +533,9 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam return 0; } -void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) +void DebayerEGL::process(uint32_t frame, const uint32_t paramsBufferId, + FrameBuffer *input, FrameBuffer *output, + const DebayerParams ¶ms) { bench_.startFrame(); @@ -557,6 +559,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output LOG(Debayer, Error) << "debayerGPU failed"; goto error; } + releaseIspParams.emit(paramsBufferId); bench_.finishFrame(); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 59aebcc81..7f29f53e6 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -50,7 +50,9 @@ public: std::vector formats(PixelFormat input); std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); - void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms); + void process(uint32_t frame, const uint32_t paramsBufferId, + FrameBuffer *input, FrameBuffer *output, + const DebayerParams ¶ms); int start(); void stop(); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index a83986b78..0447d2171 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -123,6 +123,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); + debayer_->releaseIspParams.connect(this, &SoftwareIsp::releaseIspParams); ipa_ = IPAManager::createIPA(pipe, 0, 0); if (!ipa_) { @@ -396,16 +397,22 @@ void SoftwareIsp::stop() */ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output) { - ipa_->computeParams(frame); + /* \todo Provide a real value */ + constexpr uint32_t paramsBufferId = 0; + ipa_->computeParams(frame, paramsBufferId); debayer_->invokeMethod(&Debayer::process, - ConnectionTypeQueued, frame, input, output, debayerParams_); + ConnectionTypeQueued, frame, paramsBufferId, input, output, debayerParams_); } -void SoftwareIsp::saveIspParams() +void SoftwareIsp::saveIspParams([[maybe_unused]] uint32_t paramsBufferId) { debayerParams_ = *sharedParams_; } +void SoftwareIsp::releaseIspParams([[maybe_unused]] uint32_t paramsBufferId) +{ +} + void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls) { setSensorControls.emit(sensorControls); From patchwork Mon Feb 16 20:30:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26172 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 12F0FC0DA4 for ; Mon, 16 Feb 2026 20:30:52 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 97CC16220E; Mon, 16 Feb 2026 21:30:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="MtQo3kvF"; 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 1176C62205 for ; Mon, 16 Feb 2026 21:30:49 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273848; 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=ty7Pl+oSdBnm4kdYhkv46mxz2PSFLMnGeRLtqMy2QL8=; b=MtQo3kvF4ifoCsSq4kTh3/dof8bZ0IDqOeUsXg+WNVaNTPXfuQqMux4UYGZMi+zyc0dAt0 AhLLQ86rNtyItFz+gCluOrIwLTxpFpXyP+SO1XTGAlqbGrV3rIYFKDo7j9LSh7U3qLaLhp anbm/sUN9FHqG4VgKgCdhUOZ7Fc6wIM= Received: from mx-prod-mc-01.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-130-WgpgWodQM1O9DgPM1_2r-A-1; Mon, 16 Feb 2026 15:30:47 -0500 X-MC-Unique: WgpgWodQM1O9DgPM1_2r-A-1 X-Mimecast-MFC-AGG-ID: WgpgWodQM1O9DgPM1_2r-A_1771273846 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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9B9BE1956094 for ; Mon, 16 Feb 2026 20:30:46 +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 60AE518004AD; Mon, 16 Feb 2026 20:30:45 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 03/14] libcamera: software_isp: Separate allocation of the parameters buffer Date: Mon, 16 Feb 2026 21:30:22 +0100 Message-ID: <20260216203034.27558-4-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: dyg-1wE3eKow6gOVClPMHfW1VewQj3PP4zTOE7MCqqI_1771273846 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" There will be some additions to that code in followup patches and let's not blow the code in SoftwareIsp constructor even more. Signed-off-by: Milan Zamazal --- .../internal/software_isp/software_isp.h | 1 + src/libcamera/software_isp/software_isp.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 30b25cddf..dc6b6f7c1 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -98,6 +98,7 @@ private: Thread ispWorkerThread_; SharedMemObject sharedParams_; DebayerParams debayerParams_; + bool allocateParamsBuffers(); DmaBufAllocator dmaHeap_; bool ccmEnabled_; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 0447d2171..dc0a8eb84 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -88,12 +88,8 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, LOG(SoftwareIsp, Error) << "Failed to create DmaBufAllocator object"; return; } - - sharedParams_ = SharedMemObject("softIsp_params"); - if (!sharedParams_) { - LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; + if (!allocateParamsBuffers()) return; - } const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration(); @@ -176,6 +172,17 @@ SoftwareIsp::~SoftwareIsp() debayer_.reset(); } +bool SoftwareIsp::allocateParamsBuffers() +{ + sharedParams_ = SharedMemObject("softIsp_params"); + if (!sharedParams_) { + LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; + return false; + } + + return true; +} + /** * \fn int SoftwareIsp::loadConfiguration([[maybe_unused]] const std::string &filename) * \brief Load a configuration from a file From patchwork Mon Feb 16 20:30:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26173 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 6A551C0DA4 for ; Mon, 16 Feb 2026 20:30:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 33E6462217; Mon, 16 Feb 2026 21:30:54 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="OvLrocve"; 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 016BB62217 for ; Mon, 16 Feb 2026 21:30:51 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273850; 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=kIWpIUzUQXN9/tCaqd8lQIkAEIvvGtlhVkYtCxSXG4I=; b=OvLrocvekkyOrqXemH1ycQlD+soe7NLVf6ej5vmcONYqcrJKiol3ymqS+QKuRlGueptwwW W961Yje2fqQWcBtMxJ6FXHGHLH+AKqIj4orpgeSYXjH5TQr93xq+talzfnzN/Cl6QfBOHo G2SufLmV5G2W/+o04RM7+8Gp9puwV74= 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-523-K96L4ck-OPSqiy_AJxfJaQ-1; Mon, 16 Feb 2026 15:30:49 -0500 X-MC-Unique: K96L4ck-OPSqiy_AJxfJaQ-1 X-Mimecast-MFC-AGG-ID: K96L4ck-OPSqiy_AJxfJaQ_1771273848 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 300EB195608A for ; Mon, 16 Feb 2026 20:30:48 +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 1ED7F18004AD; Mon, 16 Feb 2026 20:30:46 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 04/14] libcamera: software_isp: Track unused parameters buffers Date: Mon, 16 Feb 2026 21:30:23 +0100 Message-ID: <20260216203034.27558-5-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: 3YGvVjDv_XonIG37-O1du6YIbftcCgLdh-5gb9tuPrs_1771273848 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" As a preparation for introducing a ring of parameters buffers, this patch introduces tracking of parameters buffers available for use. SofwareIsp::availableParams_ is a queue of ids of the buffers available for use. When a fresh parameter buffer is needed, its id is retrieved from there and once the buffer is no longer needed, it's put back there, in a method invoked by a signal. This is similar to what the hardware pipelines do. If a parameters buffer is requested but there is no free available, it is an erroneous situation. To recover from it, we have currently no better mechanism than to wait for an available buffer. Simply returning from the processing would mean the finishing signals are not called, resulting in e.g. the input buffer not being returned. This is different from the hardware pipelines, which are structured somewhat differently. We use buffers' file descriptors as buffer ids. The parameters buffers will be shared with the IPA and debayering and we need their common identification everywhere. The buffer file descriptors are shared unchanged so they can be used for the purpose, avoiding a need to pass a special id->buffer mapping to the IPA and debayering on initialization. Note that the parameters buffer id is still actually unused and the only buffer currently used is still copied when passed to debayering. This patch is just preparation for followup patches that will introduce multiple buffers. Signed-off-by: Milan Zamazal --- .../internal/software_isp/software_isp.h | 2 ++ src/libcamera/software_isp/software_isp.cpp | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index dc6b6f7c1..a8b7b1eb1 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,7 @@ private: Thread ispWorkerThread_; SharedMemObject sharedParams_; DebayerParams debayerParams_; + std::queue availableParams_; bool allocateParamsBuffers(); DmaBufAllocator dmaHeap_; bool ccmEnabled_; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index dc0a8eb84..adf2a03ab 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -180,6 +180,10 @@ bool SoftwareIsp::allocateParamsBuffers() return false; } + ASSERT(sharedParams_.fd().get() >= 0); + const uint32_t bufferId = sharedParams_.fd().get(); + availableParams_.push(bufferId); + return true; } @@ -404,8 +408,15 @@ void SoftwareIsp::stop() */ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output) { - /* \todo Provide a real value */ - constexpr uint32_t paramsBufferId = 0; + if (availableParams_.empty()) { + LOG(SoftwareIsp, Error) << "Parameters buffer underrun"; + /* Well, busy loop, but this situation shouldn't normally happen. */ + while (availableParams_.empty()) + ; + } + + const uint32_t paramsBufferId = availableParams_.front(); + availableParams_.pop(); ipa_->computeParams(frame, paramsBufferId); debayer_->invokeMethod(&Debayer::process, ConnectionTypeQueued, frame, paramsBufferId, input, output, debayerParams_); @@ -416,8 +427,9 @@ void SoftwareIsp::saveIspParams([[maybe_unused]] uint32_t paramsBufferId) debayerParams_ = *sharedParams_; } -void SoftwareIsp::releaseIspParams([[maybe_unused]] uint32_t paramsBufferId) +void SoftwareIsp::releaseIspParams(uint32_t paramsBufferId) { + availableParams_.push(paramsBufferId); } void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls) From patchwork Mon Feb 16 20:30:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26174 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 2EC95C3240 for ; Mon, 16 Feb 2026 20:30:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BCF986221D; Mon, 16 Feb 2026 21:30:54 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="bjOe56y/"; 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 0E92662084 for ; Mon, 16 Feb 2026 21:30:52 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273852; 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=twgfqRH8J7fMXozHckLElKte++XFWy/wmRvClY9+4Q4=; b=bjOe56y/HNYvckpi4YHCvmgYEobJXl82LQMZWZ6fPRoWmDJ1sEjzhhh0I3VSmF8T9e2IeG JYxRKCML5Y4wtUfQilTxrtK0LuxQEQeWgbwsJbXqCL6xmSYeppy1xYqawiumB64aDBlESQ 28itmylgKYkDW91J3AYuebDtLR8PLQ0= Received: from mx-prod-mc-01.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-581-Np4WMyeYMsqotxzE9gyoHQ-1; Mon, 16 Feb 2026 15:30:50 -0500 X-MC-Unique: Np4WMyeYMsqotxzE9gyoHQ-1 X-Mimecast-MFC-AGG-ID: Np4WMyeYMsqotxzE9gyoHQ_1771273850 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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 03F531955D96 for ; Mon, 16 Feb 2026 20:30:50 +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 DC44F18004AD; Mon, 16 Feb 2026 20:30:48 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 05/14] libcamera: software_isp: Allocation of multiple params buffers Date: Mon, 16 Feb 2026 21:30:24 +0100 Message-ID: <20260216203034.27558-6-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: YRZSrCUNDDSdOI_tBhQmD4GYszo4285-S0TmSx_J18A_1771273850 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" SoftwareIsp::sharedParams_ is changed from a single buffer to a map of multiple buffer ids and the corresponding buffers. This requires some code rearranging within SoftwareIsp::allocateBuffers to keep the right sequence of actions. Currently, only a single buffer is allocated, this will be changed in a followup patch. Signed-off-by: Milan Zamazal --- .../internal/software_isp/software_isp.h | 3 +- src/libcamera/software_isp/software_isp.cpp | 28 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index a8b7b1eb1..f809e6be8 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -97,7 +97,8 @@ private: void outputReady(FrameBuffer *output); std::unique_ptr debayer_; Thread ispWorkerThread_; - SharedMemObject sharedParams_; + static constexpr unsigned int kParamStatBufferCount = 1; + std::map> sharedParams_; DebayerParams debayerParams_; std::queue availableParams_; bool allocateParamsBuffers(); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index adf2a03ab..79d5dfe0e 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -70,6 +70,11 @@ LOG_DEFINE_CATEGORY(SoftwareIsp) * ready */ +/** + * \var SoftwareIsp::kParamStatBufferCount + * \brief The number of stats and params buffers (each of them) + */ + /** * \brief Constructs SoftwareIsp object * \param[in] pipe The pipeline handler in use @@ -145,7 +150,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, ret = ipa_->init(IPASettings{ ipaTuningFile, sensor->model() }, debayer_->getStatsFD(), - sharedParams_.fd(), + sharedParams_.begin()->second.fd(), sensorInfo, sensor->controls(), ipaControls, @@ -174,15 +179,18 @@ SoftwareIsp::~SoftwareIsp() bool SoftwareIsp::allocateParamsBuffers() { - sharedParams_ = SharedMemObject("softIsp_params"); - if (!sharedParams_) { - LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; - return false; - } + for (unsigned int i = 0; i < kParamStatBufferCount; i++) { + auto params = SharedMemObject("softIsp_params"); + if (!params) { + LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; + return false; + } - ASSERT(sharedParams_.fd().get() >= 0); - const uint32_t bufferId = sharedParams_.fd().get(); - availableParams_.push(bufferId); + ASSERT(params.fd().get() >= 0); + const uint32_t bufferId = params.fd().get(); + availableParams_.push(bufferId); + sharedParams_.emplace(bufferId, std::move(params)); + } return true; } @@ -424,7 +432,7 @@ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *outpu void SoftwareIsp::saveIspParams([[maybe_unused]] uint32_t paramsBufferId) { - debayerParams_ = *sharedParams_; + debayerParams_ = *sharedParams_.begin()->second; } void SoftwareIsp::releaseIspParams(uint32_t paramsBufferId) From patchwork Mon Feb 16 20:30:25 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26175 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 D824AC0DA4 for ; Mon, 16 Feb 2026 20:30:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 951F262220; Mon, 16 Feb 2026 21:30:56 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="J/4Ax2dO"; 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 99E676221A for ; Mon, 16 Feb 2026 21:30:55 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273854; 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=Gdu6LfsyVcCj28wb76kIQZpoG81Uao3Kk/9avHTprZY=; b=J/4Ax2dOaKEQYffJ4dkBwcUGbzsIZ44gDn2KblDVA3KT6AY24WjiV9sesmuD7Pp0SnHc18 e3VQ6Wbt8R1cl2+L+JJVYhMkGUZAipoqcSCmWAgq+IZU9JPEzQSWVNeDYwC5o/MfA4fZ8C Y50PPdWP4GSkzzvjTrDcWf6V+wxufBQ= Received: from mx-prod-mc-01.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-202-J5JjY4moMoKDxjOxyaYJDA-1; Mon, 16 Feb 2026 15:30:52 -0500 X-MC-Unique: J5JjY4moMoKDxjOxyaYJDA-1 X-Mimecast-MFC-AGG-ID: J5JjY4moMoKDxjOxyaYJDA_1771273851 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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D18511955DDF for ; Mon, 16 Feb 2026 20:30:51 +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 940FF1800464; Mon, 16 Feb 2026 20:30:50 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 06/14] libcamera: software_isp: Allocate multiple parameters buffers Date: Mon, 16 Feb 2026 21:30:25 +0100 Message-ID: <20260216203034.27558-7-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: kLVktF3DdG1aZiBq6tLyr98xviYJX2M7_3giQMSH6S8_1771273851 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" We want to use more than one parameters buffer. Processing statistics (and setting the corresponding parameters) is asynchronous and may work with a parameters buffer while the last parameters buffer may be in or wait for use in debayering. The question is how many buffer we need. A starting idea might be to use the same number as for input and output buffers. This may not be necessarily the best or even correct idea, but if the number of those buffers is sufficient now then perhaps the same number of the parameters buffers (and later statistics buffers) would work. Unless multiple streams are used... Nevertheless, the number of the input and output buffers is currently fixed, which makes it possible to use in init, before configure, where the current single buffer is allocated. It just requires to make the given constant public in SimplePipelineHandler so that it can be passed to the SoftwareIsp constructor. Another alternative would be to determine the right number of buffers in SoftwareIsp::configure. This would be more complicated as it would require some more refactoring, allocating the buffers in configure and passing their file descriptors to the IPA and debayering on demand. Only the first allocated buffer is actually used at the moment. This will be changed in the followup patches once support for multiple buffers is added to the IPA and debayering. Signed-off-by: Milan Zamazal --- .../libcamera/internal/software_isp/software_isp.h | 6 +++--- src/libcamera/pipeline/simple/simple.cpp | 5 +++-- src/libcamera/software_isp/software_isp.cpp | 14 +++++--------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index f809e6be8..65348e213 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -49,7 +49,8 @@ class SoftwareIsp : public Object { public: SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, - ControlInfoMap *ipaControls); + ControlInfoMap *ipaControls, + const unsigned int bufferCount); ~SoftwareIsp(); int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } @@ -97,11 +98,10 @@ private: void outputReady(FrameBuffer *output); std::unique_ptr debayer_; Thread ispWorkerThread_; - static constexpr unsigned int kParamStatBufferCount = 1; std::map> sharedParams_; DebayerParams debayerParams_; std::queue availableParams_; - bool allocateParamsBuffers(); + bool allocateParamsBuffers(const unsigned int bufferCount); DmaBufAllocator dmaHeap_; bool ccmEnabled_; diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 4a0b9f58d..dc9176c29 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -427,13 +427,13 @@ public: V4L2Subdevice *subdev(const MediaEntity *entity); std::shared_ptr converter() { return converter_; } bool swIspEnabled() const { return swIspEnabled_; } + static constexpr unsigned int kNumInternalBuffers = 4; protected: int queueRequestDevice(Camera *camera, Request *request) override; private: static constexpr unsigned int kMaxQueuedRequestsDevice = 4; - static constexpr unsigned int kNumInternalBuffers = 4; struct EntityData { std::unique_ptr video; @@ -615,7 +615,8 @@ int SimpleCameraData::init() * Instantiate Soft ISP if this is enabled for the given driver and no converter is used. */ if (!converter_ && pipe->swIspEnabled()) { - swIsp_ = std::make_unique(pipe, sensor_.get(), &controlInfo_); + swIsp_ = std::make_unique(pipe, sensor_.get(), &controlInfo_, + pipe->kNumInternalBuffers); if (!swIsp_->isValid()) { LOG(SimplePipeline, Warning) << "Failed to create software ISP, disabling software debayering"; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 79d5dfe0e..02d1c4c12 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -70,20 +70,16 @@ LOG_DEFINE_CATEGORY(SoftwareIsp) * ready */ -/** - * \var SoftwareIsp::kParamStatBufferCount - * \brief The number of stats and params buffers (each of them) - */ - /** * \brief Constructs SoftwareIsp object * \param[in] pipe The pipeline handler in use * \param[in] sensor Pointer to the CameraSensor instance owned by the pipeline * \param[out] ipaControls The IPA controls to update + * \param[in] bufferCount Number of parameters buffers and stats buffers to allocate * handler */ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, - ControlInfoMap *ipaControls) + ControlInfoMap *ipaControls, const unsigned bufferCount) : ispWorkerThread_("SWIspWorker"), dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap | DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap | @@ -93,7 +89,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, LOG(SoftwareIsp, Error) << "Failed to create DmaBufAllocator object"; return; } - if (!allocateParamsBuffers()) + if (!allocateParamsBuffers(bufferCount)) return; const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration(); @@ -177,9 +173,9 @@ SoftwareIsp::~SoftwareIsp() debayer_.reset(); } -bool SoftwareIsp::allocateParamsBuffers() +bool SoftwareIsp::allocateParamsBuffers(const unsigned int bufferCount) { - for (unsigned int i = 0; i < kParamStatBufferCount; i++) { + for (unsigned int i = 0; i < bufferCount; i++) { auto params = SharedMemObject("softIsp_params"); if (!params) { LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; From patchwork Mon Feb 16 20:30:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26176 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 54EA6C0DA4 for ; Mon, 16 Feb 2026 20:30:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1F3296221A; Mon, 16 Feb 2026 21:30:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="GwGKe/mF"; 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 058656220C for ; Mon, 16 Feb 2026 21:30:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273855; 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=Ld0wUn/+nR/TQtrMxBgNUzu+VA8koimtcWOyHHwSsJU=; b=GwGKe/mFkHXryvMMQJTVFDEsOeMt5+ITEW4qqvLFgnA4JJI7svHaEC0zy9ehyDml/0dahy L7q61R58SYsanNzszriOnR1SEgtKmTBEGjp85e7x+5qa8KTX6PKox4Xz8aqMtWDB4fxvR3 6IRv6W9cqAcDVFM0x54ZcMoiirav1ow= 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-346--S1uuduGNz662YgwhEmjsA-1; Mon, 16 Feb 2026 15:30:54 -0500 X-MC-Unique: -S1uuduGNz662YgwhEmjsA-1 X-Mimecast-MFC-AGG-ID: -S1uuduGNz662YgwhEmjsA_1771273853 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 AB80A1955D8F for ; Mon, 16 Feb 2026 20:30:53 +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 6E0651800464; Mon, 16 Feb 2026 20:30:52 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 07/14] libcamera: software_isp: Use multiple parameters buffers in IPA Date: Mon, 16 Feb 2026 21:30:26 +0100 Message-ID: <20260216203034.27558-8-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: XRy0da1NKtwDu7XMRaLctr53x5hPOBLeLKwfXv_HemA_1771273853 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" Instead of the single parameters buffer file descriptor, pass the file descriptors of all the parameters buffers to the IPA and let it use them according to the passed buffer id. This means: - The file descriptors of all the buffers must be passed to the IPA. - The IPA must store mappings of the buffer ids to the corresponding buffers. - The current buffer id is passed to/from the IPA. The parameters buffers are still copied for debayering, this will be addressed in the next patch. Signed-off-by: Milan Zamazal --- include/libcamera/ipa/soft.mojom | 2 +- src/ipa/simple/soft_simple.cpp | 41 +++++++++++---------- src/libcamera/software_isp/software_isp.cpp | 11 ++++-- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index f37c1e747..4738a1b46 100644 --- a/include/libcamera/ipa/soft.mojom +++ b/include/libcamera/ipa/soft.mojom @@ -15,7 +15,7 @@ struct IPAConfigInfo { interface IPASoftInterface { init(libcamera.IPASettings settings, libcamera.SharedFD fdStats, - libcamera.SharedFD fdParams, + array fdParams, libcamera.IPACameraSensorInfo sensorInfo, libcamera.ControlInfoMap sensorControls) => (int32 ret, libcamera.ControlInfoMap ipaControls, bool ccmEnabled); diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index 1e8b5334c..f212fabe3 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -53,7 +53,7 @@ public: int init(const IPASettings &settings, const SharedFD &fdStats, - const SharedFD &fdParams, + const std::vector &fdParams, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls, @@ -76,7 +76,7 @@ protected: private: void updateExposure(double exposureMSV); - DebayerParams *params_; + std::map paramsBuffers_; SwIspStats *stats_; std::unique_ptr camHelper_; ControlInfoMap sensorInfoMap_; @@ -89,13 +89,13 @@ IPASoftSimple::~IPASoftSimple() { if (stats_) munmap(stats_, sizeof(SwIspStats)); - if (params_) - munmap(params_, sizeof(DebayerParams)); + for (auto &item : paramsBuffers_) + munmap(item.second, sizeof(DebayerParams)); } int IPASoftSimple::init(const IPASettings &settings, const SharedFD &fdStats, - const SharedFD &fdParams, + const std::vector &fdParams, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls, @@ -138,8 +138,6 @@ int IPASoftSimple::init(const IPASettings &settings, return ret; *ccmEnabled = context_.ccmEnabled; - - params_ = nullptr; stats_ = nullptr; if (!fdStats.isValid()) { @@ -147,25 +145,27 @@ int IPASoftSimple::init(const IPASettings &settings, return -ENODEV; } - if (!fdParams.isValid()) { - LOG(IPASoft, Error) << "Invalid Parameters handle"; - return -ENODEV; - } + for (auto &sharedFd : fdParams) { + if (!sharedFd.isValid()) { + LOG(IPASoft, Error) << "Invalid Parameters handle"; + return -ENODEV; + } - { void *mem = mmap(nullptr, sizeof(DebayerParams), PROT_WRITE, - MAP_SHARED, fdParams.get(), 0); + MAP_SHARED, sharedFd.get(), 0); if (mem == MAP_FAILED) { LOG(IPASoft, Error) << "Unable to map Parameters"; return -errno; } - params_ = static_cast(mem); - params_->blackLevel = { { 0.0, 0.0, 0.0 } }; - params_->gamma = 1.0 / algorithms::kDefaultGamma; - params_->contrastExp = 1.0; - params_->gains = { { 1.0, 1.0, 1.0 } }; + ASSERT(sharedFd.get() >= 0); + DebayerParams *params = static_cast(mem); + params->blackLevel = { { 0.0, 0.0, 0.0 } }; + params->gamma = 1.0 / algorithms::kDefaultGamma; + params->contrastExp = 1.0; + params->gains = { { 1.0, 1.0, 1.0 } }; /* combinedMatrix is reset for each frame. */ + paramsBuffers_[sharedFd.get()] = params; } { @@ -291,9 +291,10 @@ void IPASoftSimple::computeParams(const uint32_t frame, context_.activeState.combinedMatrix = Matrix::identity(); IPAFrameContext &frameContext = context_.frameContexts.get(frame); + DebayerParams *params = paramsBuffers_.at(paramsBufferId); for (auto const &algo : algorithms()) - algo->prepare(context_, frame, frameContext, params_); - params_->combinedMatrix = context_.activeState.combinedMatrix; + algo->prepare(context_, frame, frameContext, params); + params->combinedMatrix = context_.activeState.combinedMatrix; setIspParams.emit(paramsBufferId); } diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 02d1c4c12..2bc0d30b1 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -118,6 +119,9 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, if (!debayer_) debayer_ = std::make_unique(std::move(stats), configuration); + std::vector fdParams; + for (auto &item : sharedParams_) + fdParams.emplace_back(item.second.fd()); debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); debayer_->releaseIspParams.connect(this, &SoftwareIsp::releaseIspParams); @@ -146,7 +150,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, ret = ipa_->init(IPASettings{ ipaTuningFile, sensor->model() }, debayer_->getStatsFD(), - sharedParams_.begin()->second.fd(), + fdParams, sensorInfo, sensor->controls(), ipaControls, @@ -422,13 +426,14 @@ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *outpu const uint32_t paramsBufferId = availableParams_.front(); availableParams_.pop(); ipa_->computeParams(frame, paramsBufferId); + debayerParams_ = *sharedParams_.at(paramsBufferId); debayer_->invokeMethod(&Debayer::process, ConnectionTypeQueued, frame, paramsBufferId, input, output, debayerParams_); } -void SoftwareIsp::saveIspParams([[maybe_unused]] uint32_t paramsBufferId) +void SoftwareIsp::saveIspParams(uint32_t paramsBufferId) { - debayerParams_ = *sharedParams_.begin()->second; + debayerParams_ = *sharedParams_.at(paramsBufferId); } void SoftwareIsp::releaseIspParams(uint32_t paramsBufferId) From patchwork Mon Feb 16 20:30:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26177 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 E12A0C0DA4 for ; Mon, 16 Feb 2026 20:31:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ABD0162225; Mon, 16 Feb 2026 21:31:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="d0aBWrSN"; 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 0B08D62084 for ; Mon, 16 Feb 2026 21:30:58 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273858; 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=iCTExq9BSjDZs1cYMuDKGmre0Nkq/Rsd9MERn2JpJ+k=; b=d0aBWrSNbZR/bs7zeq2m87qCWfDF/UpvMZgI9x3o5du04TLB+YdK05DDvY/f+7b5n4+0QN dVxZ/4+pRyUhBjUP8JdewgzyYTo59DxG8GbbVX3Tj2MiTKYTqXuTKtr8e+dLIFoLCSDtbp fNxOHXXT8IgmsURwmhcXsO6TcYciGFE= Received: from mx-prod-mc-03.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-540-Vvl4J4RGO82krFpIB2XERA-1; Mon, 16 Feb 2026 15:30:56 -0500 X-MC-Unique: Vvl4J4RGO82krFpIB2XERA-1 X-Mimecast-MFC-AGG-ID: Vvl4J4RGO82krFpIB2XERA_1771273855 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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B7CB119560B2 for ; Mon, 16 Feb 2026 20:30:55 +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 47AE41800464; Mon, 16 Feb 2026 20:30:53 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 08/14] libcamera: software_isp: Share parameters buffers with debayering Date: Mon, 16 Feb 2026 21:30:27 +0100 Message-ID: <20260216203034.27558-9-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: gcI9mzU4riC5yfUrVh9B3nRaQxSTKwDMs3pgZaIjx4M_1771273855 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" Share the multiple parameters buffers with debayering rather than copying the current parameters buffer there. This is done in a similar way as sharing the buffers with IPA in the preceding patch. Signed-off-by: Milan Zamazal --- src/libcamera/software_isp/debayer.cpp | 27 ++++++++- src/libcamera/software_isp/debayer.h | 7 ++- src/libcamera/software_isp/debayer_cpu.cpp | 67 +++++++++++---------- src/libcamera/software_isp/debayer_cpu.h | 11 ++-- src/libcamera/software_isp/debayer_egl.cpp | 14 +++-- src/libcamera/software_isp/debayer_egl.h | 7 ++- src/libcamera/software_isp/software_isp.cpp | 16 ++--- 7 files changed, 92 insertions(+), 57 deletions(-) diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index e2e294d3e..ad47c1e8d 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -11,6 +11,8 @@ #include "debayer.h" +#include + namespace libcamera { /** @@ -21,6 +23,7 @@ namespace libcamera { /** * \fn Debayer::Debayer(const GlobalConfiguration &configuration) * \brief Construct a Debayer object + * \param[in] paramsBuffers SharedFDs of parameter buffers * \param[in] configuration Global configuration reference */ @@ -58,8 +61,22 @@ namespace libcamera { LOG_DEFINE_CATEGORY(Debayer) -Debayer::Debayer(const GlobalConfiguration &configuration) : bench_(configuration) +Debayer::Debayer(const std::vector ¶msBuffers, + const GlobalConfiguration &configuration) : bench_(configuration) { + paramsBuffers_ = std::map(); + + for (auto &sharedFd : paramsBuffers) { + void *mem = mmap(nullptr, sizeof(DebayerParams), PROT_WRITE, + MAP_SHARED, sharedFd.get(), 0); + if (mem == MAP_FAILED) { + LOG(Debayer, Error) << "Unable to map Parameters"; + return; + } + + ASSERT(sharedFd.get() >= 0); + paramsBuffers_[sharedFd.get()] = static_cast(mem); + } } Debayer::~Debayer() @@ -105,13 +122,12 @@ Debayer::~Debayer() */ /** - * \fn void Debayer::process(uint32_t frame, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output, DebayerParams params) + * \fn void Debayer::process(uint32_t frame, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output) * \brief Process the bayer data into the requested format * \param[in] frame The frame number * \param[in] paramsBufferId The id of the params buffer in use * \param[in] input The input buffer * \param[in] output The output buffer - * \param[in] params The parameters to be used in debayering * * \note DebayerParams is passed by value deliberately so that a copy is passed * when this is run in another thread by invokeMethod(). @@ -239,6 +255,11 @@ Debayer::~Debayer() * reversed. */ +/** + * \var Debayer::paramsBuffers_ + * \brief Ring of debayering parameters buffers + */ + /** * \var Debayer::bench_ * \brief Benchmarking utility instance for performance measurements diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index 0c9627d30..a66d0cbbe 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -35,7 +35,8 @@ LOG_DECLARE_CATEGORY(Debayer) class Debayer : public Object { public: - Debayer(const GlobalConfiguration &configuration); + Debayer(const std::vector ¶msBuffers, + const GlobalConfiguration &configuration); virtual ~Debayer() = 0; virtual int configure(const StreamConfiguration &inputCfg, @@ -49,8 +50,7 @@ public: virtual void process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output, - const DebayerParams ¶ms) = 0; + FrameBuffer *input, FrameBuffer *output) = 0; virtual int start() { return 0; } virtual void stop() {} @@ -83,6 +83,7 @@ public: PixelFormat inputPixelFormat_; PixelFormat outputPixelFormat_; bool swapRedBlueGains_; + std::map paramsBuffers_; Benchmark bench_; private: diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 5d0e780f7..927ac7d10 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -12,13 +12,14 @@ #include "debayer_cpu.h" #include -#include #include #include #include #include +#include + #include #include "libcamera/internal/bayer_format.h" @@ -38,10 +39,13 @@ namespace libcamera { /** * \brief Constructs a DebayerCpu object * \param[in] stats Pointer to the stats object to use + * \param[in] paramsBuffers SharedFDs of parameter buffers * \param[in] configuration The global configuration */ -DebayerCpu::DebayerCpu(std::unique_ptr stats, const GlobalConfiguration &configuration) - : Debayer(configuration), stats_(std::move(stats)) +DebayerCpu::DebayerCpu(std::unique_ptr stats, + const std::vector ¶msBuffers, + const GlobalConfiguration &configuration) + : Debayer(paramsBuffers, configuration), stats_(std::move(stats)) { /* * Reading from uncached buffers may be very slow. @@ -750,13 +754,13 @@ void DebayerCpu::process4(uint32_t frame, const uint8_t *src, uint8_t *dst) } } -void DebayerCpu::updateGammaTable(const DebayerParams ¶ms) +void DebayerCpu::updateGammaTable(const DebayerParams *params) { - const RGB blackLevel = params.blackLevel; + const RGB blackLevel = params->blackLevel; /* Take let's say the green channel black level */ const unsigned int blackIndex = blackLevel[1] * gammaTable_.size(); - const float gamma = params.gamma; - const float contrastExp = params.contrastExp; + const float gamma = params->gamma; + const float contrastExp = params->contrastExp; const float divisor = gammaTable_.size() - blackIndex - 1.0; for (unsigned int i = blackIndex; i < gammaTable_.size(); i++) { @@ -780,12 +784,12 @@ void DebayerCpu::updateGammaTable(const DebayerParams ¶ms) gammaTable_[blackIndex]); } -void DebayerCpu::updateLookupTables(const DebayerParams ¶ms) +void DebayerCpu::updateLookupTables(const DebayerParams *params) { const bool gammaUpdateNeeded = - params.gamma != params_.gamma || - params.blackLevel != params_.blackLevel || - params.contrastExp != params_.contrastExp; + params->gamma != params_.gamma || + params->blackLevel != params_.blackLevel || + params->contrastExp != params_.contrastExp; if (gammaUpdateNeeded) updateGammaTable(params); @@ -796,7 +800,7 @@ void DebayerCpu::updateLookupTables(const DebayerParams ¶ms) const double div = static_cast(kRGBLookupSize) / gammaTableSize; if (ccmEnabled_) { if (gammaUpdateNeeded || - matrixChanged(params.combinedMatrix, params_.combinedMatrix)) { + matrixChanged(params->combinedMatrix, params_.combinedMatrix)) { auto &red = swapRedBlueGains_ ? blueCcm_ : redCcm_; auto &green = greenCcm_; auto &blue = swapRedBlueGains_ ? redCcm_ : blueCcm_; @@ -804,21 +808,21 @@ void DebayerCpu::updateLookupTables(const DebayerParams ¶ms) const unsigned int greenIndex = 1; const unsigned int blueIndex = swapRedBlueGains_ ? 0 : 2; for (unsigned int i = 0; i < kRGBLookupSize; i++) { - red[i].r = std::round(i * params.combinedMatrix[redIndex][0]); - red[i].g = std::round(i * params.combinedMatrix[greenIndex][0]); - red[i].b = std::round(i * params.combinedMatrix[blueIndex][0]); - green[i].r = std::round(i * params.combinedMatrix[redIndex][1]); - green[i].g = std::round(i * params.combinedMatrix[greenIndex][1]); - green[i].b = std::round(i * params.combinedMatrix[blueIndex][1]); - blue[i].r = std::round(i * params.combinedMatrix[redIndex][2]); - blue[i].g = std::round(i * params.combinedMatrix[greenIndex][2]); - blue[i].b = std::round(i * params.combinedMatrix[blueIndex][2]); + red[i].r = std::round(i * params->combinedMatrix[redIndex][0]); + red[i].g = std::round(i * params->combinedMatrix[greenIndex][0]); + red[i].b = std::round(i * params->combinedMatrix[blueIndex][0]); + green[i].r = std::round(i * params->combinedMatrix[redIndex][1]); + green[i].g = std::round(i * params->combinedMatrix[greenIndex][1]); + green[i].b = std::round(i * params->combinedMatrix[blueIndex][1]); + blue[i].r = std::round(i * params->combinedMatrix[redIndex][2]); + blue[i].g = std::round(i * params->combinedMatrix[greenIndex][2]); + blue[i].b = std::round(i * params->combinedMatrix[blueIndex][2]); gammaLut_[i] = gammaTable_[i / div]; } } } else { - if (gammaUpdateNeeded || params.gains != params_.gains) { - auto &gains = params.gains; + if (gammaUpdateNeeded || params->gains != params_.gains) { + auto &gains = params->gains; auto &red = swapRedBlueGains_ ? blue_ : red_; auto &green = green_; auto &blue = swapRedBlueGains_ ? red_ : blue_; @@ -833,18 +837,17 @@ void DebayerCpu::updateLookupTables(const DebayerParams ¶ms) } LOG(Debayer, Debug) - << "Debayer parameters: blackLevel=" << params.blackLevel - << "; gamma=" << params.gamma - << "; contrastExp=" << params.contrastExp - << "; gains=" << params.gains - << "; matrix=" << params.combinedMatrix; + << "Debayer parameters: blackLevel=" << params->blackLevel + << "; gamma=" << params->gamma + << "; contrastExp=" << params->contrastExp + << "; gains=" << params->gains + << "; matrix=" << params->combinedMatrix; - params_ = params; + params_ = *params; } void DebayerCpu::process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output, - const DebayerParams ¶ms) + FrameBuffer *input, FrameBuffer *output) { bench_.startFrame(); @@ -852,8 +855,8 @@ void DebayerCpu::process(uint32_t frame, const uint32_t paramsBufferId, dmaSyncBegin(dmaSyncers, input, output); + DebayerParams *params = paramsBuffers_.at(paramsBufferId); updateLookupTables(params); - releaseIspParams.emit(paramsBufferId); /* Copy metadata from the input buffer */ diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 13253f999..5e3670b37 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -16,6 +16,7 @@ #include #include +#include #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/global_configuration.h" @@ -29,7 +30,9 @@ namespace libcamera { class DebayerCpu : public Debayer { public: - DebayerCpu(std::unique_ptr stats, const GlobalConfiguration &configuration); + DebayerCpu(std::unique_ptr stats, + const std::vector ¶msBuffers, + const GlobalConfiguration &configuration); ~DebayerCpu(); int configure(const StreamConfiguration &inputCfg, @@ -41,7 +44,7 @@ public: strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); void process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms); + FrameBuffer *input, FrameBuffer *output); SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); const SharedFD &getStatsFD() { return stats_->getStatsFD(); } @@ -112,8 +115,8 @@ private: void memcpyNextLine(const uint8_t *linePointers[]); void process2(uint32_t frame, const uint8_t *src, uint8_t *dst); void process4(uint32_t frame, const uint8_t *src, uint8_t *dst); - void updateGammaTable(const DebayerParams ¶ms); - void updateLookupTables(const DebayerParams ¶ms); + void updateGammaTable(const DebayerParams *params); + void updateLookupTables(const DebayerParams *params); /* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */ static constexpr unsigned int kMaxLineBuffers = 5; diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 947c05c07..c24590994 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -32,10 +32,13 @@ namespace libcamera { * \fn DebayerEGL::DebayerEGL(std::unique_ptr stats, const GlobalConfiguration &configuration) * \brief Construct a DebayerEGL object * \param[in] stats Statistics processing object + * \param[in] paramsBuffers SharedFDs of parameter buffers * \param[in] configuration Global configuration reference */ -DebayerEGL::DebayerEGL(std::unique_ptr stats, const GlobalConfiguration &configuration) - : Debayer(configuration), stats_(std::move(stats)) +DebayerEGL::DebayerEGL(std::unique_ptr stats, + const std::vector ¶msBuffers, + const GlobalConfiguration &configuration) + : Debayer(paramsBuffers, configuration), stats_(std::move(stats)) { } @@ -534,8 +537,7 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam } void DebayerEGL::process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output, - const DebayerParams ¶ms) + FrameBuffer *input, FrameBuffer *output) { bench_.startFrame(); @@ -549,6 +551,9 @@ void DebayerEGL::process(uint32_t frame, const uint32_t paramsBufferId, metadata.sequence = input->metadata().sequence; metadata.timestamp = input->metadata().timestamp; + DebayerParams params = *paramsBuffers_.at(paramsBufferId); + releaseIspParams.emit(paramsBufferId); + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); if (!in.isValid()) { LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; @@ -559,7 +564,6 @@ void DebayerEGL::process(uint32_t frame, const uint32_t paramsBufferId, LOG(Debayer, Error) << "debayerGPU failed"; goto error; } - releaseIspParams.emit(paramsBufferId); bench_.finishFrame(); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 7f29f53e6..435ff7d31 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -38,7 +38,9 @@ namespace libcamera { class DebayerEGL : public Debayer { public: - DebayerEGL(std::unique_ptr stats, const GlobalConfiguration &configuration); + DebayerEGL(std::unique_ptr stats, + const std::vector ¶msBuffers, + const GlobalConfiguration &configuration); ~DebayerEGL(); int configure(const StreamConfiguration &inputCfg, @@ -51,8 +53,7 @@ public: std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); void process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output, - const DebayerParams ¶ms); + FrameBuffer *input, FrameBuffer *output); int start(); void stop(); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 2bc0d30b1..230396bee 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -102,6 +102,10 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } stats->statsReady.connect(this, &SoftwareIsp::statsReady); + std::vector fdParams; + for (auto &item : sharedParams_) + fdParams.emplace_back(item.second.fd()); + #if HAVE_DEBAYER_EGL std::optional softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" }); if (softISPMode) { @@ -113,15 +117,14 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } if (!softISPMode || softISPMode == "gpu") - debayer_ = std::make_unique(std::move(stats), configuration); + debayer_ = std::make_unique(std::move(stats), fdParams, + configuration); #endif if (!debayer_) - debayer_ = std::make_unique(std::move(stats), configuration); + debayer_ = std::make_unique(std::move(stats), fdParams, + configuration); - std::vector fdParams; - for (auto &item : sharedParams_) - fdParams.emplace_back(item.second.fd()); debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); debayer_->releaseIspParams.connect(this, &SoftwareIsp::releaseIspParams); @@ -426,9 +429,8 @@ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *outpu const uint32_t paramsBufferId = availableParams_.front(); availableParams_.pop(); ipa_->computeParams(frame, paramsBufferId); - debayerParams_ = *sharedParams_.at(paramsBufferId); debayer_->invokeMethod(&Debayer::process, - ConnectionTypeQueued, frame, paramsBufferId, input, output, debayerParams_); + ConnectionTypeQueued, frame, paramsBufferId, input, output); } void SoftwareIsp::saveIspParams(uint32_t paramsBufferId) From patchwork Mon Feb 16 20:30:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26178 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 D27BBC0DA4 for ; Mon, 16 Feb 2026 20:31:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8F1D16222E; Mon, 16 Feb 2026 21:31:02 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="bkyXKxo9"; 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 DFEB562227 for ; Mon, 16 Feb 2026 21:31:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273859; 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=PFN3IDcGN6yq5bZ0OuDqED3r20nRJ8utmW1Jg8m2ckg=; b=bkyXKxo9AlJr6XYrTI+L9BgBctoqTWA3ipRpYh0QDcAzUUBbGV/UFeMloBcRM7oSRNfgtJ DlqoVrS31Vz5OdQiGO1v8R5m/4VYIv/Y6QTOPZjVocdcWfODBpajJmzIpWlb9+G13zsmuN x40WnZOvccRXw7FTCKxh3u+T/4ON7JA= 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-685-fFOEjKlhP7-nsoTJYJCcnQ-1; Mon, 16 Feb 2026 15:30:58 -0500 X-MC-Unique: fFOEjKlhP7-nsoTJYJCcnQ-1 X-Mimecast-MFC-AGG-ID: fFOEjKlhP7-nsoTJYJCcnQ_1771273857 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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 918E6180025B for ; Mon, 16 Feb 2026 20:30:57 +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 536621800464; Mon, 16 Feb 2026 20:30:56 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 09/14] libcamera: software_isp: Remove per-frame params buffers TODO item Date: Mon, 16 Feb 2026 21:30:28 +0100 Message-ID: <20260216203034.27558-10-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: tyNH844-W1HQVNmD66r-VXMGCQv9nRUTphnvnKFM9wc_1771273857 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" Parameters are stored in per-frame buffers and shared properly now. Signed-off-by: Milan Zamazal --- src/libcamera/software_isp/TODO | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO index f19e15ae2..1a71ab8a5 100644 --- a/src/libcamera/software_isp/TODO +++ b/src/libcamera/software_isp/TODO @@ -53,24 +53,6 @@ stats in hardware, such as the i.MX7), but please keep it on your radar. --- -5. Store ISP parameters in per-frame buffers - -> /** -> * \fn void Debayer::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) -> * \brief Process the bayer data into the requested format. -> * \param[in] input The input buffer. -> * \param[in] output The output buffer. -> * \param[in] params The parameters to be used in debayering. -> * -> * \note DebayerParams is passed by value deliberately so that a copy is passed -> * when this is run in another thread by invokeMethod(). -> */ - -Possibly something to address later, by storing ISP parameters in -per-frame buffers like we do for hardware ISPs. - ---- - 8. DebayerCpu cleanups > >> class DebayerCpu : public Debayer, public Object From patchwork Mon Feb 16 20:30:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26179 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 92F81C0DA4 for ; Mon, 16 Feb 2026 20:31:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 51BAC62232; 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="OwInZ/Yl"; 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 9C1866221D for ; Mon, 16 Feb 2026 21:31:03 +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=4qAvsc1pwWcThY/Mhwrt2f8MKgpjp3McXlfI2EtssZg=; b=OwInZ/YlhwJunhAbTUj+VI9xoyfX5GOOX7Sx2IuCgJv48UD9BEN1FFdlFAKlUlStFvZt45 kVSEZhgy0TB3I8jz3Se7YGH98DAaAdF6VPmbHy5lpdyqrf5zf/QOGXXFADbX8yLRt0fnMy /Mq12QyIVQUv2pt3TM7NrMv2tZrbx0A= 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-43-9cqGMfTLNz-HNVpG6Xugpg-1; Mon, 16 Feb 2026 15:31:00 -0500 X-MC-Unique: 9cqGMfTLNz-HNVpG6Xugpg-1 X-Mimecast-MFC-AGG-ID: 9cqGMfTLNz-HNVpG6Xugpg_1771273859 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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6B6AB180034D for ; Mon, 16 Feb 2026 20:30:59 +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 2D0001800464; Mon, 16 Feb 2026 20:30:57 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 10/14] libcamera: software_isp: Introduce arguments for statistics buffers Date: Mon, 16 Feb 2026 21:30:29 +0100 Message-ID: <20260216203034.27558-11-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: i30xJTl0WEBYHwLIIswZVPprBOKjXVHVVxrM0A5ZgfM_1771273859 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" Statistics in software ISP is held in two fixed buffers, copying the statistics from the working one to the shared one in SwIspStats::finishFrame. This patch introduces support for a ring of statistics buffers that are never copied, similarly to parameters buffers and to how hardware pipelines operate. This is to address software ISP TODO #2. The patch adds a new argument statsBufferId for the future parameters buffer ids passed to the calls. The buffer ids must be passed to the following groups of methods: - SwStatsCpu::startFrame, to reset the statistics. - Debayer::process, to signal what statistics buffer is started and stopped being used to gather the statistics. - SoftwareIsp::statsProcessed, a new signal to indicate that the given statistics buffer contents is no longer needed. The type of the buffer id statistics is set to uint32_t because: - It can be used in mojom. - The same type is used for parameters buffers. - It is consistent with the similar types in the hardware pipelines. - It covers file descriptor number range, which will be used as buffer ids. Already provided statistics buffer arguments are renamed from bufferId to statsBufferId for consistency and to avoid confusion between statistics and parameters buffer id arguments. This patch doesn't do more than adding the arguments, to keep the patch simple. The buffer handling will be implemented in the followup patches. Statistics and parameters buffers use is coupled to much extent. It can be tempting to perhaps use the same buffer ids and perhaps some common signals. But it's better to keep them separate to avoid contingent future refactoring in case this coupling becomes less tight in future. Signed-off-by: Milan Zamazal --- .../internal/software_isp/software_isp.h | 3 ++- .../internal/software_isp/swstats_cpu.h | 4 ++-- include/libcamera/ipa/soft.mojom | 3 ++- src/ipa/simple/soft_simple.cpp | 3 ++- src/libcamera/pipeline/simple/simple.cpp | 7 ++++--- src/libcamera/software_isp/debayer.cpp | 3 ++- src/libcamera/software_isp/debayer.h | 1 + src/libcamera/software_isp/debayer_cpu.cpp | 16 +++++++-------- src/libcamera/software_isp/debayer_cpu.h | 4 +++- src/libcamera/software_isp/debayer_egl.cpp | 7 +++++-- src/libcamera/software_isp/debayer_egl.h | 7 +++++-- src/libcamera/software_isp/software_isp.cpp | 13 +++++++++--- src/libcamera/software_isp/swstats_cpu.cpp | 20 ++++++++++--------- 13 files changed, 56 insertions(+), 35 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 65348e213..519dfc71a 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -93,7 +93,8 @@ private: void saveIspParams(uint32_t paramsBufferId); void releaseIspParams(uint32_t paramsBufferId); void setSensorCtrls(const ControlList &sensorControls); - void statsReady(uint32_t frame, uint32_t bufferId); + void statsReady(uint32_t frame, const uint32_t statsBufferId); + void statsProcessed(const uint32_t statsBufferId); void inputReady(FrameBuffer *input); void outputReady(FrameBuffer *output); std::unique_ptr debayer_; diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 64b3e23f5..ae8ce1e59 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -53,8 +53,8 @@ public: int configure(const StreamConfiguration &inputCfg); void setWindow(const Rectangle &window); - void startFrame(uint32_t frame); - void finishFrame(uint32_t frame, uint32_t bufferId); + void startFrame(uint32_t frame, const uint32_t statsBufferId); + void finishFrame(uint32_t frame, const uint32_t statsBufferId); void processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input); void processLine0(uint32_t frame, unsigned int y, const uint8_t *src[]) diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index 4738a1b46..5ebe2864c 100644 --- a/include/libcamera/ipa/soft.mojom +++ b/include/libcamera/ipa/soft.mojom @@ -27,12 +27,13 @@ interface IPASoftInterface { [async] queueRequest(uint32 frame, libcamera.ControlList sensorControls); [async] computeParams(uint32 frame, uint32 paramsBufferId); [async] processStats(uint32 frame, - uint32 bufferId, + uint32 statsBufferId, libcamera.ControlList sensorControls); }; interface IPASoftEventInterface { setSensorControls(libcamera.ControlList sensorControls); + statsProcessed(uint32 statsBufferId); setIspParams(uint32 paramsBufferId); metadataReady(uint32 frame, libcamera.ControlList metadata); }; diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index f212fabe3..4a681babe 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -300,7 +300,7 @@ void IPASoftSimple::computeParams(const uint32_t frame, } void IPASoftSimple::processStats(const uint32_t frame, - [[maybe_unused]] const uint32_t bufferId, + const uint32_t statsBufferId, const ControlList &sensorControls) { IPAFrameContext &frameContext = context_.frameContexts.get(frame); @@ -314,6 +314,7 @@ void IPASoftSimple::processStats(const uint32_t frame, for (auto const &algo : algorithms()) algo->process(context_, frame, frameContext, stats_, metadata); metadataReady.emit(frame, metadata); + statsProcessed.emit(statsBufferId); /* Sanity check */ if (!sensorControls.contains(V4L2_CID_EXPOSURE) || diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index dc9176c29..9e2c2a493 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -369,7 +369,7 @@ private: void conversionInputDone(FrameBuffer *buffer); void conversionOutputDone(FrameBuffer *buffer); - void ispStatsReady(uint32_t frame, uint32_t bufferId); + void ispStatsReady(uint32_t frame, const uint32_t statsBufferId); void metadataReady(uint32_t frame, const ControlList &metadata); void setSensorControls(const ControlList &sensorControls); }; @@ -1025,9 +1025,10 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer) tryCompleteRequest(request); } -void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId) +void SimpleCameraData::ispStatsReady(uint32_t frame, + const uint32_t statsBufferId) { - swIsp_->processStats(frame, bufferId, + swIsp_->processStats(frame, statsBufferId, delayedCtrls_->get(frame)); } diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index ad47c1e8d..f3f241e14 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -122,9 +122,10 @@ Debayer::~Debayer() */ /** - * \fn void Debayer::process(uint32_t frame, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output) + * \fn void Debayer::process(uint32_t frame, const uint32_t statsBufferId, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output) * \brief Process the bayer data into the requested format * \param[in] frame The frame number + * \param[in] statsBufferId The id of the stats buffer to use * \param[in] paramsBufferId The id of the params buffer in use * \param[in] input The input buffer * \param[in] output The output buffer diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index a66d0cbbe..9f08a7f4e 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -49,6 +49,7 @@ public: strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0; virtual void process(uint32_t frame, + const uint32_t statsBufferId, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output) = 0; virtual int start() { return 0; } diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 927ac7d10..6f2d70617 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -846,8 +846,11 @@ void DebayerCpu::updateLookupTables(const DebayerParams *params) params_ = *params; } -void DebayerCpu::process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output) +void DebayerCpu::process(uint32_t frame, + const uint32_t statsBufferId, + const uint32_t paramsBufferId, + FrameBuffer *input, + FrameBuffer *output) { bench_.startFrame(); @@ -873,7 +876,7 @@ void DebayerCpu::process(uint32_t frame, const uint32_t paramsBufferId, return; } - stats_->startFrame(frame); + stats_->startFrame(frame, statsBufferId); if (inputConfig_.patternSize.height == 2) process2(frame, in.planes()[0].data(), out.planes()[0].data()); @@ -887,12 +890,7 @@ void DebayerCpu::process(uint32_t frame, const uint32_t paramsBufferId, /* Measure before emitting signals */ bench_.finishFrame(); - /* - * Buffer ids are currently not used, so pass zeros as its parameter. - * - * \todo Pass real bufferId once stats buffer passing is changed. - */ - stats_->finishFrame(frame, 0); + stats_->finishFrame(frame, statsBufferId); outputBufferReady.emit(output); inputBufferReady.emit(input); } diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 5e3670b37..8d38fa43f 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -43,8 +43,10 @@ public: std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); void process(uint32_t frame, + const uint32_t statsBufferId, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output); + FrameBuffer *input, + FrameBuffer *output); SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); const SharedFD &getStatsFD() { return stats_->getStatsFD(); } diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index c24590994..5715b80ae 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -536,8 +536,11 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam return 0; } -void DebayerEGL::process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output) +void DebayerEGL::process(uint32_t frame, + [[maybe_unused]] const uint32_t statsBufferId, + const uint32_t paramsBufferId, + FrameBuffer *input, + FrameBuffer *output) { bench_.startFrame(); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 435ff7d31..3504c0d4f 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -52,8 +52,11 @@ public: std::vector formats(PixelFormat input); std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); - void process(uint32_t frame, const uint32_t paramsBufferId, - FrameBuffer *input, FrameBuffer *output); + void process(uint32_t frame, + const uint32_t statsBufferId, + const uint32_t paramsBufferId, + FrameBuffer *input, + FrameBuffer *output); int start(); void stop(); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 230396bee..04aaf7a8c 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -164,6 +164,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, return; } + ipa_->statsProcessed.connect(this, &SoftwareIsp::statsProcessed); ipa_->setIspParams.connect(this, &SoftwareIsp::saveIspParams); ipa_->metadataReady.connect(this, [this](uint32_t frame, const ControlList &metadata) { @@ -429,8 +430,10 @@ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *outpu const uint32_t paramsBufferId = availableParams_.front(); availableParams_.pop(); ipa_->computeParams(frame, paramsBufferId); + const uint32_t statsBufferId = 0; debayer_->invokeMethod(&Debayer::process, - ConnectionTypeQueued, frame, paramsBufferId, input, output); + ConnectionTypeQueued, frame, + statsBufferId, paramsBufferId, input, output); } void SoftwareIsp::saveIspParams(uint32_t paramsBufferId) @@ -448,9 +451,13 @@ void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls) setSensorControls.emit(sensorControls); } -void SoftwareIsp::statsReady(uint32_t frame, uint32_t bufferId) +void SoftwareIsp::statsReady(uint32_t frame, const uint32_t statsBufferId) +{ + ispStatsReady.emit(frame, statsBufferId); +} + +void SoftwareIsp::statsProcessed([[maybe_unused]] const uint32_t statsBufferId) { - ispStatsReady.emit(frame, bufferId); } void SoftwareIsp::inputReady(FrameBuffer *input) diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 5c3011a7f..a3b11c443 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -321,10 +321,11 @@ void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[]) /** * \brief Reset state to start statistics gathering for a new frame * \param[in] frame The frame number + * \param[in] statsBufferId ID of the statistics buffer * * This may only be called after a successful setWindow() call. */ -void SwStatsCpu::startFrame(uint32_t frame) +void SwStatsCpu::startFrame(uint32_t frame, [[maybe_unused]] const uint32_t statsBufferId) { if (frame % kStatPerNumFrames) return; @@ -339,15 +340,16 @@ void SwStatsCpu::startFrame(uint32_t frame) /** * \brief Finish statistics calculation for the current frame * \param[in] frame The frame number - * \param[in] bufferId ID of the statistics buffer + * \param[in] statsBufferId ID of the statistics buffer * * This may only be called after a successful setWindow() call. */ -void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId) +void SwStatsCpu::finishFrame(uint32_t frame, + const uint32_t statsBufferId) { stats_.valid = frame % kStatPerNumFrames == 0; *sharedStats_ = stats_; - statsReady.emit(frame, bufferId); + statsReady.emit(frame, statsBufferId); } /** @@ -512,20 +514,20 @@ void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in) /** * \brief Calculate statistics for a frame in one go * \param[in] frame The frame number - * \param[in] bufferId ID of the statistics buffer + * \param[in] statsBufferId ID of the statistics buffer * \param[in] input The frame to process * * This may only be called after a successful setWindow() call. */ -void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input) +void SwStatsCpu::processFrame(uint32_t frame, uint32_t statsBufferId, FrameBuffer *input) { if (frame % kStatPerNumFrames) { - finishFrame(frame, bufferId); + finishFrame(frame, statsBufferId); return; } bench_.startFrame(); - startFrame(frame); + startFrame(frame, statsBufferId); MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); if (!in.isValid()) { @@ -534,7 +536,7 @@ void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *in } (this->*processFrame_)(in); - finishFrame(frame, bufferId); + finishFrame(frame, statsBufferId); bench_.finishFrame(); } 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); } From patchwork Mon Feb 16 20:30:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26181 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 5F3AFC0DA4 for ; Mon, 16 Feb 2026 20:31:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F17596223C; Mon, 16 Feb 2026 21:31:07 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="KHqiBGA4"; 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 D04596222B for ; Mon, 16 Feb 2026 21:31:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273864; 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=668hMHR70XZOb9RF+lQOpoi1B8/acRs0FdbnirSL43I=; b=KHqiBGA40cv4dbZq7jzlkMS4hJm3U4Lpt/fD4/Z3T3R/jHi65GE9Uo3K5Wyr1VNKJXGCTD O0Ns0uCTt+5aDpb7tsMn23ST0WOR2ZQSfYi/FF0I75W89eyoF+C9YvTqkEloftqNHWL5Co Z0wq1dVBdYV+bm+ZW4BTszzVt69f5mg= Received: from mx-prod-mc-03.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-34-TNwyuSzvNSWAmEqAhBoWOw-1; Mon, 16 Feb 2026 15:31:03 -0500 X-MC-Unique: TNwyuSzvNSWAmEqAhBoWOw-1 X-Mimecast-MFC-AGG-ID: TNwyuSzvNSWAmEqAhBoWOw_1771273862 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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7C2A219560B7 for ; Mon, 16 Feb 2026 20:31:02 +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 57E6218004AD; Mon, 16 Feb 2026 20:31:01 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 12/14] libcamera: software_isp: Track statistics buffers Date: Mon, 16 Feb 2026 21:30:31 +0100 Message-ID: <20260216203034.27558-13-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: Z7FoDZ5LN0AO1WnbpyzODBKWhimcgBeyDHHU7AAOk00_1771273862 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" As a preparation for passing the shared statistics buffers to IPA, this patch introduces tracking statistics buffer ids. SofwareIsp::availableStats_ is a queue of ids of the buffers available for use. When a fresh statistics buffer is needed, its id is retrieved from there and once the buffer is no longer needed, it's put back there, in a method invoked by a signal. This is similar to what the hardware pipelines do. We use buffers' file descriptors as buffer ids. The statistics buffers will be shared with the IPA, SwIspStats and debayering and we need their common identification everywhere. The buffer file descriptors are shared unchanged so they can be used for the purpose, avoiding a need to pass a special mapping to the IPA and debayering on initialization. Note that the statistics buffer id is still actually unused, this will be changed once the buffers are shared with the IPA. Signed-off-by: Milan Zamazal --- .../libcamera/internal/software_isp/software_isp.h | 1 + src/libcamera/software_isp/debayer_egl.cpp | 4 ++-- src/libcamera/software_isp/software_isp.cpp | 13 +++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 1f3eb75f6..45128f25f 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -104,6 +104,7 @@ private: DebayerParams debayerParams_; std::queue availableParams_; bool allocateParamsBuffers(const unsigned int bufferCount); + std::queue availableStats_; std::unique_ptr allocateStatsBuffers( const GlobalConfiguration &configuration, std::vector &fdStats, diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 5715b80ae..66e1fcac2 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -537,7 +537,7 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam } void DebayerEGL::process(uint32_t frame, - [[maybe_unused]] const uint32_t statsBufferId, + const uint32_t statsBufferId, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output) @@ -573,7 +573,7 @@ void DebayerEGL::process(uint32_t frame, metadata.planes()[0].bytesused = output->planes()[0].length; /* Calculate stats for the whole frame */ - stats_->processFrame(frame, 0, input); + stats_->processFrame(frame, statsBufferId, input); dmaSyncers.clear(); outputBufferReady.emit(output); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index a1a9ddbf4..f3ee5773b 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -222,6 +222,7 @@ std::unique_ptr SoftwareIsp::allocateStatsBuffers( unsigned int bufferId = shared.fd().get(); fdStats.emplace_back(shared.fd()); sharedStats->emplace(bufferId, std::move(shared)); + availableStats_.push(bufferId); } auto stats = std::make_unique(configuration, std::move(sharedStats)); @@ -457,11 +458,18 @@ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *outpu while (availableParams_.empty()) ; } + if (availableStats_.empty()) { + LOG(SoftwareIsp, Error) << "Statistics buffer underrun"; + /* Well, busy loop, but this situation shouldn't normally happen. */ + while (availableStats_.empty()) + ; + } const uint32_t paramsBufferId = availableParams_.front(); availableParams_.pop(); + const uint32_t statsBufferId = availableStats_.front(); + availableStats_.pop(); ipa_->computeParams(frame, paramsBufferId); - const uint32_t statsBufferId = 0; debayer_->invokeMethod(&Debayer::process, ConnectionTypeQueued, frame, statsBufferId, paramsBufferId, input, output); @@ -487,8 +495,9 @@ void SoftwareIsp::statsReady(uint32_t frame, const uint32_t statsBufferId) ispStatsReady.emit(frame, statsBufferId); } -void SoftwareIsp::statsProcessed([[maybe_unused]] const uint32_t statsBufferId) +void SoftwareIsp::statsProcessed(const uint32_t statsBufferId) { + availableStats_.push(statsBufferId); } void SoftwareIsp::inputReady(FrameBuffer *input) From patchwork Mon Feb 16 20:30:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26182 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 1510FC0DA4 for ; Mon, 16 Feb 2026 20:31:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C6FE462237; Mon, 16 Feb 2026 21:31:09 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="WqYKzWbp"; 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 9313E6220C for ; Mon, 16 Feb 2026 21:31:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273866; 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=6GpWSVOCYfk2sKMuYL9BWe2Bb/IVbC1yntBaT9i9skE=; b=WqYKzWbpWZLbNew0QYDpSJma5RpCKMQCELWi4Q6EFchMBXlQL8OvUXWbdCEuRY2gsv/rLt SitZfhu3lmMuAQ2ozwRXbGA43Y+53yD1nUEcqyAXUL1wkgmiKPhtuPNdJ/7VH32hCeMGRK 2kBNS79AUufLSFunF0dCNXbzC6tPwa4= 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-650-uzbJVJ2oMmuPK684sTuFxA-1; Mon, 16 Feb 2026 15:31:04 -0500 X-MC-Unique: uzbJVJ2oMmuPK684sTuFxA-1 X-Mimecast-MFC-AGG-ID: uzbJVJ2oMmuPK684sTuFxA_1771273864 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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 289F31800370 for ; Mon, 16 Feb 2026 20:31:04 +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 208A91800464; Mon, 16 Feb 2026 20:31:02 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 13/14] libcamera: software_isp: Share statistics buffers with IPA Date: Mon, 16 Feb 2026 21:30:32 +0100 Message-ID: <20260216203034.27558-14-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: keXBiYsICvHqsTSqpy-E0hFRyOf02nWjMaYjIy7PiU8_1771273864 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. In order to track the current statistics buffer in SwStatsCpu instead, we change SwStatsCpu::stats_ to a wrapper structure. This is because we need a reference to a shared mem object but a class attribute cannot be a dynamically assigned reference. This hack works around the problem. 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 | 12 +++--- include/libcamera/ipa/soft.mojom | 2 +- src/ipa/simple/soft_simple.cpp | 43 ++++++++++--------- 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 | 1 - src/libcamera/software_isp/software_isp.cpp | 2 +- src/libcamera/software_isp/swstats_cpu.cpp | 35 +++++---------- 9 files changed, 42 insertions(+), 66 deletions(-) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 050b13ec1..2592da94a 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 @@ -46,10 +47,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); @@ -118,7 +115,12 @@ private: unsigned int stride_; std::unique_ptr>> sharedStats_; - SwIspStats stats_; + struct SwIspStatsRef { + SharedMemObject &stats; + SwIspStatsRef(SharedMemObject &_stats) + : stats(_stats) {}; + }; + std::unique_ptr stats_; Benchmark bench_; }; diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index 5ebe2864c..129f2f6b4 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, + array fdStats, array fdParams, libcamera.IPACameraSensorInfo sensorInfo, libcamera.ControlInfoMap sensorControls) diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index 4a681babe..b36894d5d 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::vector &fdStats, const std::vector &fdParams, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, @@ -77,7 +77,7 @@ private: void updateExposure(double exposureMSV); std::map paramsBuffers_; - SwIspStats *stats_; + std::map statsBuffers_; std::unique_ptr camHelper_; ControlInfoMap sensorInfoMap_; @@ -87,14 +87,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::vector &fdStats, const std::vector &fdParams, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, @@ -138,11 +138,21 @@ int IPASoftSimple::init(const IPASettings &settings, return ret; *ccmEnabled = context_.ccmEnabled; - stats_ = nullptr; + for (auto &sharedFd : fdStats) { + if (!sharedFd.isValid()) { + LOG(IPASoft, Error) << "Invalid Statistics handle"; + return -ENODEV; + } - if (!fdStats.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; + } + + ASSERT(sharedFd.get() >= 0); + statsBuffers_[sharedFd.get()] = static_cast(mem); } for (auto &sharedFd : fdParams) { @@ -168,17 +178,6 @@ int IPASoftSimple::init(const IPASettings &settings, paramsBuffers_[sharedFd.get()] = 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); @@ -305,6 +304,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(); @@ -312,7 +313,7 @@ void IPASoftSimple::processStats(const uint32_t frame, ControlList metadata(controls::controls); for (auto const &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 f3f241e14..3a9049d0b 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -143,16 +143,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 9f08a7f4e..e640c95a0 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 8d38fa43f..7f4428bc0 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -48,7 +48,6 @@ public: FrameBuffer *input, FrameBuffer *output); SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); - const SharedFD &getStatsFD() { return stats_->getStatsFD(); } private: /** diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 3504c0d4f..344c4a4d2 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -60,7 +60,6 @@ public: int start(); void stop(); - const SharedFD &getStatsFD() { return stats_->getStatsFD(); } unsigned int frameSize(); SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index f3ee5773b..047d0fb22 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -154,7 +154,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } 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 b9f36b383..22164e33d 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 @@ -183,12 +169,12 @@ static constexpr unsigned int kBlueYMul = 29; /* 0.114 * 256 */ yVal = r * kRedYMul; \ yVal += g * kGreenYMul; \ yVal += b * kBlueYMul; \ - stats_.yHistogram[yVal * SwIspStats::kYHistogramSize / (256 * 256 * (div))]++; + stats_->stats->yHistogram[yVal * SwIspStats::kYHistogramSize / (256 * 256 * (div))]++; -#define SWSTATS_FINISH_LINE_STATS() \ - stats_.sum_.r() += sumR; \ - stats_.sum_.g() += sumG; \ - stats_.sum_.b() += sumB; +#define SWSTATS_FINISH_LINE_STATS() \ + stats_->stats->sum_.r() += sumR; \ + stats_->stats->sum_.g() += sumG; \ + stats_->stats->sum_.b() += sumB; void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[]) { @@ -326,7 +312,7 @@ void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[]) * * This may only be called after a successful setWindow() call. */ -void SwStatsCpu::startFrame(uint32_t frame, [[maybe_unused]] const uint32_t statsBufferId) +void SwStatsCpu::startFrame(uint32_t frame, const uint32_t statsBufferId) { if (frame % kStatPerNumFrames) return; @@ -334,8 +320,10 @@ void SwStatsCpu::startFrame(uint32_t frame, [[maybe_unused]] const uint32_t stat if (window_.width == 0) LOG(SwStatsCpu, Error) << "Calling startFrame() without setWindow()"; - stats_.sum_ = RGB({ 0, 0, 0 }); - stats_.yHistogram.fill(0); + auto &s = sharedStats_->at(statsBufferId); + stats_ = std::make_unique(s); + stats_->stats->sum_ = RGB({ 0, 0, 0 }); + stats_->stats->yHistogram.fill(0); } /** @@ -348,8 +336,7 @@ void SwStatsCpu::startFrame(uint32_t frame, [[maybe_unused]] const uint32_t stat void SwStatsCpu::finishFrame(uint32_t frame, const uint32_t statsBufferId) { - stats_.valid = frame % kStatPerNumFrames == 0; - *(sharedStats_->at(statsBufferId)) = stats_; + stats_->stats->valid = frame % kStatPerNumFrames == 0; statsReady.emit(frame, statsBufferId); } From patchwork Mon Feb 16 20:30:33 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26183 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 9CAFDC0DA4 for ; Mon, 16 Feb 2026 20:31:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5CF6A6222A; Mon, 16 Feb 2026 21:31:12 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Jt6bkcpM"; 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 1216062084 for ; Mon, 16 Feb 2026 21:31:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1771273868; 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=4Of8XG1Fc76HUveb3P8ENgdIRuS25Mfk2sApS377kEo=; b=Jt6bkcpMMOLP4WMJHsl6grVhvy70duiDkLXwI1bNogZ24nRc/8KyZjssocNWtDnsp4NaXk NC6N8HSJSz1/xF8u7Usc/4v/sHxDPVkWLF3EakJdFVoMUeHeiIi68U52PRGE710QZT3UTF V78r8+RuVG9QOzOft7FvW+tVjeKIVJc= 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-161-siGspf4NNgCZtXL120t78w-1; Mon, 16 Feb 2026 15:31:06 -0500 X-MC-Unique: siGspf4NNgCZtXL120t78w-1 X-Mimecast-MFC-AGG-ID: siGspf4NNgCZtXL120t78w_1771273866 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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D99381800451 for ; Mon, 16 Feb 2026 20:31:05 +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 B47051800464; Mon, 16 Feb 2026 20:31:04 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 14/14] libcamera: software_isp: Remove stats-sharing TODO item Date: Mon, 16 Feb 2026 21:30:33 +0100 Message-ID: <20260216203034.27558-15-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: 90kfrPurvqmLwBqh7s0Xs8zRIiDBkVtLgT0U3ZxaedE_1771273866 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" Shared per-frame statistics buffers are implemented, we can remove TODO #2. Signed-off-by: Milan Zamazal --- src/libcamera/software_isp/TODO | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO index 1a71ab8a5..8837641e6 100644 --- a/src/libcamera/software_isp/TODO +++ b/src/libcamera/software_isp/TODO @@ -1,30 +1,3 @@ -2. Reconsider stats sharing - ->>> +void SwStatsCpu::finishFrame(void) ->>> +{ ->>> + *sharedStats_ = stats_; ->> ->> Is it more efficient to copy the stats instead of operating directly on ->> the shared memory ? -> -> I inherited doing things this way from Andrey. I kept this because -> we don't really have any synchronization with the IPA reading this. -> -> So the idea is to only touch this when the next set of statistics -> is ready since we don't know when the IPA is done with accessing -> the previous set of statistics ... -> -> This is both something which seems mostly a theoretic problem, -> yet also definitely something which I think we need to fix. -> -> Maybe use a ringbuffer of stats buffers and pass the index into -> the ringbuffer to the emit signal ? - -That would match how we deal with hardware ISPs, and I think that's a -good idea. It will help decoupling the processing side from the IPA. - ---- - 3. Remove statsReady signal > class SwStatsCpu