From patchwork Tue Apr 7 22:01:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 26491 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 97132C32F6 for ; Tue, 7 Apr 2026 22:03:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0D9C062D4E; Wed, 8 Apr 2026 00:02:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gNsNm7zZ"; 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 67FBA62D9C for ; Wed, 8 Apr 2026 00:02:42 +0200 (CEST) Received: from [192.168.0.204] (ams.linuxembedded.co.uk [209.38.108.23]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BA9402443; Wed, 8 Apr 2026 00:01:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1775599274; bh=ZAvcYWuGTp2ILpHWc5OXx7gFaN9n1H2xKSndLRp6N8w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gNsNm7zZCcidMG0JRkB5Wg4yr+eWoVThem2hzOJWp2rIWpuLDEgQbuIR3SBbh5gQz a6SuEvQVIXIjZLhtWqTj1FY1pFWzHFH6fvfDNNpz+KTOjNupPnFnr3uCqNE336QxM1 R8maoW+pniHzeK7PUw47QS/OPIaqy0iV2BvFHxa4= From: Kieran Bingham Date: Tue, 07 Apr 2026 23:01:10 +0100 Subject: [PATCH 07/13] ipa: simple: Add lux algorithm to the SoftIPA MIME-Version: 1.0 Message-Id: <20260407-kbingham-awb-split-v1-7-a39af3f4dc20@ideasonboard.com> References: <20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com> In-Reply-To: <20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1775599360; l=5240; i=kieran.bingham@ideasonboard.com; s=20260204; h=from:subject:message-id; bh=ZAvcYWuGTp2ILpHWc5OXx7gFaN9n1H2xKSndLRp6N8w=; b=0Wa2cG+9ySiJ/oXn6dJAsufAMA2MJZSGg9F0nMRLbZ9Yaf8szKp1O3gcz0bYXalS1aTDSvfqf MOl2YliwjomDt4dfkajOGWmyUz8jcwIHwdQe4TLUlNjrsFfdFapAmZS X-Developer-Key: i=kieran.bingham@ideasonboard.com; a=ed25519; pk=IOxS2C6nWHNjLfkDR71Iesk904i6wJDfEERqV7hDBdY= 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" Utilise the lux component of libipa to map in the lux estimate process using the yHistgram of the Soft ISP statistics. Signed-off-by: Kieran Bingham --- src/ipa/simple/algorithms/lux.cpp | 93 +++++++++++++++++++++++++++++++++++ src/ipa/simple/algorithms/lux.h | 39 +++++++++++++++ src/ipa/simple/algorithms/meson.build | 1 + src/ipa/simple/ipa_context.h | 5 ++ 4 files changed, 138 insertions(+) diff --git a/src/ipa/simple/algorithms/lux.cpp b/src/ipa/simple/algorithms/lux.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03b44ac584ae141509e79954159272504cdba17d --- /dev/null +++ b/src/ipa/simple/algorithms/lux.cpp @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * + * Simple Lux control + */ + +#include "lux.h" + +#include + +#include + +#include "libipa/histogram.h" +#include "libipa/lux.h" + +/** + * \file lux.h + */ + +namespace libcamera { + +namespace ipa::soft::algorithms { + +/** + * \class Lux + * \brief SoftISP Lux control + * + * The Lux algorithm is responsible for estimating the lux level of the image. + * It doesn't take or generate any controls, but it provides a lux level for + * other algorithms (such as AGC) to use. + */ + +/** + * \brief Construct a SoftISP Lux algo module + */ +Lux::Lux() +{ +} + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Lux::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) +{ + return lux_.parseTuningData(tuningData); +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Lux::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + [[maybe_unused]] DebayerParams *params) +{ + frameContext.lux.lux = context.activeState.lux.lux; +} + +/** + * \copydoc libcamera::ipa::Algorithm::process + */ +void Lux::process(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const SwIspStats *stats, + ControlList &metadata) +{ + /* + * Report the lux level used by algorithms to prepare this frame + * not the lux level *of* this frame. + */ + metadata.set(controls::Lux, frameContext.lux.lux); + + if (!stats) + return; + + /* Todo: Sensor configuration should move out of AGC */ + utils::Duration exposureTime = context.configuration.agc.lineDuration * + frameContext.sensor.exposure; + double gain = frameContext.sensor.gain; + double digitalGain = 1.0; + + Histogram yHist(stats->yHistogram); + + context.activeState.lux.lux = + lux_.estimateLux(exposureTime, gain, digitalGain, yHist); +} + +REGISTER_IPA_ALGORITHM(Lux, "Lux") + +} /* namespace ipa::soft::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/lux.h b/src/ipa/simple/algorithms/lux.h new file mode 100644 index 0000000000000000000000000000000000000000..04ec4c163ede422369977017cca70d12a8d361fb --- /dev/null +++ b/src/ipa/simple/algorithms/lux.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * + * Simple Lux control + */ + +#pragma once + +#include + +#include "libipa/lux.h" + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::soft::algorithms { + +class Lux : public Algorithm +{ +public: + Lux(); + + int init(IPAContext &context, const YamlObject &tuningData) override; + void prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + DebayerParams *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const SwIspStats *stats, + ControlList &metadata) override; + +private: + ipa::Lux lux_; +}; + +} /* namespace ipa::soft::algorithms */ +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build index 73c63722083ff92147253c6b10440ce50743988d..27e73c9a0eea2241cc4a4cefd1594c976fb59318 100644 --- a/src/ipa/simple/algorithms/meson.build +++ b/src/ipa/simple/algorithms/meson.build @@ -6,4 +6,5 @@ soft_simple_ipa_algorithms = files([ 'agc.cpp', 'blc.cpp', 'ccm.cpp', + 'lux.cpp', ]) diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52..2bd7c4642b118d7bb94b1b16cdf4ede5fb2554b5 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -17,6 +17,7 @@ #include "libcamera/internal/vector.h" #include +#include #include "core_ipa_interface.h" @@ -36,6 +37,8 @@ struct IPASessionConfiguration { }; struct IPAActiveState { + ipa::lux::ActiveState lux; + struct { int32_t exposure; double again; @@ -64,6 +67,8 @@ struct IPAActiveState { }; struct IPAFrameContext : public FrameContext { + ipa::lux::FrameContext lux; + Matrix ccm; struct {