From patchwork Thu Feb 10 11:43:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 15359 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 98769BDCBF for ; Thu, 10 Feb 2022 11:43:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 76F4860E70; Thu, 10 Feb 2022 12:43:23 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oYJy/tBr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A4FC5610A1 for ; Thu, 10 Feb 2022 12:43:20 +0100 (CET) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:c44d:925d:d63:5b07]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 47C0A48B; Thu, 10 Feb 2022 12:43:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1644493400; bh=z1Qs1WSEcAbn5T1b4eUCbDKEh5hHF8+OExTPMAF16CA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oYJy/tBraxWmmLm3RB4UAXSZvx7LYJBgoBFsQuXgIEzzu/HQoUZmK8PYlO9TbXl90 mQMQ4WIJfsk6Baw0+KtUcLuctlKT+qk2km5xkAwwhx5qMLrq4kfcotc6L3gANyPMTT 9z94S6TzDwzmkTK3LSFcR6lMKufVqBT/BHv2GmEA= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 10 Feb 2022 12:43:14 +0100 Message-Id: <20220210114316.1151170-2-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220210114316.1151170-1-jeanmichel.hautbois@ideasonboard.com> References: <20220210114316.1151170-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/3] ipa: ipu3: Return filtered value 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" When the current exposure value is calculated, it is cached and used by filterExposure(). Use private filteredExposure_ and pass currentExposure as a parameter. In order to limit the use of filteredExposure_, return the value from filterExposure(). While at it, remove a stale comment. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/agc.cpp | 74 ++++++++++++++++++--------------- src/ipa/ipu3/algorithms/agc.h | 3 +- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 8d6f18f6..a929085c 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -72,7 +72,7 @@ static constexpr double kRelativeLuminanceTarget = 0.16; Agc::Agc() : frameCount_(0), lineDuration_(0s), minShutterSpeed_(0s), - maxShutterSpeed_(0s), filteredExposure_(0s), currentExposure_(0s) + maxShutterSpeed_(0s), filteredExposure_(0s) { } @@ -143,33 +143,37 @@ double Agc::measureBrightness(const ipu3_uapi_stats_3a *stats, /** * \brief Apply a filter on the exposure value to limit the speed of changes + * \param[in] exposureValue The target exposure from the AGC algorithm + * + * The speed of the filter is adaptive, and will produce the target quicker + * during startup, or when the target exposure is within 20% of the most recent + * filter output. + * + * \return The filtered exposure */ -void Agc::filterExposure() +utils::Duration Agc::filterExposure(utils::Duration exposureValue) { double speed = 0.2; - /* Adapt instantly if we are in startup phase */ + /* Adapt instantly if we are in startup phase. */ if (frameCount_ < kNumStartupFrames) speed = 1.0; - if (filteredExposure_ == 0s) { - /* DG stands for digital gain.*/ - filteredExposure_ = currentExposure_; - } else { - /* - * If we are close to the desired result, go faster to avoid making - * multiple micro-adjustments. - * \todo Make this customisable? - */ - if (filteredExposure_ < 1.2 * currentExposure_ && - filteredExposure_ > 0.8 * currentExposure_) - speed = sqrt(speed); - - filteredExposure_ = speed * currentExposure_ + - filteredExposure_ * (1.0 - speed); - } + /* + * If we are close to the desired result, go faster to avoid making + * multiple micro-adjustments. + * \todo Make this customisable? + */ + if (filteredExposure_ < 1.2 * exposureValue && + filteredExposure_ > 0.8 * exposureValue) + speed = sqrt(speed); + + filteredExposure_ = speed * exposureValue + + filteredExposure_ * (1.0 - speed); - LOG(IPU3Agc, Debug) << "After filtering, total_exposure " << filteredExposure_; + LOG(IPU3Agc, Debug) << "After filtering, exposure " << filteredExposure_; + + return filteredExposure_; } /** @@ -213,27 +217,29 @@ void Agc::computeExposure(IPAFrameContext &frameContext, double yGain, * Calculate the current exposure value for the scene as the latest * exposure value applied multiplied by the new estimated gain. */ - currentExposure_ = effectiveExposureValue * evGain; + utils::Duration exposureValue = effectiveExposureValue * evGain; /* Clamp the exposure value to the min and max authorized */ utils::Duration maxTotalExposure = maxShutterSpeed_ * maxAnalogueGain_; - currentExposure_ = std::min(currentExposure_, maxTotalExposure); - LOG(IPU3Agc, Debug) << "Target total exposure " << currentExposure_ + exposureValue = std::min(exposureValue, maxTotalExposure); + LOG(IPU3Agc, Debug) << "Target total exposure " << exposureValue << ", maximum is " << maxTotalExposure; - /* \todo: estimate if we need to desaturate */ - filterExposure(); - - /* Divide the exposure value as new exposure and gain values */ - utils::Duration exposureValue = filteredExposure_; - utils::Duration shutterTime; + /* + * Filter the exposure. + * \todo: estimate if we need to desaturate + */ + exposureValue = filterExposure(exposureValue); /* - * Push the shutter time up to the maximum first, and only then - * increase the gain. - */ - shutterTime = std::clamp(exposureValue / minAnalogueGain_, - minShutterSpeed_, maxShutterSpeed_); + * Divide the exposure value as new exposure and gain values. + * + * Push the shutter time up to the maximum first, and only then + * increase the gain. + */ + utils::Duration shutterTime = + std::clamp(exposureValue / minAnalogueGain_, + minShutterSpeed_, maxShutterSpeed_); double stepGain = std::clamp(exposureValue / shutterTime, minAnalogueGain_, maxAnalogueGain_); LOG(IPU3Agc, Debug) << "Divided up shutter and gain are " diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h index 96ec7005..84bfe045 100644 --- a/src/ipa/ipu3/algorithms/agc.h +++ b/src/ipa/ipu3/algorithms/agc.h @@ -33,7 +33,7 @@ public: private: double measureBrightness(const ipu3_uapi_stats_3a *stats, const ipu3_uapi_grid_config &grid) const; - void filterExposure(); + utils::Duration filterExposure(utils::Duration currentExposure); void computeExposure(IPAFrameContext &frameContext, double yGain, double iqMeanGain); double estimateLuminance(IPAFrameContext &frameContext, @@ -51,7 +51,6 @@ private: double maxAnalogueGain_; utils::Duration filteredExposure_; - utils::Duration currentExposure_; uint32_t stride_; };