[{"id":30783,"web_url":"https://patchwork.libcamera.org/comment/30783/","msgid":"<54f736f8-65bd-431b-9844-6a50363f934f@ideasonboard.com>","date":"2024-08-13T10:02:39","subject":"Re: [PATCH v3 18/23] libcamera: software_isp: Move black level to an\n\talgorithm module","submitter":{"id":156,"url":"https://patchwork.libcamera.org/api/people/156/","name":"Dan Scally","email":"dan.scally@ideasonboard.com"},"content":"Hi Milan\n\nOn 17/07/2024 09:54, Milan Zamazal wrote:\n> The black level determination, already present as a separate class, can\n> be moved to the prepared Algorithm processing structure.  It is the\n> first of the current software ISP algorithms that is called in the stats\n> processing sequence, which means it is also the first one that should be\n> moved to the new structure.  Stats processing starts with calling\n> Algorithm-based processing so the call order of the algorithms is\n> retained.\n>\n> Movement of this algorithm is relatively straightforward because all it\n> does is processing stats.\n>\n> Black level is now recomputed on each stats processing.  In a future\n> patch, after DelayedControls are used, this will be changed to recompute\n> the black level only after exposure/gain changes.\n>\n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>\n> ---\n>   src/ipa/simple/algorithms/blc.cpp     | 71 ++++++++++++++++++++\n>   src/ipa/simple/algorithms/blc.h       | 37 +++++++++++\n>   src/ipa/simple/algorithms/meson.build |  1 +\n>   src/ipa/simple/black_level.cpp        | 93 ---------------------------\n>   src/ipa/simple/black_level.h          | 33 ----------\n>   src/ipa/simple/data/uncalibrated.yaml |  1 +\n>   src/ipa/simple/ipa_context.cpp        |  8 +++\n>   src/ipa/simple/ipa_context.h          |  5 ++\n>   src/ipa/simple/meson.build            |  1 -\n>   src/ipa/simple/soft_simple.cpp        |  8 +--\n>   10 files changed, 125 insertions(+), 133 deletions(-)\n>   create mode 100644 src/ipa/simple/algorithms/blc.cpp\n>   create mode 100644 src/ipa/simple/algorithms/blc.h\n>   delete mode 100644 src/ipa/simple/black_level.cpp\n>   delete mode 100644 src/ipa/simple/black_level.h\n>\n> diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp\n> new file mode 100644\n> index 00000000..3b73d830\n> --- /dev/null\n> +++ b/src/ipa/simple/algorithms/blc.cpp\n> @@ -0,0 +1,71 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2024, Red Hat Inc.\n> + *\n> + * Black level handling\n> + */\n> +\n> +#include \"blc.h\"\n> +\n> +#include <numeric>\n> +\n> +#include <libcamera/base/log.h>\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::soft::algorithms {\n> +\n> +LOG_DEFINE_CATEGORY(IPASoftBL)\n> +\n> +BlackLevel::BlackLevel()\n> +{\n> +}\n> +\n> +int BlackLevel::init(IPAContext &context,\n> +\t\t     [[maybe_unused]] const YamlObject &tuningData)\n> +{\n> +\tcontext.activeState.black.level = 255;\n> +\treturn 0;\n> +}\n\nThe removed comment from the defunct BlackLevel class says:\n\n- * Black level can be provided in hardware tuning files or, if no tuning file is - * available for \nthe given hardware, guessed automatically, with less accuracy. - * As tuning files are not yet \nimplemented for software ISP, BlackLevel - * currently provides only guessed black levels. Since \nmoving to the Algorithm based code includes tuning file support, can we take the opportunity to fix \nthat?\n\n> +\n> +void BlackLevel::process(IPAContext &context,\n> +\t\t\t [[maybe_unused]] const uint32_t frame,\n> +\t\t\t [[maybe_unused]] IPAFrameContext &frameContext,\n> +\t\t\t const SwIspStats *stats,\n> +\t\t\t [[maybe_unused]] ControlList &metadata)\n> +{\n> +\tconst SwIspStats::Histogram &histogram = stats->yHistogram;\n> +\n> +\t/*\n> +\t * The constant is selected to be \"good enough\", not overly conservative or\n> +\t * aggressive. There is no magic about the given value.\n> +\t */\n> +\tconstexpr float ignoredPercentage_ = 0.02;\n> +\tconst unsigned int total =\n> +\t\tstd::accumulate(begin(histogram), end(histogram), 0);\n> +\tconst unsigned int pixelThreshold = ignoredPercentage_ * total;\n> +\tconst unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;\n> +\tconst unsigned int currentBlackIdx =\n> +\t\tcontext.activeState.black.level / histogramRatio;\n> +\n> +\tfor (unsigned int i = 0, seen = 0;\n> +\t     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;\n> +\t     i++) {\n> +\t\tseen += histogram[i];\n> +\t\tif (seen >= pixelThreshold) {\n> +\t\t\tcontext.activeState.black.level = i * histogramRatio;\n> +\t\t\tLOG(IPASoftBL, Debug)\n> +\t\t\t\t<< \"Auto-set black level: \"\n> +\t\t\t\t<< i << \"/\" << SwIspStats::kYHistogramSize\n> +\t\t\t\t<< \" (\" << 100 * (seen - histogram[i]) / total << \"% below, \"\n> +\t\t\t\t<< 100 * seen / total << \"% at or below)\";\n> +\t\t\tbreak;\n> +\t\t}\n> +\t};\n> +}\n> +\n> +REGISTER_IPA_ALGORITHM(BlackLevel, \"BlackLevel\")\n> +\n> +} /* namespace ipa::soft::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/simple/algorithms/blc.h b/src/ipa/simple/algorithms/blc.h\n> new file mode 100644\n> index 00000000..2f73db52\n> --- /dev/null\n> +++ b/src/ipa/simple/algorithms/blc.h\n> @@ -0,0 +1,37 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2024, Red Hat Inc.\n> + *\n> + * Black level handling\n> + */\n> +\n> +#pragma once\n> +\n> +#include <libcamera/controls.h>\n> +\n> +#include \"libcamera/internal/software_isp/swisp_stats.h\"\n> +\n> +#include \"algorithm.h\"\n> +#include \"ipa_context.h\"\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::soft::algorithms {\n> +\n> +class BlackLevel : public Algorithm\n> +{\n> +public:\n> +\tBlackLevel();\n> +\t~BlackLevel() = default;\n> +\n> +\tint init(IPAContext &context, const YamlObject &tuningData)\n> +\t\toverride;\n> +\tvoid process(IPAContext &context, const uint32_t frame,\n> +\t\t     IPAFrameContext &frameContext,\n> +\t\t     const SwIspStats *stats,\n> +\t\t     ControlList &metadata) override;\n> +};\n> +\n> +} /* namespace ipa::soft::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build\n> index 31d26e43..1f63c220 100644\n> --- a/src/ipa/simple/algorithms/meson.build\n> +++ b/src/ipa/simple/algorithms/meson.build\n> @@ -1,4 +1,5 @@\n>   # SPDX-License-Identifier: CC0-1.0\n>   \n>   soft_simple_ipa_algorithms = files([\n> +    'blc.cpp',\n>   ])\n> diff --git a/src/ipa/simple/black_level.cpp b/src/ipa/simple/black_level.cpp\n> deleted file mode 100644\n> index 37e0109c..00000000\n> --- a/src/ipa/simple/black_level.cpp\n> +++ /dev/null\n> @@ -1,93 +0,0 @@\n> -/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> -/*\n> - * Copyright (C) 2024, Red Hat Inc.\n> - *\n> - * black level handling\n> - */\n> -\n> -#include \"black_level.h\"\n> -\n> -#include <numeric>\n> -\n> -#include <libcamera/base/log.h>\n> -\n> -namespace libcamera {\n> -\n> -LOG_DEFINE_CATEGORY(IPASoftBL)\n> -\n> -namespace ipa::soft {\n> -\n> -/**\n> - * \\class BlackLevel\n> - * \\brief Object providing black point level for software ISP\n> - *\n> - * Black level can be provided in hardware tuning files or, if no tuning file is\n> - * available for the given hardware, guessed automatically, with less accuracy.\n> - * As tuning files are not yet implemented for software ISP, BlackLevel\n> - * currently provides only guessed black levels.\n> - *\n> - * This class serves for tracking black level as a property of the underlying\n> - * hardware, not as means of enhancing a particular scene or image.\n> - *\n> - * The class is supposed to be instantiated for the given camera stream.\n> - * The black level can be retrieved using BlackLevel::get() method. It is\n> - * initially 0 and may change when updated using BlackLevel::update() method.\n> - */\n> -\n> -BlackLevel::BlackLevel()\n> -\t: blackLevel_(255), blackLevelSet_(false)\n> -{\n> -}\n> -\n> -/**\n> - * \\brief Return the current black level\n> - *\n> - * \\return The black level, in the range from 0 (minimum) to 255 (maximum).\n> - * If the black level couldn't be determined yet, return 0.\n> - */\n> -uint8_t BlackLevel::get() const\n> -{\n> -\treturn blackLevelSet_ ? blackLevel_ : 0;\n> -}\n> -\n> -/**\n> - * \\brief Update black level from the provided histogram\n> - * \\param[in] yHistogram The histogram to be used for updating black level\n> - *\n> - * The black level is property of the given hardware, not image. It is updated\n> - * only if it has not been yet set or if it is lower than the lowest value seen\n> - * so far.\n> - */\n> -void BlackLevel::update(SwIspStats::Histogram &yHistogram)\n> -{\n> -\t/*\n> -\t * The constant is selected to be \"good enough\", not overly conservative or\n> -\t * aggressive. There is no magic about the given value.\n> -\t */\n> -\tconstexpr float ignoredPercentage_ = 0.02;\n> -\tconst unsigned int total =\n> -\t\tstd::accumulate(begin(yHistogram), end(yHistogram), 0);\n> -\tconst unsigned int pixelThreshold = ignoredPercentage_ * total;\n> -\tconst unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;\n> -\tconst unsigned int currentBlackIdx = blackLevel_ / histogramRatio;\n> -\n> -\tfor (unsigned int i = 0, seen = 0;\n> -\t     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;\n> -\t     i++) {\n> -\t\tseen += yHistogram[i];\n> -\t\tif (seen >= pixelThreshold) {\n> -\t\t\tblackLevel_ = i * histogramRatio;\n> -\t\t\tblackLevelSet_ = true;\n> -\t\t\tLOG(IPASoftBL, Debug)\n> -\t\t\t\t<< \"Auto-set black level: \"\n> -\t\t\t\t<< i << \"/\" << SwIspStats::kYHistogramSize\n> -\t\t\t\t<< \" (\" << 100 * (seen - yHistogram[i]) / total << \"% below, \"\n> -\t\t\t\t<< 100 * seen / total << \"% at or below)\";\n> -\t\t\tbreak;\n> -\t\t}\n> -\t};\n> -}\n> -\n> -} /* namespace ipa::soft */\n> -\n> -} /* namespace libcamera */\n> diff --git a/src/ipa/simple/black_level.h b/src/ipa/simple/black_level.h\n> deleted file mode 100644\n> index a04230c9..00000000\n> --- a/src/ipa/simple/black_level.h\n> +++ /dev/null\n> @@ -1,33 +0,0 @@\n> -/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> -/*\n> - * Copyright (C) 2024, Red Hat Inc.\n> - *\n> - * black level handling\n> - */\n> -\n> -#pragma once\n> -\n> -#include <array>\n> -#include <stdint.h>\n> -\n> -#include \"libcamera/internal/software_isp/swisp_stats.h\"\n> -\n> -namespace libcamera {\n> -\n> -namespace ipa::soft {\n> -\n> -class BlackLevel\n> -{\n> -public:\n> -\tBlackLevel();\n> -\tuint8_t get() const;\n> -\tvoid update(SwIspStats::Histogram &yHistogram);\n> -\n> -private:\n> -\tuint8_t blackLevel_;\n> -\tbool blackLevelSet_;\n> -};\n> -\n> -} /* namespace ipa::soft */\n> -\n> -} /* namespace libcamera */\n> diff --git a/src/ipa/simple/data/uncalibrated.yaml b/src/ipa/simple/data/uncalibrated.yaml\n> index 2cdc39a8..e0d03d96 100644\n> --- a/src/ipa/simple/data/uncalibrated.yaml\n> +++ b/src/ipa/simple/data/uncalibrated.yaml\n> @@ -3,4 +3,5 @@\n>   ---\n>   version: 1\n>   algorithms:\n> +  - BlackLevel:\n>   ...\n> diff --git a/src/ipa/simple/ipa_context.cpp b/src/ipa/simple/ipa_context.cpp\n> index 3c1c7262..268cff32 100644\n> --- a/src/ipa/simple/ipa_context.cpp\n> +++ b/src/ipa/simple/ipa_context.cpp\n> @@ -50,4 +50,12 @@ namespace libcamera::ipa::soft {\n>    * \\brief The current state of IPA algorithms\n>    */\n>   \n> +/**\n> + * \\var IPAActiveState::black\n> + * \\brief Context for the Black Level algorithm\n> + *\n> + * \\var IPAActiveState::black.level\n> + * \\brief Current determined black level\n> + */\n> +\n>   } /* namespace libcamera::ipa::soft */\n> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n> index bc1235b6..ed07dbb8 100644\n> --- a/src/ipa/simple/ipa_context.h\n> +++ b/src/ipa/simple/ipa_context.h\n> @@ -8,6 +8,8 @@\n>   \n>   #pragma once\n>   \n> +#include <stdint.h>\n> +\n>   #include <libipa/fc_queue.h>\n>   \n>   namespace libcamera {\n> @@ -18,6 +20,9 @@ struct IPASessionConfiguration {\n>   };\n>   \n>   struct IPAActiveState {\n> +\tstruct {\n> +\t\tuint8_t level;\n> +\t} black;\n>   };\n>   \n>   struct IPAFrameContext : public FrameContext {\n> diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build\n> index 7515a8d8..92aa5744 100644\n> --- a/src/ipa/simple/meson.build\n> +++ b/src/ipa/simple/meson.build\n> @@ -8,7 +8,6 @@ ipa_name = 'ipa_soft_simple'\n>   soft_simple_sources = files([\n>       'ipa_context.cpp',\n>       'soft_simple.cpp',\n> -    'black_level.cpp',\n>   ])\n>   \n>   soft_simple_sources += soft_simple_ipa_algorithms\n> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n> index a8499f29..2fb3a473 100644\n> --- a/src/ipa/simple/soft_simple.cpp\n> +++ b/src/ipa/simple/soft_simple.cpp\n> @@ -28,7 +28,6 @@\n>   \n>   #include \"libipa/camera_sensor_helper.h\"\n>   \n> -#include \"black_level.h\"\n>   #include \"module.h\"\n>   \n>   namespace libcamera {\n> @@ -60,7 +59,7 @@ class IPASoftSimple : public ipa::soft::IPASoftInterface, public Module\n>   {\n>   public:\n>   \tIPASoftSimple()\n> -\t\t: params_(nullptr), stats_(nullptr), blackLevel_(BlackLevel()),\n> +\t\t: params_(nullptr), stats_(nullptr),\n>   \t\t  context_({ {}, {}, { kMaxFrameContexts } }),\n>   \t\t  ignoreUpdates_(0)\n>   \t{\n> @@ -92,7 +91,6 @@ private:\n>   \tSwIspStats *stats_;\n>   \tstd::unique_ptr<CameraSensorHelper> camHelper_;\n>   \tControlInfoMap sensorInfoMap_;\n> -\tBlackLevel blackLevel_;\n>   \n>   \tstatic constexpr unsigned int kGammaLookupSize = 1024;\n>   \tstd::array<uint8_t, kGammaLookupSize> gammaTable_;\n> @@ -303,9 +301,7 @@ void IPASoftSimple::processStats(\n>   \t\talgo->process(context_, frame, frameContext, stats_, metadata);\n>   \n>   \tSwIspStats::Histogram histogram = stats_->yHistogram;\n> -\tif (ignoreUpdates_ > 0)\n> -\t\tblackLevel_.update(histogram);\n> -\tconst uint8_t blackLevel = blackLevel_.get();\n> +\tconst uint8_t blackLevel = context_.activeState.black.level;\n>   \n>   \t/*\n>   \t * Black level must be subtracted to get the correct AWB ratios, they","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 0D923BDB13\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 13 Aug 2024 10:02:45 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1A24863382;\n\tTue, 13 Aug 2024 12:02:44 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1639E63382\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Aug 2024 12:02:42 +0200 (CEST)","from [192.168.0.43]\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id BEF30220\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Aug 2024 12:01:44 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"l9QMOJgG\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1723543304;\n\tbh=JaGLq3P6og9VVtFjFIISAdkJ024ll8sVOYOQI+Ss10Y=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=l9QMOJgGOyl/lUOJicHaS8iTtnpqMO+T+sXBkQEekyIIW3KEmRA3gGcCNxK/Mr3lu\n\tb2KSnKI5iXin+wbtrcq5Ix9LvAj4X30RcGUHi6XDTkyein6GRc3xO0gM+/mT9+QnwZ\n\tDIdg5Mf/0qTpWezq5sn8cdW/tUHX3Di/VB/at9gw=","Message-ID":"<54f736f8-65bd-431b-9844-6a50363f934f@ideasonboard.com>","Date":"Tue, 13 Aug 2024 11:02:39 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 18/23] libcamera: software_isp: Move black level to an\n\talgorithm module","To":"libcamera-devel@lists.libcamera.org","References":"<20240717085444.289997-1-mzamazal@redhat.com>\n\t<20240717085444.289997-19-mzamazal@redhat.com>","Content-Language":"en-US","From":"Dan Scally <dan.scally@ideasonboard.com>","Autocrypt":"addr=dan.scally@ideasonboard.com; keydata=\n\t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","In-Reply-To":"<20240717085444.289997-19-mzamazal@redhat.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":30786,"web_url":"https://patchwork.libcamera.org/comment/30786/","msgid":"<87h6boy95g.fsf@redhat.com>","date":"2024-08-13T11:06:19","subject":"Re: [PATCH v3 18/23] libcamera: software_isp: Move black level to\n\tan algorithm module","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Dan,\n\nthank you for review.\n\nDan Scally <dan.scally@ideasonboard.com> writes:\n\n> Hi Milan\n>\n> On 17/07/2024 09:54, Milan Zamazal wrote:\n>> The black level determination, already present as a separate class, can\n>> be moved to the prepared Algorithm processing structure.  It is the\n>> first of the current software ISP algorithms that is called in the stats\n>> processing sequence, which means it is also the first one that should be\n>> moved to the new structure.  Stats processing starts with calling\n>> Algorithm-based processing so the call order of the algorithms is\n>> retained.\n>>\n>> Movement of this algorithm is relatively straightforward because all it\n>> does is processing stats.\n>>\n>> Black level is now recomputed on each stats processing.  In a future\n>> patch, after DelayedControls are used, this will be changed to recompute\n>> the black level only after exposure/gain changes.\n>>\n>> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n>> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>\n>> ---\n>>   src/ipa/simple/algorithms/blc.cpp     | 71 ++++++++++++++++++++\n>>   src/ipa/simple/algorithms/blc.h       | 37 +++++++++++\n>>   src/ipa/simple/algorithms/meson.build |  1 +\n>>   src/ipa/simple/black_level.cpp        | 93 ---------------------------\n>>   src/ipa/simple/black_level.h          | 33 ----------\n>>   src/ipa/simple/data/uncalibrated.yaml |  1 +\n>>   src/ipa/simple/ipa_context.cpp        |  8 +++\n>>   src/ipa/simple/ipa_context.h          |  5 ++\n>>   src/ipa/simple/meson.build            |  1 -\n>>   src/ipa/simple/soft_simple.cpp        |  8 +--\n>>   10 files changed, 125 insertions(+), 133 deletions(-)\n>>   create mode 100644 src/ipa/simple/algorithms/blc.cpp\n>>   create mode 100644 src/ipa/simple/algorithms/blc.h\n>>   delete mode 100644 src/ipa/simple/black_level.cpp\n>>   delete mode 100644 src/ipa/simple/black_level.h\n>>\n>> diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp\n>> new file mode 100644\n>> index 00000000..3b73d830\n>> --- /dev/null\n>> +++ b/src/ipa/simple/algorithms/blc.cpp\n>> @@ -0,0 +1,71 @@\n>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n>> +/*\n>> + * Copyright (C) 2024, Red Hat Inc.\n>> + *\n>> + * Black level handling\n>> + */\n>> +\n>> +#include \"blc.h\"\n>> +\n>> +#include <numeric>\n>> +\n>> +#include <libcamera/base/log.h>\n>> +\n>> +namespace libcamera {\n>> +\n>> +namespace ipa::soft::algorithms {\n>> +\n>> +LOG_DEFINE_CATEGORY(IPASoftBL)\n>> +\n>> +BlackLevel::BlackLevel()\n>> +{\n>> +}\n>> +\n>> +int BlackLevel::init(IPAContext &context,\n>> +\t\t     [[maybe_unused]] const YamlObject &tuningData)\n>> +{\n>> +\tcontext.activeState.black.level = 255;\n>> +\treturn 0;\n>> +}\n>\n> The removed comment from the defunct BlackLevel class says:\n>\n> - * Black level can be provided in hardware tuning files or, if no tuning file is - * available for the given hardware, guessed automatically,\n>     with less accuracy. - * As tuning files are not yet implemented for software ISP, BlackLevel - * currently provides only guessed black\n>     levels. Since moving to the Algorithm based code includes tuning\n> file support, can we take the opportunity to fix that?\n\nCameraSensorHelper has been enhanced with blackLevel() recently, which\nas I understand it is preferred to reading this information from tuning\nfiles.  I have a patch that uses CameraSensorHelper in the sense\ndescribed above and I can post it on top of v4 or as a part of it.  I\nthink the former is preferable as this series is already long enough.\nI'll mention it in the updated commit message.\n\n>> +\n>> +void BlackLevel::process(IPAContext &context,\n>> +\t\t\t [[maybe_unused]] const uint32_t frame,\n>> +\t\t\t [[maybe_unused]] IPAFrameContext &frameContext,\n>> +\t\t\t const SwIspStats *stats,\n>> +\t\t\t [[maybe_unused]] ControlList &metadata)\n>> +{\n>> +\tconst SwIspStats::Histogram &histogram = stats->yHistogram;\n>> +\n>> +\t/*\n>> +\t * The constant is selected to be \"good enough\", not overly conservative or\n>> +\t * aggressive. There is no magic about the given value.\n>> +\t */\n>> +\tconstexpr float ignoredPercentage_ = 0.02;\n>> +\tconst unsigned int total =\n>> +\t\tstd::accumulate(begin(histogram), end(histogram), 0);\n>> +\tconst unsigned int pixelThreshold = ignoredPercentage_ * total;\n>> +\tconst unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;\n>> +\tconst unsigned int currentBlackIdx =\n>> +\t\tcontext.activeState.black.level / histogramRatio;\n>> +\n>> +\tfor (unsigned int i = 0, seen = 0;\n>> +\t     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;\n>> +\t     i++) {\n>> +\t\tseen += histogram[i];\n>> +\t\tif (seen >= pixelThreshold) {\n>> +\t\t\tcontext.activeState.black.level = i * histogramRatio;\n>> +\t\t\tLOG(IPASoftBL, Debug)\n>> +\t\t\t\t<< \"Auto-set black level: \"\n>> +\t\t\t\t<< i << \"/\" << SwIspStats::kYHistogramSize\n>> +\t\t\t\t<< \" (\" << 100 * (seen - histogram[i]) / total << \"% below, \"\n>> +\t\t\t\t<< 100 * seen / total << \"% at or below)\";\n>> +\t\t\tbreak;\n>> +\t\t}\n>> +\t};\n>> +}\n>> +\n>> +REGISTER_IPA_ALGORITHM(BlackLevel, \"BlackLevel\")\n>> +\n>> +} /* namespace ipa::soft::algorithms */\n>> +\n>> +} /* namespace libcamera */\n>> diff --git a/src/ipa/simple/algorithms/blc.h b/src/ipa/simple/algorithms/blc.h\n>> new file mode 100644\n>> index 00000000..2f73db52\n>> --- /dev/null\n>> +++ b/src/ipa/simple/algorithms/blc.h\n>> @@ -0,0 +1,37 @@\n>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n>> +/*\n>> + * Copyright (C) 2024, Red Hat Inc.\n>> + *\n>> + * Black level handling\n>> + */\n>> +\n>> +#pragma once\n>> +\n>> +#include <libcamera/controls.h>\n>> +\n>> +#include \"libcamera/internal/software_isp/swisp_stats.h\"\n>> +\n>> +#include \"algorithm.h\"\n>> +#include \"ipa_context.h\"\n>> +\n>> +namespace libcamera {\n>> +\n>> +namespace ipa::soft::algorithms {\n>> +\n>> +class BlackLevel : public Algorithm\n>> +{\n>> +public:\n>> +\tBlackLevel();\n>> +\t~BlackLevel() = default;\n>> +\n>> +\tint init(IPAContext &context, const YamlObject &tuningData)\n>> +\t\toverride;\n>> +\tvoid process(IPAContext &context, const uint32_t frame,\n>> +\t\t     IPAFrameContext &frameContext,\n>> +\t\t     const SwIspStats *stats,\n>> +\t\t     ControlList &metadata) override;\n>> +};\n>> +\n>> +} /* namespace ipa::soft::algorithms */\n>> +\n>> +} /* namespace libcamera */\n>> diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build\n>> index 31d26e43..1f63c220 100644\n>> --- a/src/ipa/simple/algorithms/meson.build\n>> +++ b/src/ipa/simple/algorithms/meson.build\n>> @@ -1,4 +1,5 @@\n>>   # SPDX-License-Identifier: CC0-1.0\n>>     soft_simple_ipa_algorithms = files([\n>> +    'blc.cpp',\n>>   ])\n>> diff --git a/src/ipa/simple/black_level.cpp b/src/ipa/simple/black_level.cpp\n>> deleted file mode 100644\n>> index 37e0109c..00000000\n>> --- a/src/ipa/simple/black_level.cpp\n>> +++ /dev/null\n>> @@ -1,93 +0,0 @@\n>> -/* SPDX-License-Identifier: LGPL-2.1-or-later */\n>> -/*\n>> - * Copyright (C) 2024, Red Hat Inc.\n>> - *\n>> - * black level handling\n>> - */\n>> -\n>> -#include \"black_level.h\"\n>> -\n>> -#include <numeric>\n>> -\n>> -#include <libcamera/base/log.h>\n>> -\n>> -namespace libcamera {\n>> -\n>> -LOG_DEFINE_CATEGORY(IPASoftBL)\n>> -\n>> -namespace ipa::soft {\n>> -\n>> -/**\n>> - * \\class BlackLevel\n>> - * \\brief Object providing black point level for software ISP\n>> - *\n>> - * Black level can be provided in hardware tuning files or, if no tuning file is\n>> - * available for the given hardware, guessed automatically, with less accuracy.\n>> - * As tuning files are not yet implemented for software ISP, BlackLevel\n>> - * currently provides only guessed black levels.\n>> - *\n>> - * This class serves for tracking black level as a property of the underlying\n>> - * hardware, not as means of enhancing a particular scene or image.\n>> - *\n>> - * The class is supposed to be instantiated for the given camera stream.\n>> - * The black level can be retrieved using BlackLevel::get() method. It is\n>> - * initially 0 and may change when updated using BlackLevel::update() method.\n>> - */\n>> -\n>> -BlackLevel::BlackLevel()\n>> -\t: blackLevel_(255), blackLevelSet_(false)\n>> -{\n>> -}\n>> -\n>> -/**\n>> - * \\brief Return the current black level\n>> - *\n>> - * \\return The black level, in the range from 0 (minimum) to 255 (maximum).\n>> - * If the black level couldn't be determined yet, return 0.\n>> - */\n>> -uint8_t BlackLevel::get() const\n>> -{\n>> -\treturn blackLevelSet_ ? blackLevel_ : 0;\n>> -}\n>> -\n>> -/**\n>> - * \\brief Update black level from the provided histogram\n>> - * \\param[in] yHistogram The histogram to be used for updating black level\n>> - *\n>> - * The black level is property of the given hardware, not image. It is updated\n>> - * only if it has not been yet set or if it is lower than the lowest value seen\n>> - * so far.\n>> - */\n>> -void BlackLevel::update(SwIspStats::Histogram &yHistogram)\n>> -{\n>> -\t/*\n>> -\t * The constant is selected to be \"good enough\", not overly conservative or\n>> -\t * aggressive. There is no magic about the given value.\n>> -\t */\n>> -\tconstexpr float ignoredPercentage_ = 0.02;\n>> -\tconst unsigned int total =\n>> -\t\tstd::accumulate(begin(yHistogram), end(yHistogram), 0);\n>> -\tconst unsigned int pixelThreshold = ignoredPercentage_ * total;\n>> -\tconst unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;\n>> -\tconst unsigned int currentBlackIdx = blackLevel_ / histogramRatio;\n>> -\n>> -\tfor (unsigned int i = 0, seen = 0;\n>> -\t     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;\n>> -\t     i++) {\n>> -\t\tseen += yHistogram[i];\n>> -\t\tif (seen >= pixelThreshold) {\n>> -\t\t\tblackLevel_ = i * histogramRatio;\n>> -\t\t\tblackLevelSet_ = true;\n>> -\t\t\tLOG(IPASoftBL, Debug)\n>> -\t\t\t\t<< \"Auto-set black level: \"\n>> -\t\t\t\t<< i << \"/\" << SwIspStats::kYHistogramSize\n>> -\t\t\t\t<< \" (\" << 100 * (seen - yHistogram[i]) / total << \"% below, \"\n>> -\t\t\t\t<< 100 * seen / total << \"% at or below)\";\n>> -\t\t\tbreak;\n>> -\t\t}\n>> -\t};\n>> -}\n>> -\n>> -} /* namespace ipa::soft */\n>> -\n>> -} /* namespace libcamera */\n>> diff --git a/src/ipa/simple/black_level.h b/src/ipa/simple/black_level.h\n>> deleted file mode 100644\n>> index a04230c9..00000000\n>> --- a/src/ipa/simple/black_level.h\n>> +++ /dev/null\n>> @@ -1,33 +0,0 @@\n>> -/* SPDX-License-Identifier: LGPL-2.1-or-later */\n>> -/*\n>> - * Copyright (C) 2024, Red Hat Inc.\n>> - *\n>> - * black level handling\n>> - */\n>> -\n>> -#pragma once\n>> -\n>> -#include <array>\n>> -#include <stdint.h>\n>> -\n>> -#include \"libcamera/internal/software_isp/swisp_stats.h\"\n>> -\n>> -namespace libcamera {\n>> -\n>> -namespace ipa::soft {\n>> -\n>> -class BlackLevel\n>> -{\n>> -public:\n>> -\tBlackLevel();\n>> -\tuint8_t get() const;\n>> -\tvoid update(SwIspStats::Histogram &yHistogram);\n>> -\n>> -private:\n>> -\tuint8_t blackLevel_;\n>> -\tbool blackLevelSet_;\n>> -};\n>> -\n>> -} /* namespace ipa::soft */\n>> -\n>> -} /* namespace libcamera */\n>> diff --git a/src/ipa/simple/data/uncalibrated.yaml b/src/ipa/simple/data/uncalibrated.yaml\n>> index 2cdc39a8..e0d03d96 100644\n>> --- a/src/ipa/simple/data/uncalibrated.yaml\n>> +++ b/src/ipa/simple/data/uncalibrated.yaml\n>> @@ -3,4 +3,5 @@\n>>   ---\n>>   version: 1\n>>   algorithms:\n>> +  - BlackLevel:\n>>   ...\n>> diff --git a/src/ipa/simple/ipa_context.cpp b/src/ipa/simple/ipa_context.cpp\n>> index 3c1c7262..268cff32 100644\n>> --- a/src/ipa/simple/ipa_context.cpp\n>> +++ b/src/ipa/simple/ipa_context.cpp\n>> @@ -50,4 +50,12 @@ namespace libcamera::ipa::soft {\n>>    * \\brief The current state of IPA algorithms\n>>    */\n>>   +/**\n>> + * \\var IPAActiveState::black\n>> + * \\brief Context for the Black Level algorithm\n>> + *\n>> + * \\var IPAActiveState::black.level\n>> + * \\brief Current determined black level\n>> + */\n>> +\n>>   } /* namespace libcamera::ipa::soft */\n>> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n>> index bc1235b6..ed07dbb8 100644\n>> --- a/src/ipa/simple/ipa_context.h\n>> +++ b/src/ipa/simple/ipa_context.h\n>> @@ -8,6 +8,8 @@\n>>     #pragma once\n>>   +#include <stdint.h>\n>> +\n>>   #include <libipa/fc_queue.h>\n>>     namespace libcamera {\n>> @@ -18,6 +20,9 @@ struct IPASessionConfiguration {\n>>   };\n>>     struct IPAActiveState {\n>> +\tstruct {\n>> +\t\tuint8_t level;\n>> +\t} black;\n>>   };\n>>     struct IPAFrameContext : public FrameContext {\n>> diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build\n>> index 7515a8d8..92aa5744 100644\n>> --- a/src/ipa/simple/meson.build\n>> +++ b/src/ipa/simple/meson.build\n>> @@ -8,7 +8,6 @@ ipa_name = 'ipa_soft_simple'\n>>   soft_simple_sources = files([\n>>       'ipa_context.cpp',\n>>       'soft_simple.cpp',\n>> -    'black_level.cpp',\n>>   ])\n>>     soft_simple_sources += soft_simple_ipa_algorithms\n>> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n>> index a8499f29..2fb3a473 100644\n>> --- a/src/ipa/simple/soft_simple.cpp\n>> +++ b/src/ipa/simple/soft_simple.cpp\n>> @@ -28,7 +28,6 @@\n>>     #include \"libipa/camera_sensor_helper.h\"\n>>   -#include \"black_level.h\"\n>>   #include \"module.h\"\n>>     namespace libcamera {\n>> @@ -60,7 +59,7 @@ class IPASoftSimple : public ipa::soft::IPASoftInterface, public Module\n>>   {\n>>   public:\n>>   \tIPASoftSimple()\n>> -\t\t: params_(nullptr), stats_(nullptr), blackLevel_(BlackLevel()),\n>> +\t\t: params_(nullptr), stats_(nullptr),\n>>   \t\t  context_({ {}, {}, { kMaxFrameContexts } }),\n>>   \t\t  ignoreUpdates_(0)\n>>   \t{\n>> @@ -92,7 +91,6 @@ private:\n>>   \tSwIspStats *stats_;\n>>   \tstd::unique_ptr<CameraSensorHelper> camHelper_;\n>>   \tControlInfoMap sensorInfoMap_;\n>> -\tBlackLevel blackLevel_;\n>>     \tstatic constexpr unsigned int kGammaLookupSize = 1024;\n>>   \tstd::array<uint8_t, kGammaLookupSize> gammaTable_;\n>> @@ -303,9 +301,7 @@ void IPASoftSimple::processStats(\n>>   \t\talgo->process(context_, frame, frameContext, stats_, metadata);\n>>     \tSwIspStats::Histogram histogram = stats_->yHistogram;\n>> -\tif (ignoreUpdates_ > 0)\n>> -\t\tblackLevel_.update(histogram);\n>> -\tconst uint8_t blackLevel = blackLevel_.get();\n>> +\tconst uint8_t blackLevel = context_.activeState.black.level;\n>>     \t/*\n>>   \t * Black level must be subtracted to get the correct AWB ratios, they","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id DE8D3C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 13 Aug 2024 11:06:31 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A6FB3633B9;\n\tTue, 13 Aug 2024 13:06:30 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CDC5F63398\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Aug 2024 13:06:27 +0200 (CEST)","from mail-wm1-f71.google.com (mail-wm1-f71.google.com\n\t[209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-351-q9XvXQkcMrK8ExwvKFzXzQ-1; Tue, 13 Aug 2024 07:06:23 -0400","by mail-wm1-f71.google.com with SMTP id\n\t5b1f17b1804b1-427ffa0c9c7so61780985e9.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Aug 2024 04:06:22 -0700 (PDT)","from nuthatch (nat-pool-brq-t.redhat.com. [213.175.37.10])\n\tby smtp.gmail.com with ESMTPSA id\n\t5b1f17b1804b1-429c776074asm134718925e9.48.2024.08.13.04.06.20\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tTue, 13 Aug 2024 04:06:20 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"iqoR4IKC\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1723547186;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=m8P8MYFQVLDqPqhGAEJ8oHX0F+PKQR1dnV80RSO+2nQ=;\n\tb=iqoR4IKCFXH9/A1KFD/RoO+mXqh3PfhWiHve8oFcEAQPhG/QvAuHIjAn9J1CGj3dlOj6GJ\n\t/vcIF8BVLN59CJrB+81lNIw4MQMtt8Kvlyuk6xwAPRaB+wH+go6qWC3cl1fCPH5/MrhFIf\n\t5nd7Zm+BVgciHlB3bDLh1vPdJmuV94s=","X-MC-Unique":"q9XvXQkcMrK8ExwvKFzXzQ-1","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1723547181; x=1724151981;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=m8P8MYFQVLDqPqhGAEJ8oHX0F+PKQR1dnV80RSO+2nQ=;\n\tb=N9XmmPp2/9b+TaDv8P4tgWDIHhNfQ7DykhxUCXKyHa1kV6RGlgD9Ivoq6Bma6zLkyd\n\ttCQABz3rUX8W9PoMEYmWLBBQgxzOZ2BIbZchDveNxIM3GNnHN54nsv5NYsa2mFgsKemi\n\t+N2d5LB4K2hoC7M09nlIZtJ1PgwYz+naj5pwwylVD9R8LI7wGJ2//NkHxrY5kbHdloOx\n\t08RX3WGPDvtIu+V/oVNFyoWBL9GdFogLdYln+LXhLSVEvZDR/d/N1AdMzxduOvCCtYlQ\n\tU8lfbBzFB+CW/SnSUlFE3Fn1oyAlxDp+tAAFkg/BsjiLraLrRyqL1xb2zWMenOeLUck6\n\tffdg==","X-Gm-Message-State":"AOJu0Yyi4az/GLALQZ/GZQzbDuwH8j6UgmR/ZBYWWKtAkgSwHfaSuTvJ\n\tt5+ree9OPCGA4CDjiDjk1weZ0p1Q+mrqqZK2Hrp5ea+o+yXma0I9ND/bkNQ2J3nWLAHcnQX2Gsh\n\tZPgBh44EfBWS6YM+mdcO9PIZxYvqlwR/+GBrbixheNYi2P2la60M67J+6YzAZHHab7lPRkSuWXf\n\tYk3LxcZ1BA4H1jsJ0/8qL9x9qFRL8F5+SI9F0ukmpKjL8hmlRusLEfEcY=","X-Received":["by 2002:a05:600c:1546:b0:428:15b0:c8dd with SMTP id\n\t5b1f17b1804b1-429d4819beamr36284045e9.20.1723547181469; \n\tTue, 13 Aug 2024 04:06:21 -0700 (PDT)","by 2002:a05:600c:1546:b0:428:15b0:c8dd with SMTP id\n\t5b1f17b1804b1-429d4819beamr36283685e9.20.1723547180903; \n\tTue, 13 Aug 2024 04:06:20 -0700 (PDT)"],"X-Google-Smtp-Source":"AGHT+IEtIMzYCiIKUMUsTV5mlwmoPiw6djBvqPLLhzuD6gsqvgbNwvj5UmzcbjEj3x6pUVXKH+GglQ==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Dan Scally <dan.scally@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v3 18/23] libcamera: software_isp: Move black level to\n\tan algorithm module","In-Reply-To":"<54f736f8-65bd-431b-9844-6a50363f934f@ideasonboard.com> (Dan\n\tScally's message of \"Tue, 13 Aug 2024 11:02:39 +0100\")","References":"<20240717085444.289997-1-mzamazal@redhat.com>\n\t<20240717085444.289997-19-mzamazal@redhat.com>\n\t<54f736f8-65bd-431b-9844-6a50363f934f@ideasonboard.com>","Date":"Tue, 13 Aug 2024 13:06:19 +0200","Message-ID":"<87h6boy95g.fsf@redhat.com>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]