From patchwork Mon Mar 28 09:24:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 15564 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 6ECF6C3256 for ; Mon, 28 Mar 2022 09:24:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 937796563A; Mon, 28 Mar 2022 11:24:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1648459483; bh=NhCazlqMoha0m10Fd7/+krMZZzST5W4Cn1YefZ60kgA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=RsGPESc1WIhTJkTw87K2h6uS5o+r7u0qOXAU25zVHyVKWKwYxGYnowoDltKcgnnX7 8xjqdY/oxu68wz9R1CNDo6jW9v2OVZdw594yOhxPgT3yAbr6OAM+BLq23zAXv5uORI IZCY7izp5k0MJlEa5H7fUQ5M7I9R2+b7W2JAGpFD1eDi2fCXyA8h38m34V6INFzxkS YIHpzY/tvXpWC9fviYMDLZGHrePjZ3Ta+giAo3cyXJbF/yiemXKsnDVevLNPsi0h3h Eq8wIKG7MeuzJntSJMMIbjTynGRq9E73Lnzq76O3LlgHC0moUcgFirIPmMma9SSqxy OjfkE3qHsAf4A== 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 EE550604BF for ; Mon, 28 Mar 2022 11:24:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="jAiPKUoR"; dkim-atps=neutral Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:4f49:c672:4655:7dbb]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 669FFB9C; Mon, 28 Mar 2022 11:24:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1648459481; bh=NhCazlqMoha0m10Fd7/+krMZZzST5W4Cn1YefZ60kgA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jAiPKUoRCwGRPy2V428wHI53Tokqb0MffKbN8Hbg0mfbAo90MDKp23H7s/wCO6HAS G2bTd+90K4o0VS5xBXPBPk8qXvSHwIcZAxeBXxh9qXDHdnFDI2dmac7WtDfiUz1NZ9 NDQkjsVT5CwclWCHjJ0oZDNZGco5gMJbvEBGP0lc= To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Mar 2022 11:24:29 +0200 Message-Id: <20220328092433.69856-2-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> References: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 1/5] ipa: rkisp1: Use frame counter for the request queued 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: , X-Patchwork-Original-From: Jean-Michel Hautbois via libcamera-devel From: Jean-Michel Hautbois Reply-To: Jean-Michel Hautbois Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Introduce a frameCount variable in the IPAFrameContext which increments each time a request is queued. It is reset at configure call, when the camera is started. This will allow the frameCount to be used by other algorithms, without having to keep multiple private frame counters. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Umang Jain Reviewed-by: Laurent Pinchart --- src/ipa/rkisp1/ipa_context.cpp | 11 ++++++++++- src/ipa/rkisp1/ipa_context.h | 4 +++- src/ipa/rkisp1/rkisp1.cpp | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 9cb2a9fd..c22e02d5 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2021, Ideas On Board + * Copyright (C) 2021-2022, Ideas On Board * * ipa_context.cpp - RkISP1 IPA Context */ @@ -113,4 +113,13 @@ namespace libcamera::ipa::rkisp1 { * \brief Analogue gain multiplier */ +/** + * \var IPAFrameContext::frameCount + * \brief Counter of requests queued to the IPA module + * + * The counter is reset to 0 when the IPA module is configured, and is + * incremented for each request being queued, after calling the + * Algorithm::prepare() function of all algorithms. + */ + } /* namespace libcamera::ipa::rkisp1 */ diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index b94ade0c..212fa052 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2021, Ideas On Board + * Copyright (C) 2021-2022, Ideas On Board * * ipa_context.h - RkISP1 IPA Context * @@ -43,6 +43,8 @@ struct IPAFrameContext { uint32_t exposure; double gain; } sensor; + + unsigned int frameCount; }; struct IPAContext { diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 2225a84d..493811d9 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -190,6 +190,8 @@ int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info, context_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain); context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain); + context_.frameContext.frameCount = 0; + for (auto const &algo : algorithms_) { int ret = algo->configure(context_, info); if (ret) @@ -243,6 +245,7 @@ void IPARkISP1::queueRequest(const uint32_t frame, const uint32_t bufferId, algo->prepare(context_, params); paramsBufferReady.emit(frame); + context_.frameContext.frameCount++; } void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId, From patchwork Mon Mar 28 09:24:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 15565 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 11E82C3265 for ; Mon, 28 Mar 2022 09:24:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EE35465637; Mon, 28 Mar 2022 11:24:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1648459483; bh=UwVmOCPbIGlpJyWAKcp8WXSU74Dwkh6Bx/98nnUbxrs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=1AZx2VS5Etd1RXB//cAvjfeXo5SX8r0e0/4JqivdF7Eop5D+oDUspb3d3xRjTmW6j lsCQJtdOKoIJMhPd3n4jp1Nw/TfWYdtsspqWeoKwNppxyAZpzMxvnfMRz4CLzSISCy AzAGLliM/uq9nw8FgxyqTLoLVNTWlXvYdeZI8UrSU/YixlPm/LVXAhVksETCEkJ9Rz i+0yTA6lRQzjQU+yuVRcbpGG/AGFxxwRNZ4ZzrGwNwI15P9ZVo9NUg5YY+5vW2e/c8 caw6KdRoCsqIuVxQHIJOBZj5NrCCU3rx/SRuhHSsFC5m5/hOj0joJMx7BvOWXj7Fgw /94Hhtep+3xgA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 33603633A7 for ; Mon, 28 Mar 2022 11:24:42 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="c6d3euPw"; dkim-atps=neutral Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:4f49:c672:4655:7dbb]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A10F39BC; Mon, 28 Mar 2022 11:24:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1648459481; bh=UwVmOCPbIGlpJyWAKcp8WXSU74Dwkh6Bx/98nnUbxrs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c6d3euPwzrLd492Izz52sR/mzyNXhcNAd4UFZQkqm9/Bn+41rUYrJ1TlDEoWTEiMw /92z5aWz34qxLDVQiLEKzA+W3K4M61sj5giSvHpg8wk3QMJdTdOUJIHNlGpVplMj5K 6JUZjl3bWYCKZpfhDoSLavaBXd/qlJwnS26UTZVc= To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Mar 2022 11:24:30 +0200 Message-Id: <20220328092433.69856-3-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> References: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 2/5] ipa: rkisp1: Introduce Black Level Correction 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: , X-Patchwork-Original-From: Jean-Michel Hautbois via libcamera-devel From: Jean-Michel Hautbois Reply-To: Jean-Michel Hautbois Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In order to have the proper pixel levels, apply a fixed black level correction, based on the imx219 tuning file in RPi. The value is 4096 on 16 bits, and the pipeline for RkISP1 is on 12 bits, scale it. Signed-off-by: Jean-Michel Hautbois Tested-by: Peter Griffin Reviewed-by: Laurent Pinchart --- src/ipa/rkisp1/algorithms/blc.cpp | 57 +++++++++++++++++++++++++++ src/ipa/rkisp1/algorithms/blc.h | 30 ++++++++++++++ src/ipa/rkisp1/algorithms/meson.build | 1 + src/ipa/rkisp1/rkisp1.cpp | 2 + 4 files changed, 90 insertions(+) create mode 100644 src/ipa/rkisp1/algorithms/blc.cpp create mode 100644 src/ipa/rkisp1/algorithms/blc.h diff --git a/src/ipa/rkisp1/algorithms/blc.cpp b/src/ipa/rkisp1/algorithms/blc.cpp new file mode 100644 index 00000000..0c5948ff --- /dev/null +++ b/src/ipa/rkisp1/algorithms/blc.cpp @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021-2022, Ideas On Board + * + * blc.cpp - RkISP1 Black Level Correction control + */ + +#include "blc.h" + +/** + * \file blc.h + */ + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +/** + * \class BlackLevelCorrection + * \brief RkISP1 Black Level Correction control + * + * The pixels output by the camera normally include a black level, because + * sensors do not always report a signal level of '0' for black. Pixels at or + * below this level should be considered black. To achieve that, the RkISP BLC + * algorithm subtracts a configurable offset from all pixels. + * + * The black level can be measured at runtime from an optical dark region of the + * camera sensor, or measured during the camera tuning process. The first option + * isn't currently supported. + */ + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void BlackLevelCorrection::prepare(IPAContext &context, + rkisp1_params_cfg *params) +{ + if (context.frameContext.frameCount > 0) + return; + /* + * Substract fixed values taken from imx219 tuning file. + * \todo Use a configuration file for it ? + */ + params->others.bls_config.enable_auto = 0; + params->others.bls_config.fixed_val.r = 256; + params->others.bls_config.fixed_val.gr = 256; + params->others.bls_config.fixed_val.gb = 256; + params->others.bls_config.fixed_val.b = 256; + + params->module_en_update |= RKISP1_CIF_ISP_MODULE_BLS; + params->module_ens |= RKISP1_CIF_ISP_MODULE_BLS; + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_BLS; +} + +} /* namespace ipa::rkisp1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/blc.h b/src/ipa/rkisp1/algorithms/blc.h new file mode 100644 index 00000000..69874d8f --- /dev/null +++ b/src/ipa/rkisp1/algorithms/blc.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021-2022, Ideas On Board + * + * blc.h - RkISP1 Black Level Correction control + */ + +#pragma once + +#include + +#include "algorithm.h" + +namespace libcamera { + +struct IPACameraSensorInfo; + +namespace ipa::rkisp1::algorithms { + +class BlackLevelCorrection : public Algorithm +{ +public: + BlackLevelCorrection() = default; + ~BlackLevelCorrection() = default; + + void prepare(IPAContext &context, rkisp1_params_cfg *params) override; +}; + +} /* namespace ipa::rkisp1::algorithms */ +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build index a19c1a4f..27c97731 100644 --- a/src/ipa/rkisp1/algorithms/meson.build +++ b/src/ipa/rkisp1/algorithms/meson.build @@ -2,4 +2,5 @@ rkisp1_ipa_algorithms = files([ 'agc.cpp', + 'blc.cpp', ]) diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 493811d9..83ed21be 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -27,6 +27,7 @@ #include "algorithms/agc.h" #include "algorithms/algorithm.h" +#include "algorithms/blc.h" #include "libipa/camera_sensor_helper.h" #include "ipa_context.h" @@ -120,6 +121,7 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision) /* Construct our Algorithms */ algorithms_.push_back(std::make_unique()); + algorithms_.push_back(std::make_unique()); return 0; } From patchwork Mon Mar 28 09:24:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 15566 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 9C8CAC3266 for ; Mon, 28 Mar 2022 09:24:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4D9DE65640; Mon, 28 Mar 2022 11:24:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1648459486; bh=2HJTGIzy9CsO2/V/VvT4biuOy1qQF6ZkFGXJMTw/Myw=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=HfI8VUbpLIE4MtKfv2UebHTAtKBNikAvcVgcSZAHX/U1h6aYPyjZje+CFRqFYN4/J phnGK/RPMZXvOIEc8Q1M6RpOENdnSCq0Y1fsbm678WrpBsmU06UoNCJ6fP4onJDqFM EWrhW3CnDib5jMsgTKQtIgN0mu8mMSWQJ85LFhx0hQczJEVxAs0s+rISMc7ZVNH+MS I9BnT7MS0a0hzF2p8YlPM6WMXvPdG7ynEbVEEOlixNA7lRdNjO2cB2ngJP4ZJW8+EX q4mFcc6Htvg8oXQY3vjRGtshOLUd65LC8QQpn8Qtn4qiJp+u3fTPxzTSo6EQG86J2n OWPInpPPyE/tg== 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 78E3A65633 for ; Mon, 28 Mar 2022 11:24:42 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oVPXykPx"; dkim-atps=neutral Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:4f49:c672:4655:7dbb]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DAE28E0A; Mon, 28 Mar 2022 11:24:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1648459482; bh=2HJTGIzy9CsO2/V/VvT4biuOy1qQF6ZkFGXJMTw/Myw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oVPXykPxmCF/NyHheEmci8/VHopV5QijU9n6Qols4ioMhh+RfI8l7KINEhTSAdEs8 olXQe8yXrUW2PG0M2yt1yC8MeGx0MQqBCv4WCZaJ2V3/QpjdxizVrmceM321oZAf3d jAFejCMwpDjYXdCD5JjRd6f3Jhktj4fkIXSJIHnQ= To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Mar 2022 11:24:31 +0200 Message-Id: <20220328092433.69856-4-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> References: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 3/5] ipa: libipa: Histogram: Constify the constructor span 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: , X-Patchwork-Original-From: Jean-Michel Hautbois via libcamera-devel From: Jean-Michel Hautbois Reply-To: Jean-Michel Hautbois Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The Histogram constructor does not modify the data. Pass it a Span instead of a Span. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Umang Jain Reviewed-by: Laurent Pinchart --- src/ipa/libipa/histogram.cpp | 2 +- src/ipa/libipa/histogram.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ipa/libipa/histogram.cpp b/src/ipa/libipa/histogram.cpp index 4d94571f..d8ad1c89 100644 --- a/src/ipa/libipa/histogram.cpp +++ b/src/ipa/libipa/histogram.cpp @@ -32,7 +32,7 @@ namespace ipa { * \brief Create a cumulative histogram * \param[in] data A pre-sorted histogram to be passed */ -Histogram::Histogram(Span data) +Histogram::Histogram(Span data) { cumulative_.reserve(data.size()); cumulative_.push_back(0); diff --git a/src/ipa/libipa/histogram.h b/src/ipa/libipa/histogram.h index c40a366b..164d4603 100644 --- a/src/ipa/libipa/histogram.h +++ b/src/ipa/libipa/histogram.h @@ -22,7 +22,7 @@ namespace ipa { class Histogram { public: - Histogram(Span data); + Histogram(Span data); size_t bins() const { return cumulative_.size() - 1; } uint64_t total() const { return cumulative_[cumulative_.size() - 1]; } uint64_t cumulativeFrequency(double bin) const; From patchwork Mon Mar 28 09:24:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 15567 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 05224C3256 for ; Mon, 28 Mar 2022 09:24:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A7A05633A7; Mon, 28 Mar 2022 11:24:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1648459486; bh=NcLm8fC4D0mA9radASJmFrgLLjerz7RKcbEGUxkQWrc=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=WRta/P/0I4ZoeLutuNyoxuS061G8c3R/u1DmloLBBVDkb8Lukkc9xDCYE2iOJfVME AGvyzB/JYa/w2CGntEr28FlquLot02pBsViaHVZF0+rzAMnBR3K8MpWgXfYMgnPvYe jJAHkzf8PL4p1i7et5pH0a+dT08Ur3GPAiOBY4hf1lztSjJ+Ve+hg9WT0sOQWuGTeU 2AKdQraWMSUhal5KWs8mXsxjSO6tSrab7Uu2nOC1JNShEAHyQID4udUwuvooaRMttP j6o8xV+gNiVoti2+HVOLejegr51TNUVcaQB5JKV+Vow7ELeRpKUwtmVzxBcPMpIJ3K PXe15ZJFcT/EA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A408C633A7 for ; Mon, 28 Mar 2022 11:24:42 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="V0ikdZCE"; dkim-atps=neutral Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:4f49:c672:4655:7dbb]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1F002E27; Mon, 28 Mar 2022 11:24:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1648459482; bh=NcLm8fC4D0mA9radASJmFrgLLjerz7RKcbEGUxkQWrc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V0ikdZCEFfomRn5gjSnxs3/XrssAKOaXux3SazzF+fsFOFQJxBBcojrHynf/gtT0u XwfHpozo8siJU3u2igtFCrwfNoeUeqCW6QggFDZO30D5D2RCVa6wWEnPtX7mc3TfQm z2jB7tz9+FrgErZ9wNhqUfX2EDdZEKHAXsW26cck= To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Mar 2022 11:24:32 +0200 Message-Id: <20220328092433.69856-5-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> References: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 4/5] ipa: rkisp1: agc: Add a histogram-based gain 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: , X-Patchwork-Original-From: Jean-Michel Hautbois via libcamera-devel From: Jean-Michel Hautbois Reply-To: Jean-Michel Hautbois Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" As for the IPU3, we can estimate the histogram of the luminance. The RkISP1 can estimate multiple ones, the R, G and B ones, the Y only one and a combination of RGB. The one we are interested by in AGC is the Y histogram. Use the hardware revision to determine the number of bins of the produced histogram. Signed-off-by: Jean-Michel Hautbois Tested-by: Peter Griffin Reviewed-by: Laurent Pinchart --- src/ipa/rkisp1/algorithms/agc.cpp | 91 ++++++++++++++++++++++++++----- src/ipa/rkisp1/algorithms/agc.h | 6 +- src/ipa/rkisp1/ipa_context.cpp | 3 + src/ipa/rkisp1/ipa_context.h | 1 + 4 files changed, 86 insertions(+), 15 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index dd97afc0..5f4c3f93 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2021, Ideas On Board + * Copyright (C) 2021-2022, Ideas On Board * * agc.cpp - AGC/AEC mean-based control algorithm */ @@ -16,6 +16,8 @@ #include +#include "libipa/histogram.h" + /** * \file agc.h */ @@ -43,6 +45,9 @@ static constexpr utils::Duration kMaxShutterSpeed = 60ms; /* Number of frames to wait before calculating stats on minimum exposure */ static constexpr uint32_t kNumStartupFrames = 10; +/* Target value to reach for the top 2% of the histogram */ +static constexpr double kEvGainTarget = 0.5; + /* * Relative luminance target. * @@ -54,7 +59,7 @@ static constexpr uint32_t kNumStartupFrames = 10; static constexpr double kRelativeLuminanceTarget = 0.4; Agc::Agc() - : frameCount_(0), numCells_(0), filteredExposure_(0s) + : frameCount_(0), numCells_(0), numHistBins_(0), filteredExposure_(0s) { } @@ -65,8 +70,7 @@ Agc::Agc() * * \return 0 */ -int Agc::configure(IPAContext &context, - [[maybe_unused]] const IPACameraSensorInfo &configInfo) +int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) { /* Configure the default exposure and gain. */ context.frameContext.agc.gain = std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain); @@ -77,10 +81,22 @@ int Agc::configure(IPAContext &context, * - versions < V12 have RKISP1_CIF_ISP_AE_MEAN_MAX_V10 entries, * - versions >= V12 have RKISP1_CIF_ISP_AE_MEAN_MAX_V12 entries. */ - if (context.configuration.hw.revision < RKISP1_V12) + if (context.configuration.hw.revision < RKISP1_V12) { numCells_ = RKISP1_CIF_ISP_AE_MEAN_MAX_V10; - else + numHistBins_ = RKISP1_CIF_ISP_HIST_BIN_N_MAX_V10; + } else { numCells_ = RKISP1_CIF_ISP_AE_MEAN_MAX_V12; + numHistBins_ = RKISP1_CIF_ISP_HIST_BIN_N_MAX_V12; + } + + /* + * Define the measurement window for AGC as a centered rectangle + * covering 3/4 of the image width and height. + */ + context.configuration.agc.measureWindow.h_offs = configInfo.outputSize.width / 8; + context.configuration.agc.measureWindow.v_offs = configInfo.outputSize.height / 8; + context.configuration.agc.measureWindow.h_size = 3 * configInfo.outputSize.width / 4; + context.configuration.agc.measureWindow.v_size = 3 * configInfo.outputSize.height / 4; /* \todo Use actual frame index by populating it in the frameContext. */ frameCount_ = 0; @@ -126,8 +142,9 @@ utils::Duration Agc::filterExposure(utils::Duration exposureValue) * \brief Estimate the new exposure and gain values * \param[inout] frameContext The shared IPA frame Context * \param[in] yGain The gain calculated on the current brightness level + * \param[in] iqMeanGain The gain calculated based on the relative luminance target */ -void Agc::computeExposure(IPAContext &context, double yGain) +void Agc::computeExposure(IPAContext &context, double yGain, double iqMeanGain) { IPASessionConfiguration &configuration = context.configuration; IPAFrameContext &frameContext = context.frameContext; @@ -136,6 +153,9 @@ void Agc::computeExposure(IPAContext &context, double yGain) uint32_t exposure = frameContext.sensor.exposure; double analogueGain = frameContext.sensor.gain; + /* Use the highest of the two gain estimates. */ + double evGain = std::max(yGain, iqMeanGain); + utils::Duration minShutterSpeed = configuration.agc.minShutterSpeed; utils::Duration maxShutterSpeed = std::min(configuration.agc.maxShutterSpeed, kMaxShutterSpeed); @@ -146,7 +166,7 @@ void Agc::computeExposure(IPAContext &context, double yGain) kMaxAnalogueGain); /* Consider within 1% of the target as correctly exposed. */ - if (utils::abs_diff(yGain, 1.0) < 0.01) + if (utils::abs_diff(evGain, 1.0) < 0.01) return; /* extracted from Rpi::Agc::computeTargetExposure. */ @@ -163,13 +183,13 @@ void Agc::computeExposure(IPAContext &context, double yGain) LOG(RkISP1Agc, Debug) << "Actual total exposure " << currentShutter * analogueGain << " Shutter speed " << currentShutter << " Gain " << analogueGain - << " Needed ev gain " << yGain; + << " Needed ev gain " << evGain; /* * Calculate the current exposure value for the scene as the latest * exposure value applied multiplied by the new estimated gain. */ - utils::Duration exposureValue = effectiveExposureValue * yGain; + utils::Duration exposureValue = effectiveExposureValue * evGain; /* Clamp the exposure value to the min and max authorized. */ utils::Duration maxTotalExposure = maxShutterSpeed * maxAnalogueGain; @@ -240,6 +260,18 @@ double Agc::estimateLuminance(const rkisp1_cif_isp_ae_stat *ae, return ySum / numCells_ / 255; } +/** + * \brief Estimate the mean value of the top 2% of the histogram + * \param[in] hist The histogram statistics computed by the ImgU + * \return The mean value of the top 2% of the histogram + */ +double Agc::measureBrightness(const rkisp1_cif_isp_hist_stat *hist) const +{ + Histogram histogram{ Span(hist->hist_bins, numHistBins_) }; + /* Estimate the quantile mean of the top 2% of the histogram. */ + return histogram.interQuantileMean(0.98, 1.0); +} + /** * \brief Process RkISP1 statistics, and run AGC operations * \param[in] context The shared IPA context @@ -254,6 +286,10 @@ void Agc::process(IPAContext &context, const rkisp1_stat_buffer *stats) ASSERT(stats->meas_type & RKISP1_CIF_ISP_STAT_AUTOEXP); const rkisp1_cif_isp_ae_stat *ae = ¶ms->ae; + const rkisp1_cif_isp_hist_stat *hist = ¶ms->hist; + + double iqMean = measureBrightness(hist); + double iqMeanGain = kEvGainTarget * numHistBins_ / iqMean; /* * Estimate the gain needed to achieve a relative luminance target. To @@ -277,15 +313,44 @@ void Agc::process(IPAContext &context, const rkisp1_stat_buffer *stats) break; } - computeExposure(context, yGain); + computeExposure(context, yGain, iqMeanGain); frameCount_++; } -void Agc::prepare([[maybe_unused]] IPAContext &context, - rkisp1_params_cfg *params) +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Agc::prepare(IPAContext &context, rkisp1_params_cfg *params) { + if (context.frameContext.frameCount > 0) + return; + + /* Configure the measurement window. */ + params->meas.aec_config.meas_window = context.configuration.agc.measureWindow; + /* Use a continuous method for measure. */ + params->meas.aec_config.autostop = RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0; + /* Estimate Y as (R + G + B) x (85/256). */ + params->meas.aec_config.mode = RKISP1_CIF_ISP_EXP_MEASURING_MODE_1; + + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AEC; params->module_ens |= RKISP1_CIF_ISP_MODULE_AEC; params->module_en_update |= RKISP1_CIF_ISP_MODULE_AEC; + + /* Configure histogram. */ + params->meas.hst_config.meas_window = context.configuration.agc.measureWindow; + /* Produce the luminance histogram. */ + params->meas.hst_config.mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM; + /* Set an average weighted histogram. */ + for (unsigned int histBin = 0; histBin < numHistBins_; histBin++) + params->meas.hst_config.hist_weight[histBin] = 1; + /* Step size can't be less than 3. */ + params->meas.hst_config.histogram_predivider = 4; + + /* Update the configuration for histogram. */ + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_HST; + /* Enable the histogram measure unit. */ + params->module_ens |= RKISP1_CIF_ISP_MODULE_HST; + params->module_en_update |= RKISP1_CIF_ISP_MODULE_HST; } } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h index 942c9d7a..ce1adf27 100644 --- a/src/ipa/rkisp1/algorithms/agc.h +++ b/src/ipa/rkisp1/algorithms/agc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2021, Ideas On Board + * Copyright (C) 2021-2022, Ideas On Board * * agc.h - RkISP1 AGC/AEC mean-based control algorithm */ @@ -32,13 +32,15 @@ public: void process(IPAContext &context, const rkisp1_stat_buffer *stats) override; private: - void computeExposure(IPAContext &Context, double yGain); + void computeExposure(IPAContext &Context, double yGain, double iqMeanGain); utils::Duration filterExposure(utils::Duration exposureValue); double estimateLuminance(const rkisp1_cif_isp_ae_stat *ae, double gain); + double measureBrightness(const rkisp1_cif_isp_hist_stat *hist) const; uint64_t frameCount_; uint32_t numCells_; + uint32_t numHistBins_; utils::Duration filteredExposure_; }; diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index c22e02d5..4a1ab058 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -71,6 +71,9 @@ namespace libcamera::ipa::rkisp1 { * \var IPASessionConfiguration::agc.maxAnalogueGain * \brief Maximum analogue gain supported with the configured sensor * + * \var IPASessionConfiguration::agc.measureWindow + * \brief AGC measure window + * * \var IPASessionConfiguration::hw * \brief RkISP1-specific hardware information * diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 212fa052..35e9b8e5 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -22,6 +22,7 @@ struct IPASessionConfiguration { utils::Duration maxShutterSpeed; double minAnalogueGain; double maxAnalogueGain; + struct rkisp1_cif_isp_window measureWindow; } agc; struct { From patchwork Mon Mar 28 09:24:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 15568 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 6E8CFC3267 for ; Mon, 28 Mar 2022 09:24:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1E16C65633; Mon, 28 Mar 2022 11:24:47 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1648459487; bh=nQ0ceSe4JXN8Fh7yx01fAZsg5TftRn7EsPWbb1iZ0kM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=xmeW3ZAyNa+w9knpaoW3zc5uMM6vc1aj5felZsvlawphiPLxbmOxZyZg9fObQLWU3 tPS9YHYEEvzr9LxpsYhd+4wpfh/E7nQALT2Hf5D0Ma3GQyGBohVgYw9vjcPeUM1boK +qft7JwYc7SRRSLr3lGLCGBVUL/fOxYr1mba1lz33EBPV5DdRkpn46ugVjhoH38tuF uHsN5d6xlubsUfyNT/Mq+HwIs6crAHgczRIoR5cxlxkDDKHKbU7d5dgK15NBFg3opT 67SOceQhiLN+ZsLifuLb7RGbtl4j/viFER3VV4SAzpoIs52z8g73VQn9eH9L/alzg+ YAQtApjyoPMuw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DF3BF65634 for ; Mon, 28 Mar 2022 11:24:42 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="qhpf/7d9"; dkim-atps=neutral Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:4f49:c672:4655:7dbb]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5797CB9C; Mon, 28 Mar 2022 11:24:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1648459482; bh=nQ0ceSe4JXN8Fh7yx01fAZsg5TftRn7EsPWbb1iZ0kM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qhpf/7d9KLBbqFkIax+JdMghk+Fx+P1C7+gJfXYtx+dD4zlNCRFDyJzmkDI53C/gO SFOuqV3HMwklyZkuxY8du5wIPvwg89zbZ6wr8OSKTEHJSrNPzwziyrEMYkIOx8iKeg 0bPwRp/lkSlOwoYNlgc1ae7TOmM+KxESs0l7rVxg= To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Mar 2022 11:24:33 +0200 Message-Id: <20220328092433.69856-6-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> References: <20220328092433.69856-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 5/5] ipa: rkisp1: Introduce AWB 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: , X-Patchwork-Original-From: Jean-Michel Hautbois via libcamera-devel From: Jean-Michel Hautbois Reply-To: Jean-Michel Hautbois Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The RkISP1 ISP calculates a mean value for Y, Cr and Cb at each frame. There is a RGB mode which could theoretically give us the values for R, G and B directly, but it seems to be failing right now. Convert those values into R, G and B and estimate the gain to apply in a grey world. Signed-off-by: Jean-Michel Hautbois Tested-by: Peter Griffin Reviewed-by: Laurent Pinchart --- v4: - swapped blue and green :-( - saturate after filtering - introduce a speed variable for filtering --- src/ipa/rkisp1/algorithms/awb.cpp | 178 ++++++++++++++++++++++++++ src/ipa/rkisp1/algorithms/awb.h | 33 +++++ src/ipa/rkisp1/algorithms/meson.build | 1 + src/ipa/rkisp1/ipa_context.cpp | 28 ++++ src/ipa/rkisp1/ipa_context.h | 16 +++ src/ipa/rkisp1/rkisp1.cpp | 2 + 6 files changed, 258 insertions(+) create mode 100644 src/ipa/rkisp1/algorithms/awb.cpp create mode 100644 src/ipa/rkisp1/algorithms/awb.h diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp new file mode 100644 index 00000000..be4585c6 --- /dev/null +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021-2022, Ideas On Board + * + * awb.cpp - AWB control algorithm + */ + +#include "awb.h" + +#include +#include + +#include + +#include + +/** + * \file awb.h + */ + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +/** + * \class Awb + * \brief A Grey world white balance correction algorithm + */ + +LOG_DEFINE_CATEGORY(RkISP1Awb) + +/** + * \copydoc libcamera::ipa::Algorithm::configure + */ +int Awb::configure(IPAContext &context, + const IPACameraSensorInfo &configInfo) +{ + context.frameContext.awb.gains.red = 1.0; + context.frameContext.awb.gains.blue = 1.0; + context.frameContext.awb.gains.green = 1.0; + + /* + * Define the measurement window for AWB as a centered rectangle + * covering 3/4 of the image width and height. + */ + context.configuration.awb.measureWindow.h_offs = configInfo.outputSize.width / 8; + context.configuration.awb.measureWindow.v_offs = configInfo.outputSize.height / 8; + context.configuration.awb.measureWindow.h_size = 3 * configInfo.outputSize.width / 4; + context.configuration.awb.measureWindow.v_size = 3 * configInfo.outputSize.height / 4; + + return 0; +} + +uint32_t Awb::estimateCCT(double red, double green, double blue) +{ + /* Convert the RGB values to CIE tristimulus values (XYZ) */ + double X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue); + double Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue); + double Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue); + + /* Calculate the normalized chromaticity values */ + double x = X / (X + Y + Z); + double y = Y / (X + Y + Z); + + /* Calculate CCT */ + double n = (x - 0.3320) / (0.1858 - y); + return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33; +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Awb::prepare(IPAContext &context, rkisp1_params_cfg *params) +{ + params->others.awb_gain_config.gain_green_b = 256 * context.frameContext.awb.gains.green; + params->others.awb_gain_config.gain_blue = 256 * context.frameContext.awb.gains.blue; + params->others.awb_gain_config.gain_red = 256 * context.frameContext.awb.gains.red; + params->others.awb_gain_config.gain_green_r = 256 * context.frameContext.awb.gains.green; + + /* Update the gains. */ + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN; + + /* If we already have configured the gains and window, return. */ + if (context.frameContext.frameCount > 0) + return; + + /* Configure the gains to apply. */ + params->module_en_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN; + /* Update the ISP to apply the gains configured. */ + params->module_ens |= RKISP1_CIF_ISP_MODULE_AWB_GAIN; + + /* Configure the measure window for AWB. */ + params->meas.awb_meas_config.awb_wnd = context.configuration.awb.measureWindow; + /* + * Measure Y, Cr and Cb means. + * \todo RGB is not working, the kernel seems to not configure it ? + */ + params->meas.awb_meas_config.awb_mode = RKISP1_CIF_ISP_AWB_MODE_YCBCR; + /* Reference Cr and Cb. */ + params->meas.awb_meas_config.awb_ref_cb = 128; + params->meas.awb_meas_config.awb_ref_cr = 128; + /* Y values to include are between min_y and max_y only. */ + params->meas.awb_meas_config.min_y = 16; + params->meas.awb_meas_config.max_y = 250; + /* Maximum Cr+Cb value to take into account for awb. */ + params->meas.awb_meas_config.max_csum = 250; + /* Minimum Cr and Cb values to take into account. */ + params->meas.awb_meas_config.min_c = 16; + /* Number of frames to use to estimate the mean (0 means 1 frame). */ + params->meas.awb_meas_config.frames = 0; + + /* Update AWB measurement unit configuration. */ + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AWB; + /* Make sure the ISP is measuring the means for the next frame. */ + params->module_en_update |= RKISP1_CIF_ISP_MODULE_AWB; + params->module_ens |= RKISP1_CIF_ISP_MODULE_AWB; +} + +/** + * \copydoc libcamera::ipa::Algorithm::process + */ +void Awb::process([[maybe_unused]] IPAContext &context, const rkisp1_stat_buffer *stats) +{ + const rkisp1_cif_isp_stat *params = &stats->params; + const rkisp1_cif_isp_awb_stat *awb = ¶ms->awb; + IPAFrameContext &frameContext = context.frameContext; + + /* Get the YCbCr mean values */ + double yMean = awb->awb_mean[0].mean_y_or_g; + double crMean = awb->awb_mean[0].mean_cr_or_r; + double cbMean = awb->awb_mean[0].mean_cb_or_b; + + /* + * Convert from YCbCr to RGB. + * The hardware uses the following formulas: + * Y = 16 + 0.2500 R + 0.5000 G + 0.1094 B + * Cb = 128 - 0.1406 R - 0.2969 G + 0.4375 B + * Cr = 128 + 0.4375 R - 0.3750 G - 0.0625 B + * + * The inverse matrix is thus: + * [[1,1636, -0,0623, 1,6008] + * [1,1636, -0,4045, -0,7949] + * [1,1636, 1,9912, -0,0250]] + */ + yMean -= 16; + cbMean -= 128; + crMean -= 128; + double redMean = 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean; + double greenMean = 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean; + double blueMean = 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean; + + /* Estimate the red and blue gains to apply in a grey world. */ + double redGain = greenMean / (redMean + 1); + double blueGain = greenMean / (blueMean + 1); + + /* Filter the values to avoid oscillations. */ + double speed = 0.2; + redGain = speed * redGain + (1 - speed) * frameContext.awb.gains.red; + blueGain = speed * blueGain + (1 - speed) * frameContext.awb.gains.blue; + + /* + * Gain values are unsigned integer value, range 0 to 4 with 8 bit + * fractional part. + */ + frameContext.awb.gains.red = std::clamp(redGain, 0.0, 1023.0 / 256); + frameContext.awb.gains.blue = std::clamp(blueGain, 0.0, 1023.0 / 256); + /* Hardcode the green gain to 1.0. */ + frameContext.awb.gains.green = 1.0; + + frameContext.awb.temperatureK = estimateCCT(redMean, greenMean, blueMean); + + LOG(RkISP1Awb, Debug) << "Gain found for red: " << context.frameContext.awb.gains.red + << " and for blue: " << context.frameContext.awb.gains.blue; +} + +} /* namespace ipa::rkisp1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/awb.h b/src/ipa/rkisp1/algorithms/awb.h new file mode 100644 index 00000000..11946643 --- /dev/null +++ b/src/ipa/rkisp1/algorithms/awb.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021-2022, Ideas On Board + * + * awb.h - AWB control algorithm + */ + +#pragma once + +#include + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +class Awb : public Algorithm +{ +public: + Awb() = default; + ~Awb() = default; + + int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override; + void prepare(IPAContext &context, rkisp1_params_cfg *params) override; + void process(IPAContext &context, const rkisp1_stat_buffer *stats) override; + +private: + uint32_t estimateCCT(double red, double green, double blue); +}; + +} /* namespace ipa::rkisp1::algorithms */ +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build index 27c97731..7ec53d89 100644 --- a/src/ipa/rkisp1/algorithms/meson.build +++ b/src/ipa/rkisp1/algorithms/meson.build @@ -2,5 +2,6 @@ rkisp1_ipa_algorithms = files([ 'agc.cpp', + 'awb.cpp', 'blc.cpp', ]) diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 4a1ab058..1559d3ff 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -81,6 +81,14 @@ namespace libcamera::ipa::rkisp1 { * \brief Hardware revision of the ISP */ +/** + * \var IPASessionConfiguration::awb + * \brief AWB parameters configuration of the IPA + * + * \var IPASessionConfiguration::awb.measureWindow + * \brief AWB measure window + */ + /** * \var IPASessionConfiguration::sensor * \brief Sensor-specific configuration of the IPA @@ -105,6 +113,26 @@ namespace libcamera::ipa::rkisp1 { * The gain should be adapted to the sensor specific gain code before applying. */ +/** + * \var IPAFrameContext::awb + * \brief Context for the Automatic White Balance algorithm + * + * \struct IPAFrameContext::awb.gains + * \brief White balance gains + * + * \var IPAFrameContext::awb.gains.red + * \brief White balance gain for R channel + * + * \var IPAFrameContext::awb.gains.green + * \brief White balance gain for G channel + * + * \var IPAFrameContext::awb.gains.blue + * \brief White balance gain for B channel + * + * \var IPAFrameContext::awb.temperatureK + * \brief Estimated color temperature + */ + /** * \var IPAFrameContext::sensor * \brief Effective sensor values diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 35e9b8e5..f387cace 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -12,6 +12,8 @@ #include +#include + namespace libcamera { namespace ipa::rkisp1 { @@ -25,6 +27,10 @@ struct IPASessionConfiguration { struct rkisp1_cif_isp_window measureWindow; } agc; + struct { + struct rkisp1_cif_isp_window measureWindow; + } awb; + struct { utils::Duration lineDuration; } sensor; @@ -40,6 +46,16 @@ struct IPAFrameContext { double gain; } agc; + struct { + struct { + double red; + double green; + double blue; + } gains; + + double temperatureK; + } awb; + struct { uint32_t exposure; double gain; diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 83ed21be..13ab1cdc 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -27,6 +27,7 @@ #include "algorithms/agc.h" #include "algorithms/algorithm.h" +#include "algorithms/awb.h" #include "algorithms/blc.h" #include "libipa/camera_sensor_helper.h" @@ -121,6 +122,7 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision) /* Construct our Algorithms */ algorithms_.push_back(std::make_unique()); + algorithms_.push_back(std::make_unique()); algorithms_.push_back(std::make_unique()); return 0;