From patchwork Fri Sep 18 12:09:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 28354 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 85202C3362 for ; Fri, 18 Sep 2026 12:10:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 330EB68763; Fri, 18 Sep 2026 14:10:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="sEdj1vwc"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 61CAC6871C for ; Fri, 18 Sep 2026 14:09:57 +0200 (CEST) Received: from pb-laptop.local (185.221.142.0.nat.pool.zt.hu [185.221.142.0]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 83C6F4C2F; Fri, 18 Sep 2026 14:08:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789733294; bh=nq4hVfm5B2GsnIYRYCGN9CWm0kS+iEsWHsrCX/+O77E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sEdj1vwc9B8CQmeOahd0eS3u2BrsNThLsYam7VKITtaji2acxBABrEqY6O+b14T2Y cfsA4mVBz942/Z1o0P+tTAo7meOCdoeVw4xkS8sN+XC4k+qXe2mnmPSUt7LLlySbCu GMx8kBqMqrPeD40wRtv0hJM2A59i2dPweaAQXGnk= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi Subject: [PATCH v3 16/21] ipa: rppx1: lux: Add Date: Fri, 18 Sep 2026 14:09:44 +0200 Message-ID: <20260918120949.191668-17-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260918120949.191668-1-barnabas.pocze@ideasonboard.com> References: <20260918120949.191668-1-barnabas.pocze@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" From: Jacopo Mondi Add the algorithm to the rppx1 ipa module based on the corresponding algorithm in the rkisp1 ipa module. Signed-off-by: Jacopo Mondi --- src/ipa/rppx1/algorithms/agc.cpp | 1 + src/ipa/rppx1/algorithms/awb.cpp | 2 +- src/ipa/rppx1/algorithms/lux.cpp | 76 ++++++++++++++++++++++++++++ src/ipa/rppx1/algorithms/lux.h | 36 +++++++++++++ src/ipa/rppx1/algorithms/meson.build | 1 + src/ipa/rppx1/ipa_context.h | 8 +++ 6 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/ipa/rppx1/algorithms/lux.cpp create mode 100644 src/ipa/rppx1/algorithms/lux.h diff --git a/src/ipa/rppx1/algorithms/agc.cpp b/src/ipa/rppx1/algorithms/agc.cpp index fd782cea3d..b7b0506463 100644 --- a/src/ipa/rppx1/algorithms/agc.cpp +++ b/src/ipa/rppx1/algorithms/agc.cpp @@ -376,6 +376,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, }, .exposure = frameContext.sensor.exposure, .gain = frameContext.sensor.gain, + .lux = frameContext.lux.lux, }}, metadata); } else { agc_.process(context.configuration.agc, context.activeState.agc, frameContext.agc, {}, metadata); diff --git a/src/ipa/rppx1/algorithms/awb.cpp b/src/ipa/rppx1/algorithms/awb.cpp index 5e23b88146..fe7d64d77d 100644 --- a/src/ipa/rppx1/algorithms/awb.cpp +++ b/src/ipa/rppx1/algorithms/awb.cpp @@ -209,7 +209,7 @@ void Awb::process(IPAContext &context, RppX1AwbStats awbStats = calculateRgbMeans(frameContext, *awb); awbAlgo_.process(context.activeState.awb, frameContext.awb, awbStats, - 0, metadata); + frameContext.lux.lux, metadata); } RppX1AwbStats Awb::calculateRgbMeans(const IPAFrameContext &frameContext, diff --git a/src/ipa/rppx1/algorithms/lux.cpp b/src/ipa/rppx1/algorithms/lux.cpp new file mode 100644 index 0000000000..41ae8e1ab6 --- /dev/null +++ b/src/ipa/rppx1/algorithms/lux.cpp @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Ideas On Board + * + * RPP-X1 Lux estimation + */ + +#include "lux.h" + +#include + +#include + +#include "libipa/histogram.h" +#include "libipa/lux.h" + +/** + * \file lux.h + */ + +namespace libcamera { + +namespace ipa::rppx1::algorithms { + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Lux::init([[maybe_unused]] IPAContext &context, const ValueNode &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]] RppX1Params *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 RppX1Stats *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); + + utils::Duration exposureTime = context.configuration.agc.lineDuration * + frameContext.sensor.exposure; + double gain = frameContext.sensor.gain; + + /* \todo Deduplicate the histogram calculation from AGC */ + const auto histPost = stats->block(); + if (!histPost) + return; + + Histogram yHist(histPost->hist_bins, [](uint32_t x) { return x >> 4; }); + + context.activeState.lux.lux = lux_.estimateLux(exposureTime, gain, 1.0, yHist); +} + +REGISTER_IPA_ALGORITHM(Lux, "Lux") + +} /* namespace ipa::rppx1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rppx1/algorithms/lux.h b/src/ipa/rppx1/algorithms/lux.h new file mode 100644 index 0000000000..e38835be2b --- /dev/null +++ b/src/ipa/rppx1/algorithms/lux.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Ideas On Board + * + * RPP-X1 Lux estimation + */ + +#pragma once + +#include "libipa/lux.h" + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::rppx1::algorithms { + +class Lux : public Algorithm +{ +public: + int init(IPAContext &context, const ValueNode &tuningData) override; + void prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + RppX1Params *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const RppX1Stats *stats, + ControlList &metadata) override; + +private: + ipa::Lux lux_; +}; + +} /* namespace ipa::rppx1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rppx1/algorithms/meson.build b/src/ipa/rppx1/algorithms/meson.build index 4a2c1b52dd..19688854a3 100644 --- a/src/ipa/rppx1/algorithms/meson.build +++ b/src/ipa/rppx1/algorithms/meson.build @@ -4,4 +4,5 @@ rppx1_ipa_algorithms = files([ 'agc.cpp', 'awb.cpp', 'blc.cpp', + 'lux.cpp', ]) diff --git a/src/ipa/rppx1/ipa_context.h b/src/ipa/rppx1/ipa_context.h index 24fbbfaa28..9dfc67f252 100644 --- a/src/ipa/rppx1/ipa_context.h +++ b/src/ipa/rppx1/ipa_context.h @@ -42,6 +42,10 @@ struct IPAActiveState { } agc; ipa::awb::ActiveState awb; + + struct { + double lux; + } lux; }; struct IPAFrameContext : public FrameContext { @@ -56,6 +60,10 @@ struct IPAFrameContext : public FrameContext { } agc; ipa::awb::FrameContext awb; + + struct { + double lux; + } lux; }; struct IPAContext {