From patchwork Fri Aug 15 10:29:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24114 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 AD8F3BDCC1 for ; Fri, 15 Aug 2025 10:30:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5E42669261; Fri, 15 Aug 2025 12:30:06 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="sdOFp/M1"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4B7ED6925A for ; Fri, 15 Aug 2025 12:30:04 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:83d1:ae5d:93a6:6837]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 6A0078FA; Fri, 15 Aug 2025 12:29:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755253749; bh=+0VxQH3b+nvVVQ6oiDfrRgrZzh0xGvNz8gW25SVg7fs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sdOFp/M1LZKnaivZhR+/MZzWfkFnMH2GhEbC4OoqCHkDc31HiS6zekeRYpVXquW/7 P/u5Byp0cB+AIondWEWD4rv/vregxWlORHyYu0zmbHizft6YNRpJ24szadDIkWkDWh gm1zD7vL6dsL073i2uOcBpXOY91thd7Cv/5uI++4= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Kieran Bingham , Daniel Scally Subject: [PATCH v3 04/19] libipa: exposure_mode_helper: Take exposure/gain quantization into account Date: Fri, 15 Aug 2025 12:29:24 +0200 Message-ID: <20250815102945.1602071-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250815102945.1602071-1-stefan.klug@ideasonboard.com> References: <20250815102945.1602071-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 ExposureModeHelper::splitExposure() the quantization of exposure time and gain is not taken into account. This can lead to visible flicker when the quantization steps are too big. As a preparation to fixing that, add a function to set the sensor line length and the current sensor mode helper and extend the clampXXX functions to return the quantization error. By default the exposure time quantization is assumed to be 1us and gain is assumed to not be quantized at all. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham Reviewed-by: Daniel Scally --- Changes in v3: - Collected tags - Renamed lineLength to lineDuration - Remove the "no functional changes" sentence, as the returned exposureTime/gain are now quantized, which happened outside of this class before. So that is actually a functional change. --- src/ipa/libipa/exposure_mode_helper.cpp | 49 ++++++++++++++++++++----- src/ipa/libipa/exposure_mode_helper.h | 10 ++++- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp index 0c1e99e31a47..b18c30a6291c 100644 --- a/src/ipa/libipa/exposure_mode_helper.cpp +++ b/src/ipa/libipa/exposure_mode_helper.cpp @@ -70,18 +70,37 @@ namespace ipa { * the runtime limits set through setLimits() instead. */ ExposureModeHelper::ExposureModeHelper(const Span> stages) + : lineDuration_(1us), minExposureTime_(0us), maxExposureTime_(0us), + minGain_(0), maxGain_(0), sensorHelper_(nullptr) { - minExposureTime_ = 0us; - maxExposureTime_ = 0us; - minGain_ = 0; - maxGain_ = 0; - for (const auto &[s, g] : stages) { exposureTimes_.push_back(s); gains_.push_back(g); } } +/** + * \brief Configure sensor details + * \param[in] lineDuration The current line length of the sensor + * \param[in] sensorHelper The sensor helper + * + * This function sets the line length and sensor helper. These are used in + * splitExposure() to take the quantization of the exposure and gain into + * account. + * + * When this is not called, is is assumed that exposure is in micro second + * granularity and gain has no quantization at all. + * + * The caller has to ensure that sensorHelper is valid for the lifetime of + * ExposureModeHelper or the next call to configure. + */ +void ExposureModeHelper::configure(utils::Duration lineDuration, + const CameraSensorHelper *sensorHelper) +{ + lineDuration_ = lineDuration; + sensorHelper_ = sensorHelper; +} + /** * \brief Set the exposure time and gain limits * \param[in] minExposureTime The minimum exposure time supported @@ -108,14 +127,26 @@ void ExposureModeHelper::setLimits(utils::Duration minExposureTime, maxGain_ = maxGain; } -utils::Duration ExposureModeHelper::clampExposureTime(utils::Duration exposureTime) const +utils::Duration ExposureModeHelper::clampExposureTime(utils::Duration exposureTime, + double *quantizationGain) const { - return std::clamp(exposureTime, minExposureTime_, maxExposureTime_); + utils::Duration clamped; + utils::Duration exp; + + clamped = std::clamp(exposureTime, minExposureTime_, maxExposureTime_); + exp = static_cast(clamped / lineDuration_) * lineDuration_; + if (quantizationGain) + *quantizationGain = clamped / exp; + + return exp; } -double ExposureModeHelper::clampGain(double gain) const +double ExposureModeHelper::clampGain(double gain, double *quantizationGain) const { - return std::clamp(gain, minGain_, maxGain_); + double clamped = std::clamp(gain, minGain_, maxGain_); + if (!sensorHelper_) + return clamped; + return sensorHelper_->quantizeGain(clamped, quantizationGain); } /** diff --git a/src/ipa/libipa/exposure_mode_helper.h b/src/ipa/libipa/exposure_mode_helper.h index c5be1b6703a8..ac7e8da95c6c 100644 --- a/src/ipa/libipa/exposure_mode_helper.h +++ b/src/ipa/libipa/exposure_mode_helper.h @@ -14,6 +14,8 @@ #include #include +#include "camera_sensor_helper.h" + namespace libcamera { namespace ipa { @@ -24,6 +26,7 @@ public: ExposureModeHelper(const Span> stages); ~ExposureModeHelper() = default; + void configure(utils::Duration lineLength, const CameraSensorHelper *sensorHelper); void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, double minGain, double maxGain); @@ -36,16 +39,19 @@ public: double maxGain() const { return maxGain_; } private: - utils::Duration clampExposureTime(utils::Duration exposureTime) const; - double clampGain(double gain) const; + utils::Duration clampExposureTime(utils::Duration exposureTime, + double *quantizationGain = nullptr) const; + double clampGain(double gain, double *quantizationGain = nullptr) const; std::vector exposureTimes_; std::vector gains_; + utils::Duration lineDuration_; utils::Duration minExposureTime_; utils::Duration maxExposureTime_; double minGain_; double maxGain_; + const CameraSensorHelper *sensorHelper_; }; } /* namespace ipa */