From patchwork Mon Jul 7 08:55:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 23758 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 34522C3237 for ; Mon, 7 Jul 2025 08:56:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BB0B768EB5; Mon, 7 Jul 2025 10:56:03 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="FXWJikQ5"; 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 D379B68EA6 for ; Mon, 7 Jul 2025 10:56:00 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:c79f:85df:e7f5:4c31]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 3D629190D; Mon, 7 Jul 2025 10:55:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1751878534; bh=V3SARb52aSpZwSeFnkttvpZZ06JCkcaM6t/PpdEkqMM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FXWJikQ5nBglK2LwO9XPxeGada/vHtu5jsiJoGuIkqmmaD2qTvT7C0CdTLOYZgj1i TABi7IVnsPG/7drdNW4+IdIzvv87gZBAKaiL0E90EMKRQu9R6zUTXEZTM7xCi6XNY8 SEBOB34I0m8kz22kkbaIVe/8Kvkt3uWYDHb3pMkQ= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Kieran Bingham , Paul Elder Subject: [PATCH v3 9/9] ipa: rkisp1: agc: Implement ExposureValue control Date: Mon, 7 Jul 2025 10:55:12 +0200 Message-ID: <20250707085520.39777-10-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250707085520.39777-1-stefan.klug@ideasonboard.com> References: <20250707085520.39777-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" Now that agc_mean_luminance supports exposure correction, implement the corresponding ExposureValue control for rkisp1. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- Changes in v3: - Collected tags --- src/ipa/rkisp1/algorithms/agc.cpp | 10 ++++++++++ src/ipa/rkisp1/ipa_context.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 137a0750017b..35440b67e999 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -157,6 +157,7 @@ int Agc::init(IPAContext &context, const YamlObject &tuningData) ControlValue(controls::AnalogueGainModeAuto)); /* \todo Move this to the Camera class */ context.ctrlMap[&controls::AeEnable] = ControlInfo(false, true, true); + context.ctrlMap[&controls::ExposureValue] = ControlInfo(-8.0f, 8.0f, 0.0f); context.ctrlMap.merge(controls()); return 0; @@ -179,6 +180,7 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure; context.activeState.agc.autoExposureEnabled = !context.configuration.raw; context.activeState.agc.autoGainEnabled = !context.configuration.raw; + context.activeState.agc.exposureValue = 0.0; context.activeState.agc.constraintMode = static_cast(constraintModes().begin()->first); @@ -301,6 +303,11 @@ void Agc::queueRequest(IPAContext &context, static_cast(*constraintMode); frameContext.agc.constraintMode = agc.constraintMode; + const auto &exposureValue = controls.get(controls::ExposureValue); + if (exposureValue) + agc.exposureValue = *exposureValue; + frameContext.agc.exposureValue = agc.exposureValue; + const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits); if (frameDurationLimits) { /* Limit the control value to the limits in ControlInfo */ @@ -407,6 +414,7 @@ void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext, metadata.set(controls::AeMeteringMode, frameContext.agc.meteringMode); metadata.set(controls::AeExposureMode, frameContext.agc.exposureMode); metadata.set(controls::AeConstraintMode, frameContext.agc.constraintMode); + metadata.set(controls::ExposureValue, frameContext.agc.exposureValue); } /** @@ -556,6 +564,8 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, double analogueGain = frameContext.sensor.gain; utils::Duration effectiveExposureValue = exposureTime * analogueGain; + setExposureCompensation(pow(2.0, frameContext.agc.exposureValue)); + utils::Duration newExposureTime; double aGain, dGain; std::tie(newExposureTime, aGain, dGain) = diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index f0d504215d34..7ccc7b501aff 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -81,6 +81,7 @@ struct IPAActiveState { bool autoExposureEnabled; bool autoGainEnabled; + double exposureValue; controls::AeConstraintModeEnum constraintMode; controls::AeExposureModeEnum exposureMode; controls::AeMeteringModeEnum meteringMode; @@ -129,6 +130,7 @@ struct IPAFrameContext : public FrameContext { struct { uint32_t exposure; double gain; + double exposureValue; uint32_t vblank; bool autoExposureEnabled; bool autoGainEnabled;