From patchwork Fri Apr 11 13:04:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 23171 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 C761AC3213 for ; Fri, 11 Apr 2025 13:04:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 819F668AB0; Fri, 11 Apr 2025 15:04:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZNPdXWj7"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3EC5368A90 for ; Fri, 11 Apr 2025 15:04:39 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:5b21:2ad5:1023:7179]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E293C667; Fri, 11 Apr 2025 15:02:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1744376560; bh=B2fZGNGruVYdJyc8L5k+mXbvXdTVuBui0YHXQkKomoQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZNPdXWj7fee1+oRgNs0k08k5U1mxKfonhoT+ryfaqNdBilR5Lc/45WZxi9klSZMf3 O4wELSFKW/qXO+K9AQTofzof7k2vwrdFj0/JPuUsEIkiTwbrRcjXoIpEOHO1qEvJTl H/puZz89A08uIrBP+nq6CEOIPVZKCBeztmMufIkM= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 4/8] ipa: rkisp1: Add correction for exposure quantization Date: Fri, 11 Apr 2025 15:04:11 +0200 Message-ID: <20250411130423.2164577-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250411130423.2164577-1-stefan.klug@ideasonboard.com> References: <20250411130423.2164577-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" When WDR regulation is active, it can happen that exposure times get set to very low values (Sometimes 2-3 lines). This intentionally introduced underexposure is corrected by the GWDR module. As exposure time is quantized by lines, the smalles possible change in exposure time now results in a quite visible change in perceived brightness. Mitigate that by applying a small global gain to account for the error introduced by the exposure quantization. ToDo: This needs perfect frame synchronous control of the sensor to work properly which is not guaranteed in all cases. It still improves the behavior with the current regulation. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/agc.cpp | 2 ++ src/ipa/rkisp1/algorithms/awb.cpp | 12 ++++++++---- src/ipa/rkisp1/ipa_context.h | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 8e77455e7afd..0e4fd3663167 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -583,6 +583,8 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, activeState.agc.automatic.exposure = newExposureTime / lineDuration; activeState.agc.automatic.gain = aGain; + activeState.agc.automatic.gainLostInExposureQuantization = + newExposureTime / (activeState.agc.automatic.exposure * lineDuration); /* * Expand the target frame duration so that we do not run faster than * the minimum frame duration when we have short exposures. diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 84aa1d29419d..cc78136a22c8 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -170,6 +170,7 @@ void Awb::queueRequest(IPAContext &context, awbAlgo_->handleControls(controls); frameContext.awb.autoEnabled = awb.autoEnabled; + frameContext.awb.additionalGain = 1.0; if (awb.autoEnabled) return; @@ -218,15 +219,18 @@ void Awb::prepare(IPAContext &context, const uint32_t frame, auto &awb = context.activeState.awb; frameContext.awb.gains = awb.automatic.gains; frameContext.awb.temperatureK = awb.automatic.temperatureK; + frameContext.awb.additionalGain = + context.activeState.agc.automatic.gainLostInExposureQuantization; } + auto gains = frameContext.awb.gains * frameContext.awb.additionalGain; auto gainConfig = params->block(); gainConfig.setEnabled(true); - gainConfig->gain_green_b = std::clamp(256 * frameContext.awb.gains.g(), 0, 0x3ff); - gainConfig->gain_blue = std::clamp(256 * frameContext.awb.gains.b(), 0, 0x3ff); - gainConfig->gain_red = std::clamp(256 * frameContext.awb.gains.r(), 0, 0x3ff); - gainConfig->gain_green_r = std::clamp(256 * frameContext.awb.gains.g(), 0, 0x3ff); + gainConfig->gain_green_b = std::clamp(256 * gains.g(), 0, 0x3ff); + gainConfig->gain_blue = std::clamp(256 * gains.b(), 0, 0x3ff); + gainConfig->gain_red = std::clamp(256 * gains.r(), 0, 0x3ff); + gainConfig->gain_green_r = std::clamp(256 * gains.g(), 0, 0x3ff); /* If we have already set the AWB measurement parameters, return. */ if (frame > 0) diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 7ccc7b501aff..182203880ac9 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -76,6 +76,7 @@ struct IPAActiveState { } manual; struct { uint32_t exposure; + double gainLostInExposureQuantization; double gain; } automatic; @@ -149,6 +150,7 @@ struct IPAFrameContext : public FrameContext { RGB gains; bool autoEnabled; unsigned int temperatureK; + double additionalGain; } awb; struct {