From patchwork Mon Sep 14 14:02:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28283 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 C0701C3369 for ; Mon, 14 Sep 2026 14:05:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4705C68700; Mon, 14 Sep 2026 16:05:11 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="RRbGT7df"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 07673686B5 for ; Mon, 14 Sep 2026 16:05:09 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:a279:75fa:1f6c:7f40]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1328D512; Mon, 14 Sep 2026 16:03:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789394609; bh=ZPL5vGE2AHSWC7DNb8XqzqupLruS1w0usmfdgTKjoD4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RRbGT7dfByCBC9nlYT3+5g+0iRi9rzhN9e7UI0+wAAcnVG2aeq2xRZL0lOreyE1nO 9ALD2NkXMcE4Mv5Oxmpr67HxIxWjrduXHBOT33IkbJjFptCI2bRq/QIDGI+809pkSd VC+cRLYniWJSvog/Lc67goOgdbapdk6GEhIbovr4= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v3 39/41] ipa: rkisp1: Handle frame jumps in calls to computeParams() Date: Mon, 14 Sep 2026 16:02:52 +0200 Message-ID: <20260914140309.3354666-40-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" In the situation of a parameter buffer underrun (due to some external event) the calls to computeParams will jump frames. It must be guaranteed that every change in the jumped frames still gets applied to the isp. To do that, call computeParams() on every missed frame or issue a full reinitialization if more than 3 frames were lost. The number of 3 is arbitrarily chosen but fits to the subjective observation that we either lose 1-2 frames due to signal issues or way more than 3 because something else blocked the system. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/rkisp1.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index ca3b0d31d9f6..7147de4a0f02 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -86,6 +86,7 @@ private: /* Local parameter storage */ struct IPAContext context_; bool initializeParams_; + uint32_t lastParamsComputed_; }; namespace { @@ -220,6 +221,7 @@ void IPARkISP1::start(const ControlList &controls, const uint32_t paramBufferId, IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(0, controls); ASSERT(frameContext); initializeParams_ = true; + lastParamsComputed_ = 0; if (paramBufferId != 0) result->paramBufferBytesUsed = computeParamsInternal(*frameContext, @@ -332,10 +334,37 @@ uint32_t IPARkISP1::computeParamsInternal(IPAFrameContext &frameContext, const u mappedBuffers_.at(bufferId).planes()[0]); unsigned int frame = frameContext.frame(); + + /* + * In the corner case that the previous params buffer was not computed + * (due to resynchronization), there is a risk that a change was missed + * and not sent to the kernel. This can have quite negative side + * effects, if e.g. a lsc table was not written. To mitigate that, run + * over all missed frames and apply them in turn or do a full reinit if + * too many frames were missed. + */ + while (!initializeParams_ && lastParamsComputed_ + 1 < frame) { + lastParamsComputed_++; + IPAFrameContext *fc = context_.frameContexts.getOrInitContext(lastParamsComputed_); + if (!fc || frame - lastParamsComputed_ > 3) { + LOG(IPARkISP1, Warning) + << "Collect missed params with full reinit"; + initializeParams_ = true; + break; + } + + LOG(IPARkISP1, Warning) << "Collect missed params for frame: " + << lastParamsComputed_; + for (const auto &algo : algorithms()) + algo->prepare(context_, lastParamsComputed_, *fc, + ¶ms, false); + } + for (const auto &algo : algorithms()) algo->prepare(context_, frame, frameContext, ¶ms, initializeParams_); + lastParamsComputed_ = std::max(frame, lastParamsComputed_); initializeParams_ = false; return params.bytesused(); @@ -376,6 +405,11 @@ void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId, return; } + if (frame > lastParamsComputed_) { + LOG(IPARkISP1, Debug) << "Process stats on frame " << frame + << " without prior compute params"; + } + /* * In raw capture mode, the ISP is bypassed and no statistics buffer is * provided.