From patchwork Thu Feb 27 10:57:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keke Li X-Patchwork-Id: 22890 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 E5AFBBF415 for ; Thu, 27 Feb 2025 10:58:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 80A5968767; Thu, 27 Feb 2025 11:58:59 +0100 (CET) Received: from mail-sh.amlogic.com (unknown [58.32.228.46]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9009368751 for ; Thu, 27 Feb 2025 11:58:55 +0100 (CET) Received: from droid10.amlogic.com (10.18.11.213) by mail-sh.amlogic.com (10.18.11.5) with Microsoft SMTP Server id 15.1.2507.39; Thu, 27 Feb 2025 18:58:54 +0800 From: Keke Li To: CC: , , , Keke Li Subject: [PATCH v3 07/11] ipa: c3-isp: Add BLC Algorithm Date: Thu, 27 Feb 2025 18:57:29 +0800 Message-ID: <20250227105733.187611-8-keke.li@amlogic.com> X-Mailer: git-send-email 2.29.0 In-Reply-To: <20250227105733.187611-1-keke.li@amlogic.com> References: <20250227105733.187611-1-keke.li@amlogic.com> MIME-Version: 1.0 X-Originating-IP: [10.18.11.213] 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" Add a new Black Level Correction algorithm. Signed-off-by: Keke Li --- src/ipa/c3-isp/algorithms/blc.cpp | 151 ++++++++++++++++++++++++++ src/ipa/c3-isp/algorithms/blc.h | 45 ++++++++ src/ipa/c3-isp/algorithms/meson.build | 1 + 3 files changed, 197 insertions(+) create mode 100644 src/ipa/c3-isp/algorithms/blc.cpp create mode 100644 src/ipa/c3-isp/algorithms/blc.h diff --git a/src/ipa/c3-isp/algorithms/blc.cpp b/src/ipa/c3-isp/algorithms/blc.cpp new file mode 100644 index 00000000..4410d03f --- /dev/null +++ b/src/ipa/c3-isp/algorithms/blc.cpp @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Amlogic + * + * C3ISP Black Level Correction control + */ + +#include "blc.h" + +#include + +#include +#include + +#include "libcamera/internal/yaml_parser.h" + +/** + * \file blc.h + */ + +namespace libcamera { + +namespace ipa::c3isp::algorithms { + +/** + * \class Blc + * \brief C3 ISP 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 C3 ISP 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. + */ + +LOG_DEFINE_CATEGORY(C3ISPBlc) + +Blc::Blc() + : tuningBlc_(false) +{ +} + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Blc::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) +{ + offsetR_ = tuningData["offsetR"].get(0); + offsetGr_ = tuningData["offsetGr"].get(0); + offsetGb_ = tuningData["offsetGb"].get(0); + offsetB_ = tuningData["offsetB"].get(0); + + if (!(offsetR_ + offsetGr_ + offsetGb_ + offsetB_)) { + LOG(C3ISPBlc, Debug) << "All black level offsets are empty"; + tuningBlc_ = false; + } else { + tuningBlc_ = true; + } + + return 0; +} + +/** + * \copydoc libcamera::ipa::Algorithm::configure + */ +int Blc::configure(IPAContext &context, + [[maybe_unused]] const IPACameraSensorInfo &configInfo) +{ + uint16_t blackLevel = offsetCompress(context.configuration.sensor.blackLevel); + + if (blackLevel && !tuningBlc_) { + offsetR_ = context.configuration.sensor.blackLevel; + offsetGr_ = context.configuration.sensor.blackLevel; + offsetGb_ = context.configuration.sensor.blackLevel; + offsetB_ = context.configuration.sensor.blackLevel; + } + + return 0; +} + +uint16_t Blc::offsetCompress(uint32_t blackLevel) +{ + uint8_t shift = 0; + uint32_t integer = 0; + uint8_t highestBitPos = static_cast(log2(blackLevel)); + + /* The compressed offset is stored in Q4.12 format */ + if (highestBitPos < 12) { + shift = 0; + integer = blackLevel; + } else { + shift = highestBitPos - 11; + integer = blackLevel >> shift; + } + + shift = (shift > 0xf) ? 0xf : shift; + + return (shift & 0xf) << 12 | (integer & 0xfff); +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Blc::prepare([[maybe_unused]] IPAContext &context, const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + C3ISPParams *params) +{ + if (frame > 0) + return; + + if (!tuningBlc_ && !context.configuration.sensor.blackLevel) + return; + + auto blcCfg = params->block(); + blcCfg.setEnabled(C3_ISP_PARAMS_BLOCK_FL_ENABLE); + + blcCfg->gr_ofst = offsetCompress(offsetGr_); + blcCfg->r_ofst = offsetCompress(offsetR_); + blcCfg->b_ofst = offsetCompress(offsetB_); + blcCfg->gb_ofst = offsetCompress(offsetGb_); +} + +/** + * \copydoc libcamera::ipa::Algorithm::process + */ +void Blc::process([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + [[maybe_unused]] const c3_isp_stats_info *stats, + ControlList &metadata) +{ + /* + * Black Level Offsets in tuning data need to be 20-bit, whereas the + * metadata expects values from a 16-bit range. Right-shift to remove + * the 4 least significant bits. + */ + metadata.set(controls::SensorBlackLevels, + { static_cast(offsetR_ >> 4), + static_cast(offsetGr_ >> 4), + static_cast(offsetGb_ >> 4), + static_cast(offsetB_ >> 4) }); +} + +REGISTER_IPA_ALGORITHM(Blc, "Blc") + +} /* namespace ipa::c3isp::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/c3-isp/algorithms/blc.h b/src/ipa/c3-isp/algorithms/blc.h new file mode 100644 index 00000000..67244e4a --- /dev/null +++ b/src/ipa/c3-isp/algorithms/blc.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Amlogic + * + * C3ISP Black Level Correction control + */ + +#pragma once + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::c3isp::algorithms { + +class Blc : public Algorithm +{ +public: + Blc(); + ~Blc() = default; + + int init(IPAContext &context, const YamlObject &tuningData) override; + int configure(IPAContext &context, + const IPACameraSensorInfo &configInfo) override; + void prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + C3ISPParams *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const c3_isp_stats_info *stats, + ControlList &metadata) override; + +private: + uint16_t offsetCompress(uint32_t blackLevel); + + bool tuningBlc_; + uint32_t offsetR_; + uint32_t offsetGr_; + uint32_t offsetGb_; + uint32_t offsetB_; +}; + +} /* namespace ipa::c3isp::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/c3-isp/algorithms/meson.build b/src/ipa/c3-isp/algorithms/meson.build index 9460da99..d91973e3 100644 --- a/src/ipa/c3-isp/algorithms/meson.build +++ b/src/ipa/c3-isp/algorithms/meson.build @@ -3,4 +3,5 @@ c3isp_ipa_algorithms = files([ 'agc.cpp', 'awb.cpp', + 'blc.cpp', ])