From patchwork Fri May 1 19:13:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: d3vv3 X-Patchwork-Id: 26595 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 47B7AC32F7 for ; Fri, 1 May 2026 19:55:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7B8BC63020; Fri, 1 May 2026 21:55:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="nOS10SpO"; dkim-atps=neutral Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E5A106301A for ; Fri, 1 May 2026 21:14:24 +0200 (CEST) Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-488ab2db91aso25729605e9.3 for ; Fri, 01 May 2026 12:14:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777662864; x=1778267664; 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; bh=Np2KpHav7jquUv7l8lhExD9bUwRg7NkVkFY4AMLAGpQ=; b=nOS10SpO4bJao0IGdtIucVXodVS7Jla+wbAWjZjo+JEdJkdTaAlcKdL2OE3HFZlrpX tu5C/yLj34jKmuias+w2v9rGRmJdf7C2WYFEKaBWjHzDFsLB7hwwEV6/ycsHw3VdhMKp 17NJbnwqrdGL7Waxss1sfwMJ9Fe/+oDnXETBiGQB+7GF/F4yrSu6rltPbwUEJjranrkT Vjq9YHauVOmStgW+PCaCb+xpHZ/gLJZUePrcSv93NgOkD9CDRV7G3n/vPFtBNIJ56rj1 0PIMTegRcq+x5StGj2bso/mGDCuyY4K26XHbjgALLK80mBCjKQT296yfIY5U949xnY4O Lx6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777662864; x=1778267664; 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; bh=Np2KpHav7jquUv7l8lhExD9bUwRg7NkVkFY4AMLAGpQ=; b=I9ljDs92ULszzROXmAnzhfu/BIfGxuUyTcq+j2RJu3UTfTt7x1K5fvpn3bfApxLzrT Q1nb/mrsE4vTHJKs+VLwUht4TvYoUmSMnRLmssXQQIxp5aEgEj8nNWjuQ4pLcQ3+/6Nq PTUQej+l0UawVzRjmd29DY90fLgckokF3ehIY4zOorPLSdv0FuFLRswKRDRC25J9XHQa ygrnZ8vcxnZNdONXY4yxZOMUOz+QROUx7ewydHqVc6vJbeHU/+UxhvywFM2e8q12szba S4tsyQN0F/Aa8qCjlVb3Fp5CwQdI9JU0B0RHXzHthpdDLc2GstlSCoPdFlMiY0RyD9ZW 80vg== X-Gm-Message-State: AOJu0YxgQNJVp082QP4JblJFAVw8e/fqTJtZ8Q4pHb3S372Z3ehR36Ho UltY9sgU8hkDuu/YnrRnqJ2eWC+hIMRFKgD7GqPEP1zDGdIOSGuNhsSfSHVV5Q== X-Gm-Gg: AeBDiesf/Jy+e4pYIjwxzeAXGMrpbJ2WCWVul/wqHph374pDIyhvjUHJUjQJGMcyzCE nPSUkAUC4Yfay/kmUULWxDappyEXnR9R/jtgGjD7inorBcE+2Td2hhWL1/ILQLLzFDkUnlbN2v6 SIBh5fr27zCOXGC1IqQ+wRHpXeKBXX23TN6oymAE2jsdiXcGKSn+Roj7fVj0G87wCJFYezgfX3V eiCKkRsYfc93/mKOAVhBff+05nujM2cmS8QDVl9/+SeGNx/XzURxOEtyU5S9H/N4b9OU8E2DvbF fMZDkVrz2IXB2zDp3MYmNtmXNBBoXRxDwxHlxSZo09Zn/SOP4959B5NytmkLsyBcYiwcA3PRM3D riY/RaplODtJxiNhme6MiCuUWZQus3WDoOiN/9P4JPpqromV0tnzG1gtUFqPP1vuvDz4to6tiPa YfNqIN9hKZd2c6sHKY+p6ZvbrLWzq23coLi0OeWZ1eiUuD1S2+/YBTQKoUZSsRKFX1WjYh0rNYe yopzoax+cUZ+VDV+Z72z7NUhqLrgqd5gY3OT8rI928= X-Received: by 2002:a05:600c:a402:b0:486:fba7:b150 with SMTP id 5b1f17b1804b1-48a9865f7c3mr4466595e9.15.1777662864353; Fri, 01 May 2026 12:14:24 -0700 (PDT) Received: from dexps.speedport.ip (p200300eda74453f7a35e44f7d2f0427a.dip0.t-ipconnect.de. [2003:ed:a744:53f7:a35e:44f7:d2f0:427a]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48a8eb69698sm139146305e9.1.2026.05.01.12.14.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 May 2026 12:14:24 -0700 (PDT) From: d3vv3 To: libcamera-devel@lists.libcamera.org Cc: d3vv3 Subject: [PATCH] ipa: simple: agc: Read exposure target and gain from YAML Date: Fri, 1 May 2026 21:13:12 +0200 Message-ID: <20260501191400.985920-4-devve.3@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260501191400.985920-1-devve.3@gmail.com> References: <20260501191400.985920-1-devve.3@gmail.com> MIME-Version: 1.0 X-Mailman-Approved-At: Fri, 01 May 2026 21:55:24 +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" Replace the hardcoded kExposureOptimal, kExposureSatisfactory, and kExpProportionalGain constants with member variables read from the tuning file as exposureTarget, hysteresis, and proportionalGain. Defaults match the previous values (2.5, 0.2, 0.04). Signed-off-by: d3vv3 --- src/ipa/simple/algorithms/agc.cpp | 33 ++++++++++++++++++++----------- src/ipa/simple/algorithms/agc.h | 8 ++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp index ac977d5f..66618d0f 100644 --- a/src/ipa/simple/algorithms/agc.cpp +++ b/src/ipa/simple/algorithms/agc.cpp @@ -28,45 +28,56 @@ static constexpr unsigned int kExposureBinsCount = 5; /* * The exposure is optimal when the mean sample value of the histogram is - * in the middle of the range. + * in the middle of the range. Overridable via YAML exposureTarget. */ -static constexpr float kExposureOptimal = kExposureBinsCount / 2.0; +static constexpr float kExposureTargetDefault = kExposureBinsCount / 2.0; /* * This implements the hysteresis for the exposure adjustment. * It is small enough to have the exposure close to the optimal, and is big * enough to prevent the exposure from wobbling around the optimal value. */ -static constexpr float kExposureSatisfactory = 0.2; +static constexpr float kHysteresisDefault = 0.2; /* * Proportional gain for exposure/gain adjustment. Maps the MSV error to a * multiplicative correction factor: * - * factor = 1.0 + kExpProportionalGain * error + * factor = 1.0 + proportionalGain_ * error * - * With kExpProportionalGain = 0.04: + * With proportionalGain_ = 0.04: * - max error ~2.5 -> factor 1.10 (~10% step, same as before) * - error 1.0 -> factor 1.04 (~4% step) * - error 0.3 -> factor 1.012 (~1.2% step) * - * This replaces the fixed 10% bang-bang step with a proportional correction - * that converges smoothly and avoids overshooting near the target. + * Overridable via YAML proportionalGain. */ -static constexpr float kExpProportionalGain = 0.04; +static constexpr float kProportionalGainDefault = 0.04; Agc::Agc() { } +int Agc::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData) +{ + exposureTarget_ = tuningData["exposureTarget"].get() + .value_or(kExposureTargetDefault); + hysteresis_ = tuningData["hysteresis"].get() + .value_or(kHysteresisDefault); + proportionalGain_ = tuningData["proportionalGain"].get() + .value_or(kProportionalGainDefault); + + return 0; +} + void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV) { int32_t &exposure = frameContext.sensor.exposure; double &again = frameContext.sensor.gain; - double error = kExposureOptimal - exposureMSV; + double error = exposureTarget_ - exposureMSV; - if (std::abs(error) <= kExposureSatisfactory) + if (std::abs(error) <= hysteresis_) return; /* @@ -74,7 +85,7 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou * determines the direction: positive error means too dark (increase), * negative means too bright (decrease). */ - float factor = 1.0f + static_cast(error) * kExpProportionalGain; + float factor = 1.0f + static_cast(error) * proportionalGain_; if (factor > 1.0f) { /* Scene too dark: increase exposure first, then gain. */ diff --git a/src/ipa/simple/algorithms/agc.h b/src/ipa/simple/algorithms/agc.h index 112d9f5a..b8ed542b 100644 --- a/src/ipa/simple/algorithms/agc.h +++ b/src/ipa/simple/algorithms/agc.h @@ -7,6 +7,8 @@ #pragma once +#include + #include "algorithm.h" namespace libcamera { @@ -19,6 +21,8 @@ public: Agc(); ~Agc() = default; + int init(IPAContext &context, const ValueNode &tuningData) override; + void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const SwIspStats *stats, @@ -26,6 +30,10 @@ public: private: void updateExposure(IPAContext &context, IPAFrameContext &frameContext, double exposureMSV); + + float exposureTarget_; + float hysteresis_; + float proportionalGain_; }; } /* namespace ipa::soft::algorithms */