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);