From patchwork Tue Sep 23 19:06:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 24440 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 D4F78C32A9 for ; Tue, 23 Sep 2025 19:07:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8FB7D6B606; Tue, 23 Sep 2025 21:07:07 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="ADlLHnE1"; dkim-atps=neutral Received: from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 252C36B5C4 for ; Tue, 23 Sep 2025 21:07:03 +0200 (CEST) Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 0EF5040A38 for ; Tue, 23 Sep 2025 19:07:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 23BD6C4CEF5; Tue, 23 Sep 2025 19:07:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758654421; bh=ramw4DO9WLojIiNJYWPw1VXQmGJRsjyRNuX+hJ5G2z4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ADlLHnE1/CBQvWfy+lHfT3LUw14xaqVctWAIthjpDGdHTEP87M8MjzTz7Xfy4XnBh GOzqEw7BBExkPcEc1NIoygQSoGuEgV9Dnk/h5vA2dpCBIKFz/99S9VS9XOPb/bXCTS A+PdV8dvL88VPZ/xU48yHdLXle5t8HjW/aBxSOTN0cNNcrujVQSYqFzPOv5zhX40RY kLv/IBaUlljc6oMq5qmmOKDnbHPSUqvsLHNFBzhLYmIdj2OxsDQpk5/QbPZOQUkONb yBnOwvxh3MAFe9GsHIzk0p5CIyJhqscHX974cbVpMcCG9kPd8cPedY33Oae9VG9jIo 6bgNRfbjL5EAw== From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Hans de Goede Subject: [PATCH 1/5] ipa: software_isp: Fix context_.configuration.agc.againMin init Date: Tue, 23 Sep 2025 21:06:53 +0200 Message-ID: <20250923190657.21453-2-hansg@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250923190657.21453-1-hansg@kernel.org> References: <20250923190657.21453-1-hansg@kernel.org> 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" Currently context_.configuration.agc.againMin is not initialized when the control reports a non 0 minumum gain value. So far only the againMin == 0 case was handled and context_.configuration.agc.againMin was left unset otherwise. Signed-off-by: Hans de Goede Reviewed-by: Milan Zamazal Reviewed-by: Isaac Scott --- src/ipa/simple/soft_simple.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index c94c4cd55..e70439ee5 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -246,7 +246,9 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo) * other) we limit the range of the gain values used. */ context_.configuration.agc.againMax = againMax; - if (!againMin) { + if (againMin) { + context_.configuration.agc.againMin = againMin; + } else { LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear"; context_.configuration.agc.againMin = From patchwork Tue Sep 23 19:06:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 24441 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 D0EB3BDB1C for ; Tue, 23 Sep 2025 19:07:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 169836B615; Tue, 23 Sep 2025 21:07:13 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="UIbfWgYc"; dkim-atps=neutral Received: from tor.source.kernel.org (tor.source.kernel.org [IPv6:2600:3c04:e001:324:0:1991:8:25]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 04BBE6B5A2 for ; Tue, 23 Sep 2025 21:07:05 +0200 (CEST) Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id A52A660278 for ; Tue, 23 Sep 2025 19:07:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 74F5DC113D0; Tue, 23 Sep 2025 19:07:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758654423; bh=NVj0ZrZwq/FKJSkhzj18eapAWwCFZn/MHUunU/eV5rM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UIbfWgYcYMvKK5HTciFdj3iLm5SIRUUIn7/822babstDJrormcMMLArqJp16zLKa4 Y+dPaTVVoWFSfUSz8+dD4434ksWKxENmi7AjvAY4TkbyZwJhwwzlBsiHNF+WWRU+sM E5T4ANehCTtNkilhW2caeaBKnP3G5uzT24EaXRfZGfKRlLLLSFwZgCubgfx0F7RC0i 0PIKcYi1/FBC5J3p/kzmEYB2XQBHDnVMkTtVGMweN0UzoLZdBbjhAlzK1nlXrX7LPQ cJYCFd5KAZvpxSGuAivnRGNOfgF4BQGy2EGaa3vTWIJZV5ymHXDUmKtQCM07zP1J6O I+VgWqyKNSiYg== From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Hans de Goede Subject: [PATCH 2/5] ipa: software_isp: AGC: do not lower gain below default gain value Date: Tue, 23 Sep 2025 21:06:54 +0200 Message-ID: <20250923190657.21453-3-hansg@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250923190657.21453-1-hansg@kernel.org> References: <20250923190657.21453-1-hansg@kernel.org> 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" At the moment when the overall image brightness is considered too high the AGC code will lower the gain all the way down to againMin before considering lowering the exposure. What should happen instead is lower the gain no lower then its default ctrl value and after that lower the exposure instead of lowering the gain. Otherwise there might be a heavily overexposed image (e.g. all white) which then is made less white by a very low gain which is no good. While at it also remove the weird limitation to only lower the gain when exposure is set to the maximum. As long as the gain is higher then the default gain, the gain should be lowered first. Signed-off-by: Hans de Goede Reviewed-by: Milan Zamazal --- src/ipa/simple/algorithms/agc.cpp | 3 +-- src/ipa/simple/ipa_context.h | 2 +- src/ipa/simple/soft_simple.cpp | 3 +++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp index c46bb0ebe..94961f9fe 100644 --- a/src/ipa/simple/algorithms/agc.cpp +++ b/src/ipa/simple/algorithms/agc.cpp @@ -71,8 +71,7 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou } if (exposureMSV > kExposureOptimal + kExposureSatisfactory) { - if (exposure == context.configuration.agc.exposureMax && - again > context.configuration.agc.againMin) { + if (again > context.configuration.agc.againDef) { next = again * kExpNumeratorDown / kExpDenominator; if (again - next < context.configuration.agc.againMinStep) again -= context.configuration.agc.againMinStep; diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index a471b80ae..ba525a881 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -28,7 +28,7 @@ struct IPASessionConfiguration { float gamma; struct { int32_t exposureMin, exposureMax; - double againMin, againMax, againMinStep; + double againMin, againMax, againDef, againMinStep; utils::Duration lineDuration; } agc; struct { diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index e70439ee5..f0764ef46 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -216,10 +216,12 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo) int32_t againMin = gainInfo.min().get(); int32_t againMax = gainInfo.max().get(); + int32_t againDef = gainInfo.def().get(); if (camHelper_) { context_.configuration.agc.againMin = camHelper_->gain(againMin); context_.configuration.agc.againMax = camHelper_->gain(againMax); + context_.configuration.agc.againDef = camHelper_->gain(againDef); context_.configuration.agc.againMinStep = (context_.configuration.agc.againMax - context_.configuration.agc.againMin) / @@ -246,6 +248,7 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo) * other) we limit the range of the gain values used. */ context_.configuration.agc.againMax = againMax; + context_.configuration.agc.againDef = againDef; if (againMin) { context_.configuration.agc.againMin = againMin; } else { From patchwork Tue Sep 23 19:06:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 24442 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 DD37DC3331 for ; Tue, 23 Sep 2025 19:07:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1B27C6B605; Tue, 23 Sep 2025 21:07:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="QyzC8YBk"; dkim-atps=neutral Received: from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1AB836B605 for ; Tue, 23 Sep 2025 21:07:05 +0200 (CEST) Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id BC7F744AF1 for ; Tue, 23 Sep 2025 19:07:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DFCB4C4CEF5; Tue, 23 Sep 2025 19:07:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758654424; bh=n3plQx2gSYRqny6mDLwVPPbY+ll2yb/yiokZsOGyqjU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QyzC8YBkV3xxgbBYvJzGByh1pUGyPRxzHhkCTaMBRo0HaUt7wNMSgmds6H7nGqB7F ZUMf6O9AKuCVbgWAWH2TuISCtBx5kAzLboIo5ZH6lJm8nrGj5po35Upl5a6uRuXIiG jbdY3xJ8bgtgYdOjIHFSsxPhePWV/N5xyTaTVU5sJXcmKjJL6pEcaUiw9HqPPEcTMZ 1go2KjioSvIX00RXErE/RSUTlXXjmkJJWFOJX2q9ssXvdbMVlar6SoZcFemVUt1aGE nVgubdxpZ7CZwya3DNs10GCS6SSRWXpxxbm9lIyQkrBsb2NBo1wYOuX9F19qB0Pe39 q4Vm0bxhutL3w== From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Hans de Goede Subject: [PATCH 3/5] ipa: software_isp: AGC: Raise exposure or gain not both at the same time Date: Tue, 23 Sep 2025 21:06:55 +0200 Message-ID: <20250923190657.21453-4-hansg@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250923190657.21453-1-hansg@kernel.org> References: <20250923190657.21453-1-hansg@kernel.org> 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" Raise either exposure or gain; not both at the same time. Before this change when the last exposure raise is done, hitting exposure-max, gain would be increased at the same time. Signed-off-by: Hans de Goede Reviewed-by: Milan Zamazal --- src/ipa/simple/algorithms/agc.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp index 94961f9fe..230616e62 100644 --- a/src/ipa/simple/algorithms/agc.cpp +++ b/src/ipa/simple/algorithms/agc.cpp @@ -56,12 +56,13 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou double &again = frameContext.sensor.gain; if (exposureMSV < kExposureOptimal - kExposureSatisfactory) { - next = exposure * kExpNumeratorUp / kExpDenominator; - if (next - exposure < 1) - exposure += 1; - else - exposure = next; - if (exposure >= context.configuration.agc.exposureMax) { + if (exposure < context.configuration.agc.exposureMax) { + next = exposure * kExpNumeratorUp / kExpDenominator; + if (next - exposure < 1) + exposure += 1; + else + exposure = next; + } else { next = again * kExpNumeratorUp / kExpDenominator; if (next - again < context.configuration.agc.againMinStep) again += context.configuration.agc.againMinStep; From patchwork Tue Sep 23 19:06:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 24443 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 DE000C3332 for ; Tue, 23 Sep 2025 19:07:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 39BB56B611; Tue, 23 Sep 2025 21:07:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="SIft1GSQ"; dkim-atps=neutral Received: from tor.source.kernel.org (tor.source.kernel.org [IPv6:2600:3c04:e001:324:0:1991:8:25]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0E80B6B5FE for ; Tue, 23 Sep 2025 21:07:07 +0200 (CEST) Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 3CD416027D for ; Tue, 23 Sep 2025 19:07:06 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 198CEC113D0; Tue, 23 Sep 2025 19:07:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758654425; bh=Vx/0xvt89XCCFLMy+c+hKznTAYPnX+/TgEK9P5I19Go=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SIft1GSQMVoxaxoPjxT0URWNwUq1trgMiQObknjqkRl1mp/8Ae/Z29qXEGp6LVHIa 1kil9OT6B026XSqRMLQu1wooxyvGufkn56i2R2+o8+JhMRVobpmJhGPQH99tbYKHOO +goOwdM3rvco8DlyMm/95+Br67HkQjXP/W6HLTbWt24uUpAM6zU8TxPgvc0iNRkg0m YnLhkW2hEbHF+Pxviw7P/xjopfHvMB7qR6QhYAU+Yj+6EzJAIKzgt+nvcz86ILDKl4 OCOG0fUvvxYth1VHGiwneLyGmV5tvmYspz1mmU/SoTcsd63t0Ig03JGdU2sGoPyQ7N BMMZx7nHw2NUg== From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Hans de Goede Subject: [PATCH 4/5] ipa: software_isp: AGC: Only use integers for exposure calculations Date: Tue, 23 Sep 2025 21:06:56 +0200 Message-ID: <20250923190657.21453-5-hansg@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250923190657.21453-1-hansg@kernel.org> References: <20250923190657.21453-1-hansg@kernel.org> 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" Exposure is an integer, instead of re-using the "double next" used for again calculations, doing intermediate calculations with double precision, use a local next variable of an integer type. Signed-off-by: Hans de Goede Reviewed-by: Milan Zamazal Reviewed-by: Isaac Scott --- src/ipa/simple/algorithms/agc.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp index 230616e62..cdde56ba2 100644 --- a/src/ipa/simple/algorithms/agc.cpp +++ b/src/ipa/simple/algorithms/agc.cpp @@ -51,19 +51,18 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1; static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1; - double next; int32_t &exposure = frameContext.sensor.exposure; double &again = frameContext.sensor.gain; if (exposureMSV < kExposureOptimal - kExposureSatisfactory) { if (exposure < context.configuration.agc.exposureMax) { - next = exposure * kExpNumeratorUp / kExpDenominator; + int32_t next = exposure * kExpNumeratorUp / kExpDenominator; if (next - exposure < 1) exposure += 1; else exposure = next; } else { - next = again * kExpNumeratorUp / kExpDenominator; + double next = again * kExpNumeratorUp / kExpDenominator; if (next - again < context.configuration.agc.againMinStep) again += context.configuration.agc.againMinStep; else @@ -73,13 +72,13 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou if (exposureMSV > kExposureOptimal + kExposureSatisfactory) { if (again > context.configuration.agc.againDef) { - next = again * kExpNumeratorDown / kExpDenominator; + double next = again * kExpNumeratorDown / kExpDenominator; if (again - next < context.configuration.agc.againMinStep) again -= context.configuration.agc.againMinStep; else again = next; } else { - next = exposure * kExpNumeratorDown / kExpDenominator; + int32_t next = exposure * kExpNumeratorDown / kExpDenominator; if (exposure - next < 1) exposure -= 1; else From patchwork Tue Sep 23 19:06:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 24444 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 31361C32A9 for ; Tue, 23 Sep 2025 19:07:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4B3A66B61A; Tue, 23 Sep 2025 21:07:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="ZLwO21v8"; dkim-atps=neutral Received: from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 336CC6B608 for ; Tue, 23 Sep 2025 21:07:08 +0200 (CEST) Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 6693C60278 for ; Tue, 23 Sep 2025 19:07:07 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 616BDC113D0; Tue, 23 Sep 2025 19:07:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758654427; bh=CCZwD+CJ73bAxaZILpNf1Z+g+VTllZSU3Kfzx+PICJo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZLwO21v8l2nuSKTSwlU0e0HrtbJyTcgYoTmRGq01ImSZWGWgnjd93fRlk6HDp5fk+ GtZl7I+0n+Cripchh3UwOXgrTfIIaakb3Snxm1rmjGSSVGjO++pFPAMTTLJlqDXcBA iKsSulbjwy078SMWeAdREZ7ch5x40iJ65+PFTrgxPXAGNLmfCypz+ueoGc3x519h9s mg6Z2IIf1Wp9dPhViwl+xWvDbepS4GcDCd6Cj9zPpXSsCAVJ//VzDXzuiTdmSb0huG mV/3JLhYTf/hIhZ7gJorxnf9kviBkfzESIN9SzOaVInGbXbpE6qKT+ahTk50zXDOAM rcNP4QO++YhFA== From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Hans de Goede Subject: [PATCH 5/5] ipa: software_isp: AGC: Stop using delayed control for previous values Date: Tue, 23 Sep 2025 21:06:57 +0200 Message-ID: <20250923190657.21453-6-hansg@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250923190657.21453-1-hansg@kernel.org> References: <20250923190657.21453-1-hansg@kernel.org> 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" Due to a combination of not having correct control-delay information for various sensors as well as the generic nature of the simple-pipeline + software-ISP meaning that any pipeline delays are unknown it is impossible to get reliable control-delay values. Wrong control-delay values can lead to pretty bad oscilation. Since atm it is not possible to fix the wrong control-delay values, stop using the old sensor values reported by the delayed-controlled mechanism. Instead remember the gain and exposures set the last time the algorithm runs (initializing the cached values with the actual sensor values on the first frame), combined with skipping a fixed number of frames after changing values. Signed-off-by: Hans de Goede --- src/ipa/simple/algorithms/agc.cpp | 30 +++++++++++++++++++++++++----- src/ipa/simple/algorithms/agc.h | 3 ++- src/ipa/simple/ipa_context.h | 6 ++++++ src/ipa/simple/soft_simple.cpp | 4 ++-- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp index cdde56ba2..3c0e20ddc 100644 --- a/src/ipa/simple/algorithms/agc.cpp +++ b/src/ipa/simple/algorithms/agc.cpp @@ -41,7 +41,15 @@ Agc::Agc() { } -void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV) +int Agc::configure(IPAContext &context, + [[maybe_unused]] const IPAConfigInfo &configInfo) +{ + context.activeState.agc.skipFrames = 0; + + return 0; +} + +void Agc::updateExposure(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, double exposureMSV) { /* * kExpDenominator of 10 gives ~10% increment/decrement; @@ -51,8 +59,18 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1; static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1; - int32_t &exposure = frameContext.sensor.exposure; - double &again = frameContext.sensor.gain; + int32_t &skipFrames = context.activeState.agc.skipFrames; + int32_t &exposure = context.activeState.agc.exposure; + double &again = context.activeState.agc.again; + + /* Set initial-gain values from sensor on first frame */ + if (frame == 0) { + exposure = frameContext.sensor.exposure; + again = frameContext.sensor.gain; + } + + if (skipFrames && --skipFrames) + return; if (exposureMSV < kExposureOptimal - kExposureSatisfactory) { if (exposure < context.configuration.agc.exposureMax) { @@ -68,6 +86,7 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou else again = next; } + skipFrames = 3; } if (exposureMSV > kExposureOptimal + kExposureSatisfactory) { @@ -84,6 +103,7 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou else exposure = next; } + skipFrames = 3; } exposure = std::clamp(exposure, context.configuration.agc.exposureMin, @@ -97,7 +117,7 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou } void Agc::process(IPAContext &context, - [[maybe_unused]] const uint32_t frame, + const uint32_t frame, IPAFrameContext &frameContext, const SwIspStats *stats, ControlList &metadata) @@ -135,7 +155,7 @@ void Agc::process(IPAContext &context, } float exposureMSV = (denom == 0 ? 0 : static_cast(num) / denom); - updateExposure(context, frameContext, exposureMSV); + updateExposure(context, frame, frameContext, exposureMSV); } REGISTER_IPA_ALGORITHM(Agc, "Agc") diff --git a/src/ipa/simple/algorithms/agc.h b/src/ipa/simple/algorithms/agc.h index 112d9f5a1..ef387664f 100644 --- a/src/ipa/simple/algorithms/agc.h +++ b/src/ipa/simple/algorithms/agc.h @@ -19,13 +19,14 @@ public: Agc(); ~Agc() = default; + int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const SwIspStats *stats, ControlList &metadata) override; private: - void updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV); + void updateExposure(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, double exposureMSV); }; } /* namespace ipa::soft::algorithms */ diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index ba525a881..cdab980a1 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -37,6 +37,12 @@ struct IPASessionConfiguration { }; struct IPAActiveState { + struct { + int32_t skipFrames; + int32_t exposure; + double again; + } agc; + struct { uint8_t level; int32_t lastExposure; diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index f0764ef46..f8c6291e2 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -327,8 +327,8 @@ void IPASoftSimple::processStats(const uint32_t frame, ControlList ctrls(sensorInfoMap_); - auto &againNew = frameContext.sensor.gain; - ctrls.set(V4L2_CID_EXPOSURE, frameContext.sensor.exposure); + auto &againNew = context_.activeState.agc.again; + ctrls.set(V4L2_CID_EXPOSURE, context_.activeState.agc.exposure); ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast(camHelper_ ? camHelper_->gainCode(againNew) : againNew));