From patchwork Mon Sep 14 14:02:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28258 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 3A70EC3356 for ; Mon, 14 Sep 2026 14:04:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ABC7D686CF; Mon, 14 Sep 2026 16:04:06 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="J3UqkKfD"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4174C686C9 for ; Mon, 14 Sep 2026 16:04:05 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:a279:75fa:1f6c:7f40]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4C055929; Mon, 14 Sep 2026 16:02:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789394545; bh=dn4PZNmJZpW7ZylyG9DrVpbfcC/F4Y2fSphY/XstT7E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J3UqkKfDMO1QIwj3xSjq8S604KZlEJrVZprPyLthx6uZ36Olp4jHpdNxdKZ612YP1 rUA41KSTOcOGbKBNPe6mSntRvRxICNlu9Hy5IthGzL3CFEjPZaHZCxM0ofaoY0ywK+ 8p17qVNYGT/hgQ7fbEHsw+lA5LnD93tmcMkhuecE= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v3 14/41] ipa: rkisp1: Move setSensorControls signal to computeParams Date: Mon, 14 Sep 2026 16:02:27 +0200 Message-ID: <20260914140309.3354666-15-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260914140309.3354666-1-stefan.klug@ideasonboard.com> References: <20260914140309.3354666-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 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 setSensorControls event is emitted in the processStats() function. On first sight this looks reasonable as in processStats() we got the latest statistics and can therefore calculate the most up to date sensor controls. In the light of per-frame-controls however it produces difficult to solve timing issues: - The frame context in processStats() is the frame context of the frame that produced the stats, not for the frame that should be prepared and sent to the sensor. - To synchronize digital gain applied in the ISP with the analog gain applied in the sensor the set of parameters prepared for sensor and ISP must also be synchronized, which is currently not the case. To fix that, move the calculation and setting of sensor controls into the computeParams(). This way the model is far more easy to understand. We lose a tiny option for optimizations in that (in theory) we could delay the calculation of ISP parameters by another frame (assuming the sensor has a typical 2-frame delay). But all discussions and tests showed that keeping all parameters in sync is more important than that possible optimization for one frame. To ensure setSensorControls() still gets emitted in raw mode, allow computeParams() to be called with a zero bufferId. This strategy is also used for processStats() to ensure that metadata gets filled in raw mode. Then call computeParams() for raw mode also. Signed-off-by: Stefan Klug --- Changes in v3: - Squashed the fix for raw mode into this patch as it is a logical unit Changes in v2: - Collected tag --- src/ipa/rkisp1/rkisp1.cpp | 22 ++++++++++------------ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 6 ++++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index eff1f40d605b..98fc3244d9a6 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -302,13 +302,18 @@ void IPARkISP1::computeParams(const uint32_t frame, const uint32_t bufferId) { IPAFrameContext &frameContext = context_.frameContexts.get(frame); - RkISP1Params params(context_.configuration.paramFormat, - mappedBuffers_.at(bufferId).planes()[0]); + if (bufferId != 0) { + RkISP1Params params(context_.configuration.paramFormat, + mappedBuffers_.at(bufferId).planes()[0]); - for (const auto &algo : algorithms()) - algo->prepare(context_, frame, frameContext, ¶ms); + for (const auto &algo : algorithms()) + algo->prepare(context_, frame, frameContext, ¶ms); - paramsComputed.emit(frame, params.bytesused()); + paramsComputed.emit(frame, params.bytesused()); + } + + ControlList ctrls = getSensorControls(frameContext); + setSensorControls.emit(frame, ctrls); } void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId, @@ -337,13 +342,6 @@ void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId, algo->process(context_, frame, frameContext, stats, metadata); } - /* - * \todo: Here we should do a lookahead that takes the sensor delays - * into account. - */ - ControlList ctrls = getSensorControls(frameContext); - setSensorControls.emit(frame, ctrls); - context_.debugMetadata.moveEntries(metadata); metadataReady.emit(frame, metadata); } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index ffd49157ec67..d3940692c11b 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -1352,6 +1352,12 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) if (data->selfPath_ && info->selfPathBuffer) data->selfPath_->queueBuffer(info->selfPathBuffer); + + /* + * Call computeParams with an empty param buffer to trigger the + * setSensorControls signal. + */ + data->ipa_->computeParams(data->frame_, 0); } else { data->ipa_->computeParams(data->frame_, info->paramBuffer->cookie());