From patchwork Mon Aug 9 09:20:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13252 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 8A0A8C3241 for ; Mon, 9 Aug 2021 09:20:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 36DF9687EB; Mon, 9 Aug 2021 11:20:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="J9FGTk16"; 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 1706968823 for ; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:14c5:c0eb:b1fb:db22]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A670049A; Mon, 9 Aug 2021 11:20:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628500815; bh=hOGLI3q4SOSC3OcV2W2qxHLsax8Do1MNf+KmmiGjdMU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J9FGTk169QW78xNWaj7lHnDctkjIYaTPhg55vo9iUI+X8cAtglVFPeA85khvcz199 HV0+TsuQDA1DkssmbA+DSFsYD2RQ2JXTBeUWbz77CZWEUD9cw+CkVOSXYCnozw4zhW 4FvTpkHXBw4JATP3yUNAHhanhxWQjSHtXSw+6fuY= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Aug 2021 11:20:03 +0200 Message-Id: <20210809092007.79067-2-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> References: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 1/5] ipa: ipu3: Introduce a Context structure 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" Passing parameters, statistics and all specific data each algorithm shares. As the ipu3_uapi_params are part of the IPA context referenced by the algorithms, move the structure into the IPAContext directly and adapt existing algorithm implementations. Signed-off-by: Kieran Bingham Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Umang Jain --- src/ipa/ipu3/ipa_context.h | 30 ++++++++++++++++++++++++++++++ src/ipa/ipu3/ipu3.cpp | 16 +++++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 src/ipa/ipu3/ipa_context.h diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h new file mode 100644 index 00000000..5d717be5 --- /dev/null +++ b/src/ipa/ipu3/ipa_context.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Ideas On Board + * + * ipu3_ipa_context.h - IPU3 IPA Context + * + * Context information shared between the algorithms + */ +#ifndef __LIBCAMERA_IPU3_IPA_CONTEXT_H__ +#define __LIBCAMERA_IPU3_IPA_CONTEXT_H__ + +#include + +namespace libcamera { + +namespace ipa::ipu3 { + +struct IPAContext { + /* Input statistics from the previous frame */ + const ipu3_uapi_stats_3a *stats; + + /* Output Parameters which will be written to the hardware */ + ipu3_uapi_params params; +}; + +} /* namespace ipa::ipu3 */ + +} /* namespace libcamera*/ + +#endif /* __LIBCAMERA_IPU3_IPA_CONTEXT_H__ */ diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 71698d36..a714af85 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -22,6 +22,8 @@ #include "libcamera/internal/framebuffer.h" +#include "ipa_context.h" + #include "ipu3_agc.h" #include "ipu3_awb.h" #include "libipa/camera_sensor_helper.h" @@ -81,9 +83,8 @@ private: std::unique_ptr camHelper_; /* Local parameter storage */ - struct ipu3_uapi_params params_; - struct ipu3_uapi_grid_config bdsGrid_; + struct IPAContext context_; }; int IPAIPU3::init(const IPASettings &settings) @@ -94,6 +95,9 @@ int IPAIPU3::init(const IPASettings &settings) return -ENODEV; } + /* Reset all the hardware settings */ + context_.params = {}; + return 0; } @@ -193,12 +197,10 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) defVBlank_ = itVBlank->second.def().get(); - params_ = {}; - calculateBdsGrid(configInfo.bdsOutputSize); awbAlgo_ = std::make_unique(); - awbAlgo_->initialise(params_, configInfo.bdsOutputSize, bdsGrid_); + awbAlgo_->initialise(context_.params, configInfo.bdsOutputSize, bdsGrid_); agcAlgo_ = std::make_unique(); agcAlgo_->initialise(bdsGrid_, sensorInfo_); @@ -276,9 +278,9 @@ void IPAIPU3::processControls([[maybe_unused]] unsigned int frame, void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params) { if (agcAlgo_->updateControls()) - awbAlgo_->updateWbParameters(params_, agcAlgo_->gamma()); + awbAlgo_->updateWbParameters(context_.params, agcAlgo_->gamma()); - *params = params_; + *params = context_.params; IPU3Action op; op.op = ActionParamFilled; From patchwork Mon Aug 9 09:20:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13253 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 81230BD87D for ; Mon, 9 Aug 2021 09:20:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3FE1E68864; Mon, 9 Aug 2021 11:20:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="CaWiKM0b"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3770A68826 for ; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:14c5:c0eb:b1fb:db22]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D74B94A1; Mon, 9 Aug 2021 11:20:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628500815; bh=A3Lt+YMe0FeKiiDBhL7+1hPAh1k7tHbw8GSzNrytY5c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CaWiKM0bC+JMvISK4KZZJEVIylBsVLmltRO0ZDWs/V4SKuS4moBPEeWqoPnSR2V1i qVqz8SMJkJCmk32Ls5kvRAlctJiIxW1yE+uVDPJSP/r+bt42cyMzD0D8angMhv9aNz E9ko74O96oe3VIgv/uEF2A7cpE4wD60MHf0C2PcY= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Aug 2021 11:20:04 +0200 Message-Id: <20210809092007.79067-3-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> References: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 2/5] ipa: ipu3: Introduce modular algorithms 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" Provide a modular IPU3 specific algorithm, and frame context structure so that algorithms can be built for the IPU3 in a component based structure. Signed-off-by: Kieran Bingham Signed-off-by: Jean-Michel Hautbois --- src/ipa/ipu3/algorithms/algorithm.h | 30 ++++++++++++++++++ src/ipa/ipu3/algorithms/meson.build | 4 +++ src/ipa/ipu3/ipu3.cpp | 47 +++++++++++++++++++++++++++++ src/ipa/ipu3/ipu3_agc.h | 3 +- src/ipa/ipu3/ipu3_awb.h | 3 +- src/ipa/ipu3/meson.build | 4 +++ 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 src/ipa/ipu3/algorithms/algorithm.h create mode 100644 src/ipa/ipu3/algorithms/meson.build diff --git a/src/ipa/ipu3/algorithms/algorithm.h b/src/ipa/ipu3/algorithms/algorithm.h new file mode 100644 index 00000000..bac82b7c --- /dev/null +++ b/src/ipa/ipu3/algorithms/algorithm.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Ideas On Board + * + * algorithm.h - IPU3 control algorithm interface + */ +#ifndef __LIBCAMERA_IPA_IPU3_ALGORITHM_H__ +#define __LIBCAMERA_IPA_IPU3_ALGORITHM_H__ + +#include + +namespace libcamera { + +namespace ipa::ipu3 { + +class Algorithm +{ +public: + virtual ~Algorithm() {} + + virtual int initialise([[maybe_unused]] IPAContext &context) { return 0; } + virtual int configure([[maybe_unused]] IPAContext &context) { return 0; } + virtual void process([[maybe_unused]] IPAContext &context) {} +}; + +} /* namespace ipa::ipu3 */ + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_IPA_IPU3_ALGORITHM_H__ */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build new file mode 100644 index 00000000..67148333 --- /dev/null +++ b/src/ipa/ipu3/algorithms/meson.build @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: CC0-1.0 + +ipu3_ipa_algorithms = files([ +]) diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index a714af85..55c4da72 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -22,6 +22,7 @@ #include "libcamera/internal/framebuffer.h" +#include "algorithms/algorithm.h" #include "ipa_context.h" #include "ipu3_agc.h" @@ -53,6 +54,10 @@ public: private: void processControls(unsigned int frame, const ControlList &controls); void fillParams(unsigned int frame, ipu3_uapi_params *params); + + int initialiseAlgorithms(); + int configureAlgorithms(); + void processAlgorithms(const ipu3_uapi_stats_3a *stats); void parseStatistics(unsigned int frame, int64_t frameTimestamp, const ipu3_uapi_stats_3a *stats); @@ -82,6 +87,9 @@ private: /* Interface to the Camera Helper */ std::unique_ptr camHelper_; + /* Maintain the algorithms used by the IPA */ + std::list> algorithms_; + /* Local parameter storage */ struct ipu3_uapi_grid_config bdsGrid_; struct IPAContext context_; @@ -98,6 +106,8 @@ int IPAIPU3::init(const IPASettings &settings) /* Reset all the hardware settings */ context_.params = {}; + initialiseAlgorithms(); + return 0; } @@ -199,6 +209,8 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) calculateBdsGrid(configInfo.bdsOutputSize); + configureAlgorithms(); + awbAlgo_ = std::make_unique(); awbAlgo_->initialise(context_.params, configInfo.bdsOutputSize, bdsGrid_); @@ -288,12 +300,47 @@ void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params) queueFrameAction.emit(frame, op); } +int IPAIPU3::initialiseAlgorithms() +{ + for (auto const &algo : algorithms_) { + int ret = algo->initialise(context_); + if (ret) + return ret; + } + + return 0; +} + +int IPAIPU3::configureAlgorithms() +{ + for (auto const &algo : algorithms_) { + int ret = algo->configure(context_); + if (ret) + return ret; + } + + return 0; +} + +void IPAIPU3::processAlgorithms(const ipu3_uapi_stats_3a *stats) +{ + /* It might be better to pass the stats in as a parameter to process() ? */ + context_.stats = stats; + + for (auto const &algo : algorithms_) { + algo->process(context_); + } +} + void IPAIPU3::parseStatistics(unsigned int frame, [[maybe_unused]] int64_t frameTimestamp, [[maybe_unused]] const ipu3_uapi_stats_3a *stats) { ControlList ctrls(controls::controls); + /* Run the process for each algorithm on the stats */ + processAlgorithms(stats); + double gain = camHelper_->gain(gain_); agcAlgo_->process(stats, exposure_, gain); gain_ = camHelper_->gainCode(gain); diff --git a/src/ipa/ipu3/ipu3_agc.h b/src/ipa/ipu3/ipu3_agc.h index 3deca3ae..e3e1d28b 100644 --- a/src/ipa/ipu3/ipu3_agc.h +++ b/src/ipa/ipu3/ipu3_agc.h @@ -16,6 +16,7 @@ #include +#include "algorithms/algorithm.h" #include "libipa/algorithm.h" namespace libcamera { @@ -26,7 +27,7 @@ namespace ipa::ipu3 { using utils::Duration; -class IPU3Agc : public Algorithm +class IPU3Agc : public ipa::Algorithm { public: IPU3Agc(); diff --git a/src/ipa/ipu3/ipu3_awb.h b/src/ipa/ipu3/ipu3_awb.h index 122cf68c..284e3844 100644 --- a/src/ipa/ipu3/ipu3_awb.h +++ b/src/ipa/ipu3/ipu3_awb.h @@ -13,6 +13,7 @@ #include +#include "algorithms/algorithm.h" #include "libipa/algorithm.h" namespace libcamera { @@ -23,7 +24,7 @@ namespace ipa::ipu3 { static constexpr uint32_t kAwbStatsSizeX = 16; static constexpr uint32_t kAwbStatsSizeY = 12; -class IPU3Awb : public Algorithm +class IPU3Awb : public ipa::Algorithm { public: IPU3Awb(); diff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build index b6364190..fcb27d68 100644 --- a/src/ipa/ipu3/meson.build +++ b/src/ipa/ipu3/meson.build @@ -1,5 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 +subdir('algorithms') + ipa_name = 'ipa_ipu3' ipu3_ipa_sources = files([ @@ -8,6 +10,8 @@ ipu3_ipa_sources = files([ 'ipu3_awb.cpp', ]) +ipu3_ipa_sources += ipu3_ipa_algorithms + mod = shared_module(ipa_name, [ipu3_ipa_sources, libcamera_generated_ipa_headers], name_prefix : '', From patchwork Mon Aug 9 09:20:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13254 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 2DE43C3242 for ; Mon, 9 Aug 2021 09:20:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B5F3868826; Mon, 9 Aug 2021 11:20:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="g7OwlpWU"; 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 635F5687EB for ; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:14c5:c0eb:b1fb:db22]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1464BEE; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628500816; bh=gV2W5BMl/IGfqZ28vFNS1Xz9w9rEZysXtutG/golD48=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=g7OwlpWUsWcziVrsAStrLEOaH6DHKfvofpUPl86ZtlyTJpNbmO/vCjJZYOOfTZDbd FfJITmulfuO69iQha61UbdpM4pyk5VDCwFw1SkpouKejnS+BtebjZsy6i/MQPwFCpl h368kJb+uoX5Kxlt/vo61KQrygCE7AK7EuPdQS6I= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Aug 2021 11:20:05 +0200 Message-Id: <20210809092007.79067-4-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> References: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 3/5] ipa: ipu3: Introduce a modular contrast algorithm 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" Implement a new modular framework for algorithms with a common context structure that is passed to each algorithm through a common API. The initial algorithm is chosen to configure the gamma contrast curve which replicates the implementation from AWB for simplicity. As it is initialised with a default gamma value of 1.0, there is no need to use the default table at init time anymore. Signed-off-by: Kieran Bingham Signed-off-by: Jean-Michel Hautbois --- src/ipa/ipu3/algorithms/contrast.cpp | 52 ++++++++++++++++++++++++++++ src/ipa/ipu3/algorithms/contrast.h | 32 +++++++++++++++++ src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipu3.cpp | 6 +++- src/ipa/ipu3/ipu3_agc.cpp | 5 +-- src/ipa/ipu3/ipu3_agc.h | 3 -- src/ipa/ipu3/ipu3_awb.cpp | 41 ++-------------------- src/ipa/ipu3/ipu3_awb.h | 2 +- 8 files changed, 94 insertions(+), 48 deletions(-) create mode 100644 src/ipa/ipu3/algorithms/contrast.cpp create mode 100644 src/ipa/ipu3/algorithms/contrast.h diff --git a/src/ipa/ipu3/algorithms/contrast.cpp b/src/ipa/ipu3/algorithms/contrast.cpp new file mode 100644 index 00000000..832dbf35 --- /dev/null +++ b/src/ipa/ipu3/algorithms/contrast.cpp @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Ideas On Board + * + * constrast.cpp - IPU3 Contrast and Gamma control + */ + +#include "contrast.h" + +#include + +#include + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +LOG_DEFINE_CATEGORY(IPU3Contrast) + +Contrast::Contrast() + : gamma_(1.0) +{ + LOG(IPU3Contrast, Info) << "Instantiate Gamma"; +} + +int Contrast::initialise(IPAContext &context) +{ + ipu3_uapi_params ¶ms = context.params; + + params.use.acc_gamma = 1; + params.acc_param.gamma.gc_ctrl.enable = 1; + + /* Limit the gamma effect for now */ + gamma_ = 1.1; + + /* Plot the gamma curve into the look up table */ + for (uint32_t i = 0; i < 256; i++) { + double j = i / 255.0; + double gamma = std::pow(j, 1.0 / gamma_); + + /* The maximum value 255 is represented on 13 bits in the IPU3 */ + params.acc_param.gamma.gc_lut.lut[i] = gamma * 8191; + } + + LOG(IPU3Contrast, Info) << "Processed Gamma Curve"; + + return 0; +} + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/ipu3/algorithms/contrast.h b/src/ipa/ipu3/algorithms/contrast.h new file mode 100644 index 00000000..958e8bb8 --- /dev/null +++ b/src/ipa/ipu3/algorithms/contrast.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google + * + * constrast.h - IPU3 Contrast and Gamma control + */ +#ifndef __LIBCAMERA_IPU3_ALGORITHMS_CONTRAST_H__ +#define __LIBCAMERA_IPU3_ALGORITHMS_CONTRAST_H__ + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +class Contrast : public Algorithm +{ +public: + Contrast(); + ~Contrast() = default; + + int initialise(IPAContext &context) override; + +private: + double gamma_; +}; + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_IPU3_ALGORITHMS_CONTRAST_H__ */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build index 67148333..f71d1e61 100644 --- a/src/ipa/ipu3/algorithms/meson.build +++ b/src/ipa/ipu3/algorithms/meson.build @@ -1,4 +1,5 @@ # SPDX-License-Identifier: CC0-1.0 ipu3_ipa_algorithms = files([ + 'contrast.cpp', ]) diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 55c4da72..7035802f 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -23,6 +23,7 @@ #include "libcamera/internal/framebuffer.h" #include "algorithms/algorithm.h" +#include "algorithms/contrast.h" #include "ipa_context.h" #include "ipu3_agc.h" @@ -103,6 +104,9 @@ int IPAIPU3::init(const IPASettings &settings) return -ENODEV; } + /* Construct our Algorithms */ + algorithms_.emplace_back(new algorithms::Contrast()); + /* Reset all the hardware settings */ context_.params = {}; @@ -290,7 +294,7 @@ void IPAIPU3::processControls([[maybe_unused]] unsigned int frame, void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params) { if (agcAlgo_->updateControls()) - awbAlgo_->updateWbParameters(context_.params, agcAlgo_->gamma()); + awbAlgo_->updateWbParameters(context_.params); *params = context_.params; diff --git a/src/ipa/ipu3/ipu3_agc.cpp b/src/ipa/ipu3/ipu3_agc.cpp index 6253ab94..733814dd 100644 --- a/src/ipa/ipu3/ipu3_agc.cpp +++ b/src/ipa/ipu3/ipu3_agc.cpp @@ -52,7 +52,7 @@ static constexpr uint8_t kCellSize = 8; IPU3Agc::IPU3Agc() : frameCount_(0), lastFrame_(0), converged_(false), - updateControls_(false), iqMean_(0.0), gamma_(1.0), + updateControls_(false), iqMean_(0.0), lineDuration_(0s), maxExposureTime_(0s), prevExposure_(0s), prevExposureNoDg_(0s), currentExposure_(0s), currentExposureNoDg_(0s) @@ -104,9 +104,6 @@ void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats) } } - /* Limit the gamma effect for now */ - gamma_ = 1.1; - /* Estimate the quantile mean of the top 2% of the histogram */ iqMean_ = Histogram(Span(hist)).interQuantileMean(0.98, 1.0); } diff --git a/src/ipa/ipu3/ipu3_agc.h b/src/ipa/ipu3/ipu3_agc.h index e3e1d28b..3b7f781e 100644 --- a/src/ipa/ipu3/ipu3_agc.h +++ b/src/ipa/ipu3/ipu3_agc.h @@ -37,8 +37,6 @@ public: void process(const ipu3_uapi_stats_3a *stats, uint32_t &exposure, double &gain); bool converged() { return converged_; } bool updateControls() { return updateControls_; } - /* \todo Use a metadata exchange between IPAs */ - double gamma() { return gamma_; } private: void processBrightness(const ipu3_uapi_stats_3a *stats); @@ -54,7 +52,6 @@ private: bool updateControls_; double iqMean_; - double gamma_; Duration lineDuration_; Duration maxExposureTime_; diff --git a/src/ipa/ipu3/ipu3_awb.cpp b/src/ipa/ipu3/ipu3_awb.cpp index 9b409c8f..043c3838 100644 --- a/src/ipa/ipu3/ipu3_awb.cpp +++ b/src/ipa/ipu3/ipu3_awb.cpp @@ -134,31 +134,6 @@ static const struct ipu3_uapi_ccm_mat_config imguCssCcmDefault = { 0, 0, 8191, 0 }; -/* Default settings for Gamma correction */ -const struct ipu3_uapi_gamma_corr_lut imguCssGammaLut = { { - 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, 271, 287, - 303, 319, 335, 351, 367, 383, 399, 415, 431, 447, 463, 479, 495, 511, - 527, 543, 559, 575, 591, 607, 623, 639, 655, 671, 687, 703, 719, 735, - 751, 767, 783, 799, 815, 831, 847, 863, 879, 895, 911, 927, 943, 959, - 975, 991, 1007, 1023, 1039, 1055, 1071, 1087, 1103, 1119, 1135, 1151, - 1167, 1183, 1199, 1215, 1231, 1247, 1263, 1279, 1295, 1311, 1327, 1343, - 1359, 1375, 1391, 1407, 1423, 1439, 1455, 1471, 1487, 1503, 1519, 1535, - 1551, 1567, 1583, 1599, 1615, 1631, 1647, 1663, 1679, 1695, 1711, 1727, - 1743, 1759, 1775, 1791, 1807, 1823, 1839, 1855, 1871, 1887, 1903, 1919, - 1935, 1951, 1967, 1983, 1999, 2015, 2031, 2047, 2063, 2079, 2095, 2111, - 2143, 2175, 2207, 2239, 2271, 2303, 2335, 2367, 2399, 2431, 2463, 2495, - 2527, 2559, 2591, 2623, 2655, 2687, 2719, 2751, 2783, 2815, 2847, 2879, - 2911, 2943, 2975, 3007, 3039, 3071, 3103, 3135, 3167, 3199, 3231, 3263, - 3295, 3327, 3359, 3391, 3423, 3455, 3487, 3519, 3551, 3583, 3615, 3647, - 3679, 3711, 3743, 3775, 3807, 3839, 3871, 3903, 3935, 3967, 3999, 4031, - 4063, 4095, 4127, 4159, 4223, 4287, 4351, 4415, 4479, 4543, 4607, 4671, - 4735, 4799, 4863, 4927, 4991, 5055, 5119, 5183, 5247, 5311, 5375, 5439, - 5503, 5567, 5631, 5695, 5759, 5823, 5887, 5951, 6015, 6079, 6143, 6207, - 6271, 6335, 6399, 6463, 6527, 6591, 6655, 6719, 6783, 6847, 6911, 6975, - 7039, 7103, 7167, 7231, 7295, 7359, 7423, 7487, 7551, 7615, 7679, 7743, - 7807, 7871, 7935, 7999, 8063, 8127, 8191 -} }; - IPU3Awb::IPU3Awb() : Algorithm() { @@ -198,10 +173,6 @@ void IPU3Awb::initialise(ipu3_uapi_params ¶ms, const Size &bdsOutputSize, st params.use.acc_ccm = 1; params.acc_param.ccm = imguCssCcmDefault; - params.use.acc_gamma = 1; - params.acc_param.gamma.gc_lut = imguCssGammaLut; - params.acc_param.gamma.gc_ctrl.enable = 1; - zones_.reserve(kAwbStatsSizeX * kAwbStatsSizeY); } @@ -351,7 +322,7 @@ void IPU3Awb::calculateWBGains(const ipu3_uapi_stats_3a *stats) } } -void IPU3Awb::updateWbParameters(ipu3_uapi_params ¶ms, double agcGamma) +void IPU3Awb::updateWbParameters(ipu3_uapi_params ¶ms) { /* * Green gains should not be touched and considered 1. @@ -363,18 +334,10 @@ void IPU3Awb::updateWbParameters(ipu3_uapi_params ¶ms, double agcGamma) params.acc_param.bnr.wb_gains.b = 4096 * asyncResults_.blueGain; params.acc_param.bnr.wb_gains.gb = 16; - LOG(IPU3Awb, Debug) << "Color temperature estimated: " << asyncResults_.temperatureK - << " and gamma calculated: " << agcGamma; + LOG(IPU3Awb, Debug) << "Color temperature estimated: " << asyncResults_.temperatureK; /* The CCM matrix may change when color temperature will be used */ params.acc_param.ccm = imguCssCcmDefault; - - for (uint32_t i = 0; i < 256; i++) { - double j = i / 255.0; - double gamma = std::pow(j, 1.0 / agcGamma); - /* The maximum value 255 is represented on 13 bits in the IPU3 */ - params.acc_param.gamma.gc_lut.lut[i] = gamma * 8191; - } } } /* namespace ipa::ipu3 */ diff --git a/src/ipa/ipu3/ipu3_awb.h b/src/ipa/ipu3/ipu3_awb.h index 284e3844..8b05ac03 100644 --- a/src/ipa/ipu3/ipu3_awb.h +++ b/src/ipa/ipu3/ipu3_awb.h @@ -32,7 +32,7 @@ public: void initialise(ipu3_uapi_params ¶ms, const Size &bdsOutputSize, struct ipu3_uapi_grid_config &bdsGrid); void calculateWBGains(const ipu3_uapi_stats_3a *stats); - void updateWbParameters(ipu3_uapi_params ¶ms, double agcGamma); + void updateWbParameters(ipu3_uapi_params ¶ms); struct Ipu3AwbCell { unsigned char greenRedAvg; From patchwork Mon Aug 9 09:20:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13255 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 8BC89C3241 for ; Mon, 9 Aug 2021 09:20:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2B54168890; Mon, 9 Aug 2021 11:20:21 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gl+KvdV7"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8D63268823 for ; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:14c5:c0eb:b1fb:db22]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4D57049A; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628500816; bh=79d8ZYNWuPlZ0uJhLoLd85PBr4/ElSJ4Ynhvfhaw9Dc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gl+KvdV7f1QkLSdpy2ds+hT9ZatuPTuWEbMFB4HLG2bua96rsdQx6xPgjInfKXzlc UYq1w58i/JX621kNY1UjkB0v9XseAXgU2x4TlzPHo8N+oguTJrRKMUX05uADi4i0tg QEwaVZ66ygBSIomlTP9nMn9pav7Qn8sJPs/7Q674= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Aug 2021 11:20:06 +0200 Message-Id: <20210809092007.79067-5-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> References: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 4/5] ipa: ipu3: Move IPU3 awb into algorithms 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" Use the Context class and algorithm interface to properly call the AWB algorithm from IPAIPU3. We need to pass the BDS grid size calculated, pass those through the Context class in a dedicated Awb structure. Signed-off-by: Jean-Michel Hautbois --- .../ipu3/{ipu3_awb.cpp => algorithms/awb.cpp} | 42 ++++++++++++------- src/ipa/ipu3/{ipu3_awb.h => algorithms/awb.h} | 29 ++++++------- src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipa_context.h | 12 ++++++ src/ipa/ipu3/ipu3.cpp | 30 ++++++------- src/ipa/ipu3/meson.build | 1 - 6 files changed, 66 insertions(+), 49 deletions(-) rename src/ipa/ipu3/{ipu3_awb.cpp => algorithms/awb.cpp} (92%) rename src/ipa/ipu3/{ipu3_awb.h => algorithms/awb.h} (79%) diff --git a/src/ipa/ipu3/ipu3_awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp similarity index 92% rename from src/ipa/ipu3/ipu3_awb.cpp rename to src/ipa/ipu3/algorithms/awb.cpp index 043c3838..92a41b65 100644 --- a/src/ipa/ipu3/ipu3_awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -2,9 +2,9 @@ /* * Copyright (C) 2021, Ideas On Board * - * ipu3_awb.cpp - AWB control algorithm + * awb.cpp - AWB control algorithm */ -#include "ipu3_awb.h" +#include "awb.h" #include #include @@ -14,7 +14,7 @@ namespace libcamera { -namespace ipa::ipu3 { +namespace ipa::ipu3::algorithms { LOG_DEFINE_CATEGORY(IPU3Awb) @@ -134,7 +134,7 @@ static const struct ipu3_uapi_ccm_mat_config imguCssCcmDefault = { 0, 0, 8191, 0 }; -IPU3Awb::IPU3Awb() +Awb::Awb() : Algorithm() { asyncResults_.blueGain = 1.0; @@ -143,17 +143,19 @@ IPU3Awb::IPU3Awb() asyncResults_.temperatureK = 4500; } -IPU3Awb::~IPU3Awb() +Awb::~Awb() { } -void IPU3Awb::initialise(ipu3_uapi_params ¶ms, const Size &bdsOutputSize, struct ipu3_uapi_grid_config &bdsGrid) +int Awb::configure(IPAContext &context) { + ipu3_uapi_params ¶ms = context.params; + Size &bdsOutputSize = context.awb.grid.bdsOutputSize; + params.use.acc_awb = 1; params.acc_param.awb.config = imguCssAwbDefaults; - awbGrid_ = bdsGrid; - params.acc_param.awb.config.grid = awbGrid_; + awbGrid_ = context.awb.grid.bdsGrid; params.use.acc_bnr = 1; params.acc_param.bnr = imguCssBnrDefaults; @@ -174,6 +176,8 @@ void IPU3Awb::initialise(ipu3_uapi_params ¶ms, const Size &bdsOutputSize, st params.acc_param.ccm = imguCssCcmDefault; zones_.reserve(kAwbStatsSizeX * kAwbStatsSizeY); + + return 0; } /** @@ -190,7 +194,7 @@ void IPU3Awb::initialise(ipu3_uapi_params ¶ms, const Size &bdsOutputSize, st * More detailed information can be found in: * https://en.wikipedia.org/wiki/Color_temperature#Approximation */ -uint32_t IPU3Awb::estimateCCT(double red, double green, double blue) +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); @@ -207,7 +211,7 @@ uint32_t IPU3Awb::estimateCCT(double red, double green, double blue) } /* Generate an RGB vector with the average values for each region */ -void IPU3Awb::generateZones(std::vector &zones) +void Awb::generateZones(std::vector &zones) { for (unsigned int i = 0; i < kAwbStatsSizeX * kAwbStatsSizeY; i++) { RGB zone; @@ -224,7 +228,7 @@ void IPU3Awb::generateZones(std::vector &zones) } /* Translate the IPU3 statistics into the default statistics region array */ -void IPU3Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats) +void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats) { uint32_t regionWidth = round(awbGrid_.width / static_cast(kAwbStatsSizeX)); uint32_t regionHeight = round(awbGrid_.height / static_cast(kAwbStatsSizeY)); @@ -256,7 +260,7 @@ void IPU3Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats) } } -void IPU3Awb::clearAwbStats() +void Awb::clearAwbStats() { for (unsigned int i = 0; i < kAwbStatsSizeX * kAwbStatsSizeY; i++) { awbStats_[i].bSum = 0; @@ -267,7 +271,7 @@ void IPU3Awb::clearAwbStats() } } -void IPU3Awb::awbGreyWorld() +void Awb::awbGreyWorld() { LOG(IPU3Awb, Debug) << "Grey world AWB"; /* @@ -307,7 +311,7 @@ void IPU3Awb::awbGreyWorld() asyncResults_.blueGain = blueGain; } -void IPU3Awb::calculateWBGains(const ipu3_uapi_stats_3a *stats) +void Awb::calculateWBGains(const ipu3_uapi_stats_3a *stats) { ASSERT(stats->stats_3a_status.awb_en); zones_.clear(); @@ -322,7 +326,7 @@ void IPU3Awb::calculateWBGains(const ipu3_uapi_stats_3a *stats) } } -void IPU3Awb::updateWbParameters(ipu3_uapi_params ¶ms) +void Awb::updateWbParameters(ipu3_uapi_params ¶ms) { /* * Green gains should not be touched and considered 1. @@ -340,6 +344,12 @@ void IPU3Awb::updateWbParameters(ipu3_uapi_params ¶ms) params.acc_param.ccm = imguCssCcmDefault; } -} /* namespace ipa::ipu3 */ +void Awb::process(IPAContext &context) +{ + calculateWBGains(context.stats); + updateWbParameters(context.params); +} + +} /* namespace ipa::ipu3::algorithms */ } /* namespace libcamera */ diff --git a/src/ipa/ipu3/ipu3_awb.h b/src/ipa/ipu3/algorithms/awb.h similarity index 79% rename from src/ipa/ipu3/ipu3_awb.h rename to src/ipa/ipu3/algorithms/awb.h index 8b05ac03..37690b37 100644 --- a/src/ipa/ipu3/ipu3_awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -2,10 +2,10 @@ /* * Copyright (C) 2021, Ideas On Board * - * ipu3_awb.h - IPU3 AWB control algorithm + * awb.h - IPU3 AWB control algorithm */ -#ifndef __LIBCAMERA_IPU3_AWB_H__ -#define __LIBCAMERA_IPU3_AWB_H__ +#ifndef __LIBCAMERA_IPU3_ALGORITHMS_AWB_H__ +#define __LIBCAMERA_IPU3_ALGORITHMS_AWB_H__ #include @@ -13,26 +13,24 @@ #include -#include "algorithms/algorithm.h" -#include "libipa/algorithm.h" +#include "algorithm.h" namespace libcamera { -namespace ipa::ipu3 { +namespace ipa::ipu3::algorithms { /* Region size for the statistics generation algorithm */ static constexpr uint32_t kAwbStatsSizeX = 16; static constexpr uint32_t kAwbStatsSizeY = 12; -class IPU3Awb : public ipa::Algorithm +class Awb : public Algorithm { public: - IPU3Awb(); - ~IPU3Awb(); + Awb(); + ~Awb(); - void initialise(ipu3_uapi_params ¶ms, const Size &bdsOutputSize, struct ipu3_uapi_grid_config &bdsGrid); - void calculateWBGains(const ipu3_uapi_stats_3a *stats); - void updateWbParameters(ipu3_uapi_params ¶ms); + int configure(IPAContext &context) override; + void process(IPAContext &context) override; struct Ipu3AwbCell { unsigned char greenRedAvg; @@ -73,6 +71,9 @@ public: }; private: + void calculateWBGains(const ipu3_uapi_stats_3a *stats); + void updateWbParameters(ipu3_uapi_params ¶ms); + void generateZones(std::vector &zones); void generateAwbStats(const ipu3_uapi_stats_3a *stats); void clearAwbStats(); @@ -86,7 +87,7 @@ private: AwbStatus asyncResults_; }; -} /* namespace ipa::ipu3 */ +} /* namespace ipa::ipu3::algorithms */ } /* namespace libcamera*/ -#endif /* __LIBCAMERA_IPU3_AWB_H__ */ +#endif /* __LIBCAMERA_IPU3_ALGORITHMS_AWB_H__ */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build index f71d1e61..df36d719 100644 --- a/src/ipa/ipu3/algorithms/meson.build +++ b/src/ipa/ipu3/algorithms/meson.build @@ -1,5 +1,6 @@ # SPDX-License-Identifier: CC0-1.0 ipu3_ipa_algorithms = files([ + 'awb.cpp', 'contrast.cpp', ]) diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index 5d717be5..c43b275b 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -11,6 +11,8 @@ #include +#include + namespace libcamera { namespace ipa::ipu3 { @@ -21,6 +23,16 @@ struct IPAContext { /* Output Parameters which will be written to the hardware */ ipu3_uapi_params params; + + /* AWB specific parameters to share */ + struct Awb { + struct Grid { + /* BDS grid plane config used by the kernel */ + ipu3_uapi_grid_config bdsGrid; + /* BDS output size configured by the pipeline handler */ + Size bdsOutputSize; + } grid; + } awb; }; } /* namespace ipa::ipu3 */ diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 7035802f..82506461 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -23,11 +23,11 @@ #include "libcamera/internal/framebuffer.h" #include "algorithms/algorithm.h" +#include "algorithms/awb.h" #include "algorithms/contrast.h" #include "ipa_context.h" #include "ipu3_agc.h" -#include "ipu3_awb.h" #include "libipa/camera_sensor_helper.h" static constexpr uint32_t kMaxCellWidthPerSet = 160; @@ -81,8 +81,6 @@ private: uint32_t minGain_; uint32_t maxGain_; - /* Interface to the AWB algorithm */ - std::unique_ptr awbAlgo_; /* Interface to the AEC/AGC algorithm */ std::unique_ptr agcAlgo_; /* Interface to the Camera Helper */ @@ -105,6 +103,7 @@ int IPAIPU3::init(const IPASettings &settings) } /* Construct our Algorithms */ + algorithms_.emplace_back(new algorithms::Awb()); algorithms_.emplace_back(new algorithms::Contrast()); /* Reset all the hardware settings */ @@ -138,7 +137,7 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) uint32_t minError = std::numeric_limits::max(); Size best; Size bestLog2; - bdsGrid_ = {}; + ipu3_uapi_grid_config &bdsGrid = context_.awb.grid.bdsGrid; for (uint32_t widthShift = 3; widthShift <= 7; ++widthShift) { uint32_t width = std::min(kMaxCellWidthPerSet, @@ -162,14 +161,14 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) } } - bdsGrid_.width = best.width >> bestLog2.width; - bdsGrid_.block_width_log2 = bestLog2.width; - bdsGrid_.height = best.height >> bestLog2.height; - bdsGrid_.block_height_log2 = bestLog2.height; + bdsGrid.width = best.width >> bestLog2.width; + bdsGrid.block_width_log2 = bestLog2.width; + bdsGrid.height = best.height >> bestLog2.height; + bdsGrid.block_height_log2 = bestLog2.height; LOG(IPAIPU3, Debug) << "Best grid found is: (" - << (int)bdsGrid_.width << " << " << (int)bdsGrid_.block_width_log2 << ") x (" - << (int)bdsGrid_.height << " << " << (int)bdsGrid_.block_height_log2 << ")"; + << (int)bdsGrid.width << " << " << (int)bdsGrid.block_width_log2 << ") x (" + << (int)bdsGrid.height << " << " << (int)bdsGrid.block_height_log2 << ")"; } int IPAIPU3::configure(const IPAConfigInfo &configInfo) @@ -211,13 +210,13 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) defVBlank_ = itVBlank->second.def().get(); + /* Prepare AWB parameters */ calculateBdsGrid(configInfo.bdsOutputSize); + context_.awb.grid.bdsOutputSize = configInfo.bdsOutputSize; configureAlgorithms(); - awbAlgo_ = std::make_unique(); - awbAlgo_->initialise(context_.params, configInfo.bdsOutputSize, bdsGrid_); - + bdsGrid_ = context_.awb.grid.bdsGrid; agcAlgo_ = std::make_unique(); agcAlgo_->initialise(bdsGrid_, sensorInfo_); @@ -293,9 +292,6 @@ void IPAIPU3::processControls([[maybe_unused]] unsigned int frame, void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params) { - if (agcAlgo_->updateControls()) - awbAlgo_->updateWbParameters(context_.params); - *params = context_.params; IPU3Action op; @@ -349,8 +345,6 @@ void IPAIPU3::parseStatistics(unsigned int frame, agcAlgo_->process(stats, exposure_, gain); gain_ = camHelper_->gainCode(gain); - awbAlgo_->calculateWBGains(stats); - if (agcAlgo_->updateControls()) setControls(frame); diff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build index fcb27d68..d1126947 100644 --- a/src/ipa/ipu3/meson.build +++ b/src/ipa/ipu3/meson.build @@ -7,7 +7,6 @@ ipa_name = 'ipa_ipu3' ipu3_ipa_sources = files([ 'ipu3.cpp', 'ipu3_agc.cpp', - 'ipu3_awb.cpp', ]) ipu3_ipa_sources += ipu3_ipa_algorithms From patchwork Mon Aug 9 09:20:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13256 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 E2043C3243 for ; Mon, 9 Aug 2021 09:20:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7791668894; Mon, 9 Aug 2021 11:20:21 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="W4lyKNZt"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BE25768826 for ; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:14c5:c0eb:b1fb:db22]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 79BF6EE; Mon, 9 Aug 2021 11:20:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628500816; bh=q3xLYhlQWLqVZGaLtxBXVXGidaoqPRlpYIJTIY6j2P4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W4lyKNZtBa7yNUA3XyizOJJOj4q1eSn0TE98Y7VLQb1ODLMMGDtsqTiv27uDzzRW9 cz4DhFHZhHkvVtyRPfy0XJr4DYsjKOEtAyYGwPN1E824HByLFE4nREZxpoCjb5B+Ei dt4zT2LQSCKWOhGO9cpAtgC1zcxKEfnehv5q7qE4= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Aug 2021 11:20:07 +0200 Message-Id: <20210809092007.79067-6-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> References: <20210809092007.79067-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 5/5] ipa: ipu3: Move IPU3 agc into algorithms 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" Use the Context class and algorithm interface to properly call the AGC algorithm from IPAIPU3. We need to pass shutter speed and analogue gain through Context. Add a dedicated AGC structure for that. Signed-off-by: Jean-Michel Hautbois --- .../ipu3/{ipu3_agc.cpp => algorithms/agc.cpp} | 56 ++++++++++--------- src/ipa/ipu3/{ipu3_agc.h => algorithms/agc.h} | 31 +++++----- src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipa_context.h | 11 ++++ src/ipa/ipu3/ipu3.cpp | 25 +++++---- src/ipa/ipu3/meson.build | 1 - 6 files changed, 70 insertions(+), 55 deletions(-) rename src/ipa/ipu3/{ipu3_agc.cpp => algorithms/agc.cpp} (81%) rename src/ipa/ipu3/{ipu3_agc.h => algorithms/agc.h} (61%) diff --git a/src/ipa/ipu3/ipu3_agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp similarity index 81% rename from src/ipa/ipu3/ipu3_agc.cpp rename to src/ipa/ipu3/algorithms/agc.cpp index 733814dd..1146a34a 100644 --- a/src/ipa/ipu3/ipu3_agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -2,26 +2,25 @@ /* * Copyright (C) 2021, Ideas On Board * - * ipu3_agc.cpp - AGC/AEC control algorithm + * agc.cpp - AGC/AEC control algorithm */ -#include "ipu3_agc.h" +#include "agc.h" -#include #include + +#include #include #include -#include - #include "libipa/histogram.h" namespace libcamera { using namespace std::literals::chrono_literals; -namespace ipa::ipu3 { +namespace ipa::ipu3::algorithms { LOG_DEFINE_CATEGORY(IPU3Agc) @@ -36,8 +35,8 @@ static constexpr uint32_t kMaxISO = 1500; /* Maximum analogue gain value * \todo grab it from a camera helper */ -static constexpr uint32_t kMinGain = kMinISO / 100; -static constexpr uint32_t kMaxGain = kMaxISO / 100; +static constexpr double kMinGain = kMinISO / 100; +static constexpr double kMaxGain = kMaxISO / 100; /* \todo use calculated value based on sensor */ static constexpr uint32_t kMinExposure = 1; @@ -50,24 +49,24 @@ static constexpr double kEvGainTarget = 0.5; /* A cell is 8 bytes and contains averages for RGB values and saturation ratio */ static constexpr uint8_t kCellSize = 8; -IPU3Agc::IPU3Agc() +Agc::Agc() : frameCount_(0), lastFrame_(0), converged_(false), - updateControls_(false), iqMean_(0.0), - lineDuration_(0s), maxExposureTime_(0s), + updateControls_(false), iqMean_(0.0), maxExposureTime_(0s), prevExposure_(0s), prevExposureNoDg_(0s), currentExposure_(0s), currentExposureNoDg_(0s) { } -void IPU3Agc::initialise(struct ipu3_uapi_grid_config &bdsGrid, const IPACameraSensorInfo &sensorInfo) +int Agc::configure(IPAContext &context) { - aeGrid_ = bdsGrid; + /* The AGC algorithm uses the AWB statistics */ + aeGrid_ = context.awb.grid.bdsGrid; + maxExposureTime_ = kMaxExposure * context.agc.lineDuration; - lineDuration_ = sensorInfo.lineLength * 1.0s / sensorInfo.pixelRate; - maxExposureTime_ = kMaxExposure * lineDuration_; + return 0; } -void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats) +void Agc::processBrightness(const ipu3_uapi_stats_3a *stats) { const struct ipu3_uapi_grid_config statsAeGrid = stats->stats_4a_config.awb_config.grid; Rectangle aeRegion = { statsAeGrid.x_start, @@ -108,7 +107,7 @@ void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats) iqMean_ = Histogram(Span(hist)).interQuantileMean(0.98, 1.0); } -void IPU3Agc::filterExposure() +void Agc::filterExposure() { double speed = 0.2; if (prevExposure_ == 0s) { @@ -128,7 +127,7 @@ void IPU3Agc::filterExposure() prevExposure_ = speed * currentExposure_ + prevExposure_ * (1.0 - speed); prevExposureNoDg_ = speed * currentExposureNoDg_ + - prevExposureNoDg_ * (1.0 - speed); + prevExposureNoDg_ * (1.0 - speed); } /* * We can't let the no_dg exposure deviate too far below the @@ -142,7 +141,7 @@ void IPU3Agc::filterExposure() LOG(IPU3Agc, Debug) << "After filtering, total_exposure " << prevExposure_; } -void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain) +void Agc::lockExposureGain(IPAContext &context) { updateControls_ = false; @@ -160,7 +159,9 @@ void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain) double newGain = kEvGainTarget * knumHistogramBins / iqMean_; /* extracted from Rpi::Agc::computeTargetExposure */ - libcamera::utils::Duration currentShutter = exposure * lineDuration_; + libcamera::utils::Duration currentShutter = context.agc.shutterTime; + uint32_t exposure = currentShutter / context.agc.lineDuration; + double &gain = context.agc.analogueGain; currentExposureNoDg_ = currentShutter * gain; LOG(IPU3Agc, Debug) << "Actual total exposure " << currentExposureNoDg_ << " Shutter speed " << currentShutter @@ -177,26 +178,27 @@ void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain) if (currentShutter < maxExposureTime_) { exposure = std::clamp(static_cast(exposure * currentExposure_ / currentExposureNoDg_), kMinExposure, kMaxExposure); newExposure = currentExposure_ / exposure; - gain = std::clamp(static_cast(gain * currentExposure_ / newExposure), kMinGain, kMaxGain); + gain = std::clamp(static_cast(gain * currentExposure_ / newExposure), kMinGain, kMaxGain); updateControls_ = true; } else if (currentShutter >= maxExposureTime_) { - gain = std::clamp(static_cast(gain * currentExposure_ / currentExposureNoDg_), kMinGain, kMaxGain); + gain = std::clamp(static_cast(gain * currentExposure_ / currentExposureNoDg_), kMinGain, kMaxGain); newExposure = currentExposure_ / gain; exposure = std::clamp(static_cast(exposure * currentExposure_ / newExposure), kMinExposure, kMaxExposure); updateControls_ = true; } - LOG(IPU3Agc, Debug) << "Adjust exposure " << exposure * lineDuration_ << " and gain " << gain; + context.agc.shutterTime = exposure * context.agc.lineDuration; + LOG(IPU3Agc, Debug) << "Adjust exposure " << exposure * context.agc.lineDuration << " and gain " << gain; } lastFrame_ = frameCount_; } -void IPU3Agc::process(const ipu3_uapi_stats_3a *stats, uint32_t &exposure, double &gain) +void Agc::process(IPAContext &context) { - processBrightness(stats); - lockExposureGain(exposure, gain); + processBrightness(context.stats); + lockExposureGain(context); frameCount_++; } -} /* namespace ipa::ipu3 */ +} /* namespace ipa::ipu3::algorithms */ } /* namespace libcamera */ diff --git a/src/ipa/ipu3/ipu3_agc.h b/src/ipa/ipu3/algorithms/agc.h similarity index 61% rename from src/ipa/ipu3/ipu3_agc.h rename to src/ipa/ipu3/algorithms/agc.h index 3b7f781e..e87a06f3 100644 --- a/src/ipa/ipu3/ipu3_agc.h +++ b/src/ipa/ipu3/algorithms/agc.h @@ -4,44 +4,44 @@ * * ipu3_agc.h - IPU3 AGC/AEC control algorithm */ -#ifndef __LIBCAMERA_IPU3_AGC_H__ -#define __LIBCAMERA_IPU3_AGC_H__ +#ifndef __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__ +#define __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__ + +#include #include #include -#include - #include #include -#include "algorithms/algorithm.h" -#include "libipa/algorithm.h" +#include "algorithm.h" namespace libcamera { struct IPACameraSensorInfo; -namespace ipa::ipu3 { +namespace ipa::ipu3::algorithms { using utils::Duration; -class IPU3Agc : public ipa::Algorithm +class Agc : public Algorithm { public: - IPU3Agc(); - ~IPU3Agc() = default; + Agc(); + ~Agc() = default; + + int configure(IPAContext &context) override; + void process(IPAContext &context) override; - void initialise(struct ipu3_uapi_grid_config &bdsGrid, const IPACameraSensorInfo &sensorInfo); - void process(const ipu3_uapi_stats_3a *stats, uint32_t &exposure, double &gain); bool converged() { return converged_; } bool updateControls() { return updateControls_; } private: void processBrightness(const ipu3_uapi_stats_3a *stats); void filterExposure(); - void lockExposureGain(uint32_t &exposure, double &gain); + void lockExposureGain(IPAContext &context); struct ipu3_uapi_grid_config aeGrid_; @@ -53,7 +53,6 @@ private: double iqMean_; - Duration lineDuration_; Duration maxExposureTime_; Duration prevExposure_; @@ -62,8 +61,8 @@ private: Duration currentExposureNoDg_; }; -} /* namespace ipa::ipu3 */ +} /* namespace ipa::ipu3::algorithms */ } /* namespace libcamera */ -#endif /* __LIBCAMERA_IPU3_AGC_H__ */ +#endif /* __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__ */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build index df36d719..3faf913e 100644 --- a/src/ipa/ipu3/algorithms/meson.build +++ b/src/ipa/ipu3/algorithms/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 ipu3_ipa_algorithms = files([ + 'agc.cpp', 'awb.cpp', 'contrast.cpp', ]) diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index c43b275b..1d7a1984 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -11,10 +11,14 @@ #include +#include + #include namespace libcamera { +using libcamera::utils::Duration; + namespace ipa::ipu3 { struct IPAContext { @@ -33,6 +37,13 @@ struct IPAContext { Size bdsOutputSize; } grid; } awb; + + /* AGC specific parameters to share */ + struct Agc { + Duration lineDuration; + Duration shutterTime; + double analogueGain; + } agc; }; } /* namespace ipa::ipu3 */ diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 82506461..07b1d11c 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -22,12 +22,12 @@ #include "libcamera/internal/framebuffer.h" +#include "algorithms/agc.h" #include "algorithms/algorithm.h" #include "algorithms/awb.h" #include "algorithms/contrast.h" #include "ipa_context.h" -#include "ipu3_agc.h" #include "libipa/camera_sensor_helper.h" static constexpr uint32_t kMaxCellWidthPerSet = 160; @@ -37,6 +37,8 @@ namespace libcamera { LOG_DEFINE_CATEGORY(IPAIPU3) +using namespace std::literals::chrono_literals; + namespace ipa::ipu3 { class IPAIPU3 : public IPAIPU3Interface @@ -81,8 +83,6 @@ private: uint32_t minGain_; uint32_t maxGain_; - /* Interface to the AEC/AGC algorithm */ - std::unique_ptr agcAlgo_; /* Interface to the Camera Helper */ std::unique_ptr camHelper_; @@ -103,6 +103,7 @@ int IPAIPU3::init(const IPASettings &settings) } /* Construct our Algorithms */ + algorithms_.emplace_back(new algorithms::Agc()); algorithms_.emplace_back(new algorithms::Awb()); algorithms_.emplace_back(new algorithms::Contrast()); @@ -214,11 +215,14 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) calculateBdsGrid(configInfo.bdsOutputSize); context_.awb.grid.bdsOutputSize = configInfo.bdsOutputSize; + /* Prepare AGC parameters */ + context_.agc.lineDuration = sensorInfo_.lineLength * 1.0s / sensorInfo_.pixelRate; + context_.agc.shutterTime = exposure_ * context_.agc.lineDuration; + context_.agc.analogueGain = camHelper_->gain(gain_); + configureAlgorithms(); bdsGrid_ = context_.awb.grid.bdsGrid; - agcAlgo_ = std::make_unique(); - agcAlgo_->initialise(bdsGrid_, sensorInfo_); return 0; } @@ -341,12 +345,7 @@ void IPAIPU3::parseStatistics(unsigned int frame, /* Run the process for each algorithm on the stats */ processAlgorithms(stats); - double gain = camHelper_->gain(gain_); - agcAlgo_->process(stats, exposure_, gain); - gain_ = camHelper_->gainCode(gain); - - if (agcAlgo_->updateControls()) - setControls(frame); + setControls(frame); /* \todo Use VBlank value calculated from each frame exposure. */ int64_t frameDuration = sensorInfo_.lineLength * (defVBlank_ + sensorInfo_.outputSize.height) / @@ -365,6 +364,10 @@ void IPAIPU3::setControls(unsigned int frame) IPU3Action op; op.op = ActionSetSensorControls; + /* Convert gain and exposure */ + gain_ = camHelper_->gainCode(context_.agc.analogueGain); + exposure_ = context_.agc.shutterTime / context_.agc.lineDuration; + ControlList ctrls(ctrls_); ctrls.set(V4L2_CID_EXPOSURE, static_cast(exposure_)); ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast(gain_)); diff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build index d1126947..39320980 100644 --- a/src/ipa/ipu3/meson.build +++ b/src/ipa/ipu3/meson.build @@ -6,7 +6,6 @@ ipa_name = 'ipa_ipu3' ipu3_ipa_sources = files([ 'ipu3.cpp', - 'ipu3_agc.cpp', ]) ipu3_ipa_sources += ipu3_ipa_algorithms