From patchwork Wed Aug 26 08:23:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?UsOzYmVydCBCb8W+aWs=?= X-Patchwork-Id: 28102 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 28473C333D for ; Wed, 26 Aug 2026 08:33:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 042D368446; Wed, 26 Aug 2026 10:33:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="m03I33LF"; dkim-atps=neutral Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E77068421 for ; Wed, 26 Aug 2026 10:23:40 +0200 (CEST) Received: by mail-ed1-x52f.google.com with SMTP id 4fb4d7f45d1cf-6a18e24ad25so884382a12.1 for ; Wed, 26 Aug 2026 01:23:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787732620; x=1788337420; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=WQwB7xsAKMXncRqqK9sNh6HsEyacyJk53ZfjeTdxXgo=; b=m03I33LFiLjSTXNZCOJB0lKyuZtdbvA6UnbzVY7XDpmx9EWBz+1jGcFD115qpi7JO2 4ZYyEkiFFYjgdxOiEbX39CL39jiZR05K5pfqCUzY+iqOLslaHXmvMQbTpTIne+IUYNBs YYF/jfGjEbTj21A7kWF8qkXs20lv0mGqsXHY+PLOAniHd5zn1s8rpBbT4j2Wa4q0JQQG m3hJTd3UBzrIgMqOOvI78DsX62Z/AbMPh4UQZiMywpbqa2ZLfzbOUklw6bDclEOOnG5p Xt2zUYMKHO1YUidoe7KbkFfXldFZtj/tYM/ChYFVjrnVZlfArI+Uq4lpZTJhUq7GWnVK 442Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787732620; x=1788337420; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=WQwB7xsAKMXncRqqK9sNh6HsEyacyJk53ZfjeTdxXgo=; b=ZeTN4yzyZgk19YFJqX+7RfjSVuDKlzItpxbmf4K3HLP9nQizNZLkFCoKrbByAya3QA xpQ39pxoLsXNPyHmR0J3Pl/jkOGNul1epAZKQPZlohA5ON1l3cfb9V+riPBia01Wgf7s dW5/+CgQ+JGWQcBgURl6yOwMl5BzkbII61AeUmVE+XWbj5wy+8rk1CbSrXMUGAqTXnwq KdDwE0H5uqo7R89K5SRkILFotV75QgfiyoPPS2G+dKJgwpiCL8sJt4L4+AINfmwJJJ0s tunW4C/89hdbgRYTyWhg5FKQKRdNh5ldM2giS+1wwaxOKbXDHL73BYPcpJSALA5om/Cn cnnA== X-Gm-Message-State: AFuF++l+W6PNJlZfmngJxrFeDicDXhRjIuo9eaFZD2MF32mQz9drpMVQ XfqzgXBFrXo7bnayhqkztz6wlxq9vHLY+2rb5zzQOAkfjNmswFj35id8gkS67ym/8FU= X-Gm-Gg: AR+sD13wJZo3iLe4RWs4B/DCjmVMs5tjhWngkMdB3DYbskvpnjkabbSuNnOD8ArpUO0 FdBl9Ct3jIjV8PoOuAoSQJMldbkcbjzPPtxVQb+yH7xXtm81d3V2idDqd/ZZr4Nms7b8Fu3e1jz PZmk4amaFjMVfjhZ4ll0TzIVfa8I54VM/e55nL/thWGc3D0FbEwHwGjUanWGHqlcetO2j9063C2 SWpW8C6PciYmkPwa45SHeTNDTY9IladE4THlkfhlKrey6XeOLUJTiior8+i14JXpd4m7wg2KbT8 FVjjzFheS8ggN31H59kFmjzBxV87T2p6DTv4WkUmG4IOn0SYJlH4bnM8RkalmHs78aMmmxfs/+V Ukk3JGwngfxJECc2aQDpgTfzO7sbYst5YY9HqC3+O0o+9Te+tv8KCFkCG8TT48hQzf2aRD/pZX6 jQUL36MnsDHB6wZPwIWlH3rF84ENHOlqyt+aDRxGHCLi51+2VB0F9kGZ+wFKQO2kyK3ZJwZ9Bpz kMkhnKgxySxANZje0VaBjiQVDep6Be651ZPagY+5ajRKC0IfK++q/qrZS6uhVkl+kNQpIuwrpN/ 3iwDeuvAh0TpBQ4= X-Received: by 2002:a17:906:ef04:b0:c20:af9d:454a with SMTP id a640c23a62f3a-c250c36aa50mr599124466b.16.1787732619590; Wed, 26 Aug 2026 01:23:39 -0700 (PDT) Received: from robert-83cx (static-dsl-191.87-197-115.telecom.sk. [87.197.115.191]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-c250a5d69a7sm554222766b.8.2026.08.26.01.23.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Aug 2026 01:23:38 -0700 (PDT) From: Robert Bozik To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham , Milan Zamazal , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Hans de Goede , Robert Mader , Bryan O'Donoghue , Laurent Pinchart , Robert Bozik Subject: [PATCH 6/7] ipa: softisp: Let the tuning file bound the default frame duration Date: Wed, 26 Aug 2026 10:23:27 +0200 Message-ID: <20260826082328.24176-7-robertbozik@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260826082328.24176-1-robertbozik@gmail.com> References: <20260826082328.24176-1-robertbozik@gmail.com> MIME-Version: 1.0 X-Mailman-Approved-At: Wed, 26 Aug 2026 10:33:21 +0200 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" Applications that don't set FrameDurationLimits get the full range the sensor mode supports, so in low light the AGC lengthens the frame as far as the sensor allows. Not all applications that omit the control expect that: the PipeWire libcamera source, for instance, negotiates a frame rate with its clients but never passes it to libcamera, and a video call would then drop to a frame every second in a dim room. Add a maxFrameDuration tuning parameter (in microseconds) that bounds the maximum frame duration used when no FrameDurationLimits control is set. Explicit FrameDurationLimits keep allowing the full sensor range. Signed-off-by: Robert Bozik --- src/ipa/softisp/algorithms/agc.cpp | 24 ++++++++++++++++++++++++ src/ipa/softisp/algorithms/agc.h | 5 +++++ 2 files changed, 29 insertions(+) diff --git a/src/ipa/softisp/algorithms/agc.cpp b/src/ipa/softisp/algorithms/agc.cpp index b6fc7203..0037fa6e 100644 --- a/src/ipa/softisp/algorithms/agc.cpp +++ b/src/ipa/softisp/algorithms/agc.cpp @@ -84,6 +84,15 @@ static constexpr float kExpMaxJump = 2.0; */ static constexpr double kDefaultMaxDigitalGain = 1.0; +/* + * Applications that don't set FrameDurationLimits get the full range the + * sensor supports, which lets the AGC slow the frame rate down to whatever + * the sensor allows in low light. That is rarely what an application which + * didn't ask for it expects, so the tuning file can bound the default + * maximum frame duration with maxFrameDuration (in microseconds); explicit + * FrameDurationLimits still allow the full sensor range. + */ + Agc::Agc() { } @@ -91,6 +100,17 @@ Agc::Agc() int Agc::init(IPAContext &context, const ValueNode &tuningData) { maxDigitalGain_ = tuningData["maxDigitalGain"].get(kDefaultMaxDigitalGain); + + const auto tuningMaxFrameDuration = tuningData["maxFrameDuration"].get(); + if (tuningMaxFrameDuration) { + if (*tuningMaxFrameDuration == 0) { + LOG(IPASoftIspExposure, Warning) + << "maxFrameDuration must be positive, ignored"; + } else { + defaultMaxFrameDuration_ = + std::chrono::microseconds(*tuningMaxFrameDuration); + } + } if (maxDigitalGain_ < 1.0) { LOG(IPASoftIspExposure, Warning) << "maxDigitalGain " << maxDigitalGain_ << " below 1.0, ignored"; @@ -136,6 +156,10 @@ int Agc::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &co if (it != context.ctrlMap.end() && cfg.vblankSupported) { agc.minFrameDuration = std::chrono::microseconds(it->second.min().get()); agc.maxFrameDuration = std::chrono::microseconds(it->second.max().get()); + if (defaultMaxFrameDuration_) + agc.maxFrameDuration = std::clamp(*defaultMaxFrameDuration_, + agc.minFrameDuration, + agc.maxFrameDuration); } else { agc.minFrameDuration = cfg.lineDuration * (cfg.frameHeight + cfg.vblankDef); agc.maxFrameDuration = agc.minFrameDuration; diff --git a/src/ipa/softisp/algorithms/agc.h b/src/ipa/softisp/algorithms/agc.h index 6e9ba728..ad732b1a 100644 --- a/src/ipa/softisp/algorithms/agc.h +++ b/src/ipa/softisp/algorithms/agc.h @@ -7,6 +7,10 @@ #pragma once +#include + +#include + #include "algorithm.h" namespace libcamera { @@ -39,6 +43,7 @@ private: int32_t exposureMaxForVblank(const IPAContext &context, int32_t vblank) const; double maxDigitalGain_; + std::optional defaultMaxFrameDuration_; }; } /* namespace ipa::softisp::algorithms */