[{"id":24578,"web_url":"https://patchwork.libcamera.org/comment/24578/","msgid":"<fe119c11-ef12-13ad-da80-65ec11809098@ideasonboard.com>","date":"2022-08-15T15:52:12","subject":"Re: [libcamera-devel] [PATCH v3 3/3] ipa: rkisp1: Add support of\n\tDenoise Pre-Filter control","submitter":{"id":86,"url":"https://patchwork.libcamera.org/api/people/86/","name":"Umang Jain","email":"umang.jain@ideasonboard.com"},"content":"Hi Laurent, Florian\n\nThank you for the patch\n\nOn 8/13/22 04:03, Laurent Pinchart via libcamera-devel wrote:\n> From: Florian Sylvestre <fsylvestre@baylibre.com>\n>\n> The denoise pre-filter algorithm is a bilateral filter which combines a range\n> filter and a domain filter. The denoise pre-filter is applied before\n> demosaicing.\n>\n> Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n> Changes since v2:\n>\n> - Change the scope of some variables in Dpf::prepare()\n> - Line-wrap coefficients in tuning file\n> ---\n>   src/ipa/rkisp1/algorithms/dpf.cpp     | 249 ++++++++++++++++++++++++++\n>   src/ipa/rkisp1/algorithms/dpf.h       |  36 ++++\n>   src/ipa/rkisp1/algorithms/meson.build |   1 +\n>   src/ipa/rkisp1/data/ov5640.yaml       |  15 ++\n>   src/ipa/rkisp1/ipa_context.cpp        |  11 ++\n>   src/ipa/rkisp1/ipa_context.h          |   5 +\n>   6 files changed, 317 insertions(+)\n>   create mode 100644 src/ipa/rkisp1/algorithms/dpf.cpp\n>   create mode 100644 src/ipa/rkisp1/algorithms/dpf.h\n>\n> diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\n> new file mode 100644\n> index 000000000000..33fe3066b9e3\n> --- /dev/null\n> +++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n> @@ -0,0 +1,249 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2021-2022, Ideas On Board\n> + *\n> + * dpf.cpp - RkISP1 Denoise Pre-Filter control\n> + */\n> +\n> +#include \"dpf.h\"\n> +\n> +#include <cmath>\n> +\n> +#include <libcamera/base/log.h>\n> +\n> +#include <libcamera/control_ids.h>\n> +\n> +#include \"linux/rkisp1-config.h\"\n> +\n> +/**\n> + * \\file dpf.h\n> + */\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::rkisp1::algorithms {\n> +\n> +/**\n> + * \\class Dpf\n> + * \\brief RkISP1 Denoise Pre-Filter control\n> + *\n> + * The denoise pre-filter algorithm is a bilateral filter which combines a\n> + * range filter and a domain filter. The denoise pre-filter is applied before\n> + * demosaicing.\n> + */\n> +\n> +LOG_DEFINE_CATEGORY(RkISP1Dpf)\n> +\n> +Dpf::Dpf()\n> +\t: initialized_(false), config_({}), strengthConfig_({})\n> +{\n> +}\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::init\n> + */\n> +int Dpf::init([[maybe_unused]] IPAContext &context,\n> +\t      const YamlObject &tuningData)\n> +{\n> +\tstd::vector<uint16_t> values;\n> +\n> +\t/*\n> +\t * The domain kernel is configured with a 9x9 kernel for the green\n> +\t * pixels, and a 13x9 or 9x9 kernel for red and blue pixels.\n> +\t */\n> +\tconst YamlObject &dFObject = tuningData[\"DomainFilter\"];\n> +\n> +\t/*\n> +\t * For the green component, we have the 9x9 kernel specified\n> +\t * as 6 coefficients:\n> +\t *    Y\n> +\t *    ^\n> +\t *  4 | 6   5   4   5   6\n> +\t *  3 |   5   3   3   5\n> +\t *  2 | 5   3   2   3   5\n> +\t *  1 |   3   1   1   3\n> +\t *  0 - 4   2   0   2   4\n> +\t * -1 |   3   1   1   3\n> +\t * -2 | 5   3   2   3   5\n> +\t * -3 |   5   3   3   5\n> +\t * -4 | 6   5   4   5   6\n> +\t *    +---------|--------> X\n> +\t *     -4....-1 0 1 2 3 4\n> +\t */\n> +\tvalues = dFObject[\"g\"].getList<uint16_t>().value_or(utils::defopt);\n> +\tif (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) {\n> +\t\tLOG(RkISP1Dpf, Error)\n> +\t\t\t<< \"Invalid 'DomainFilter:g': expected \"\n> +\t\t\t<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n> +\t\t\t<< \" elements, got \" << values.size();\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n> +\tstd::copy_n(values.begin(), values.size(),\n> +\t\t    std::begin(config_.g_flt.spatial_coeff));\n> +\n> +\tconfig_.g_flt.gr_enable = true;\n> +\tconfig_.g_flt.gb_enable = true;\n> +\n> +\t/*\n> +\t * For the red and blue components, we have the 13x9 kernel specified\n> +\t * as 6 coefficients:\n> +\t *\n> +\t *    Y\n> +\t *    ^\n> +\t *  4 | 6   5   4   3   4   5   6\n> +\t *    |\n> +\t *  2 | 5   4   2   1   2   4   5\n> +\t *    |\n> +\t *  0 - 5   3   1   0   1   3   5\n> +\t *    |\n> +\t * -2 | 5   4   2   1   2   4   5\n> +\t *    |\n> +\t * -4 | 6   5   4   3   4   5   6\n> +\t *    +-------------|------------> X\n> +\t *     -6  -4  -2   0   2   4   6\n> +\t *\n> +\t * For a 9x9 kernel, columns -6 and 6 are dropped, so coefficient\n> +\t * number 6 is not used.\n> +\t */\n> +\tvalues = dFObject[\"rb\"].getList<uint16_t>().value_or(utils::defopt);\n> +\tif (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS &&\n> +\t    values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1) {\n> +\t\tLOG(RkISP1Dpf, Error)\n> +\t\t\t<< \"Invalid 'DomainFilter:rb': expected \"\n> +\t\t\t<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1\n> +\t\t\t<< \" or \" << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n> +\t\t\t<< \" elements, got \" << values.size();\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n> +\tconfig_.rb_flt.fltsize = values.size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n> +\t\t\t       ? RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9\n> +\t\t\t       : RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9;\n> +\n> +\tstd::copy_n(values.begin(), values.size(),\n> +\t\t    std::begin(config_.rb_flt.spatial_coeff));\n> +\n> +\tconfig_.rb_flt.r_enable = true;\n> +\tconfig_.rb_flt.b_enable = true;\n> +\n> +\t/*\n> +\t * The range kernel is configured with a noise level lookup table (NLL)\n> +\t * which stores a piecewise linear function that characterizes the\n> +\t * sensor noise profile as a noise level function curve (NLF).\n> +\t */\n> +\tconst YamlObject &rFObject = tuningData[\"NoiseLevelFunction\"];\n> +\n> +\tvalues = rFObject[\"coeff\"].getList<uint16_t>().value_or(utils::defopt);\n> +\tif (values.size() != RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS) {\n> +\t\tLOG(RkISP1Dpf, Error)\n> +\t\t\t<< \"Invalid 'RangeFilter:coeff': expected \"\n> +\t\t\t<< RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS\n> +\t\t\t<< \" elements, got \" << values.size();\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n> +\tstd::copy_n(values.begin(), values.size(),\n> +\t\t    std::begin(config_.nll.coeff));\n> +\n> +\tstd::string scaleMode = rFObject[\"scale-mode\"].get<std::string>(\"\");\n> +\tif (scaleMode == \"linear\") {\n> +\t\tconfig_.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LINEAR;\n> +\t} else if (scaleMode == \"logarithmic\") {\n> +\t\tconfig_.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC;\n> +\t} else {\n> +\t\tLOG(RkISP1Dpf, Error)\n> +\t\t\t<< \"Invalid 'RangeFilter:scale-mode': expected \"\n> +\t\t\t<< \"'linear' or 'logarithmic' value, got \"\n> +\t\t\t<< scaleMode;\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n> +\tconst YamlObject &fSObject = tuningData[\"FilterStrength\"];\n> +\n> +\tstrengthConfig_.r = fSObject[\"r\"].get<uint16_t>(64);\n> +\tstrengthConfig_.g = fSObject[\"g\"].get<uint16_t>(64);\n> +\tstrengthConfig_.b = fSObject[\"b\"].get<uint16_t>(64);\n> +\n> +\tinitialized_ = true;\n> +\n> +\treturn 0;\n> +}\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> + */\n> +void Dpf::queueRequest(IPAContext &context,\n> +\t\t       [[maybe_unused]] const uint32_t frame,\n> +\t\t       const ControlList &controls)\n> +{\n> +\tauto &dpf = context.frameContext.dpf;\n> +\n> +\tconst auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n> +\tif (denoise) {\n> +\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n> +\n> +\t\tswitch (*denoise) {\n> +\t\tcase controls::draft::NoiseReductionModeOff:\n> +\t\t\tdpf.denoise = false;\n> +\t\t\tdpf.updateParams = true;\n> +\t\t\tbreak;\n> +\t\tcase controls::draft::NoiseReductionModeMinimal:\n> +\t\tcase controls::draft::NoiseReductionModeHighQuality:\n> +\t\tcase controls::draft::NoiseReductionModeFast:\n> +\t\t\tdpf.denoise = true;\n> +\t\t\tdpf.updateParams = true;\n> +\t\t\tbreak;\n> +\t\tdefault:\n> +\t\t\tLOG(RkISP1Dpf, Error)\n> +\t\t\t\t<< \"Unsupported denoise value \"\n> +\t\t\t\t<< *denoise;\n> +\t\t}\n> +\t}\n> +}\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::prepare\n> + */\n> +void Dpf::prepare(IPAContext &context, rkisp1_params_cfg *params)\n> +{\n> +\tif (!initialized_)\n> +\t\treturn;\n> +\n> +\tauto &dpf = context.frameContext.dpf;\n> +\n> +\tif (context.frameContext.frameCount == 0) {\n> +\t\tparams->others.dpf_config = config_;\n> +\t\tparams->others.dpf_strength_config = strengthConfig_;\n> +\n> +\t\tconst auto &awb = context.configuration.awb;\n> +\t\tconst auto &lsc = context.configuration.lsc;\n> +\t\tauto &mode = params->others.dpf_config.gain.mode;\n> +\n> +\t\tif (awb.enabled && lsc.enabled)\n> +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS;\n> +\t\telse if (awb.enabled)\n> +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS;\n> +\t\telse if (lsc.enabled)\n> +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS;\n> +\t\telse\n> +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED;\n> +\n\n\nIt might be worth to mention as a comment that usage of *_GAIN_USAGE_* \nmode will inherently supply AWB/LSC gain values to the DPF h/w block.\n\nAlso a question on whether the _GAIN_USAGE_ is allowed to change between \nframes somehow? Or once it's set to AWB's or LSC's - it should continue \nto use that for the entire session.\n\nhmm, now this is looking like something at configure() time operation - \nah but we won't have rkisp1_params_cfg* at configure().\n\n> +\t\tparams->module_cfg_update |= RKISP1_CIF_ISP_MODULE_DPF |\n> +\t\t\t\t\t     RKISP1_CIF_ISP_MODULE_DPF_STRENGTH;\n> +\t}\n> +\n> +\tif (dpf.updateParams) {\n> +\t\tparams->module_en_update |= RKISP1_CIF_ISP_MODULE_DPF;\n> +\t\tif (dpf.denoise)\n> +\t\t\tparams->module_ens |= RKISP1_CIF_ISP_MODULE_DPF;\n> +\n> +\t\tdpf.updateParams = false;\n> +\t}\n> +}\n> +\n> +REGISTER_IPA_ALGORITHM(Dpf, \"Dpf\")\n> +\n> +} /* namespace ipa::rkisp1::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\n> new file mode 100644\n> index 000000000000..128ebd5e02e3\n> --- /dev/null\n> +++ b/src/ipa/rkisp1/algorithms/dpf.h\n> @@ -0,0 +1,36 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2021-2022, Ideas On Board\n> + *\n> + * dpf.h - RkISP1 Denoise Pre-Filter control\n> + */\n> +\n> +#pragma once\n> +\n> +#include <sys/types.h>\n> +\n> +#include \"algorithm.h\"\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::rkisp1::algorithms {\n> +\n> +class Dpf : public Algorithm\n> +{\n> +public:\n> +\tDpf();\n> +\t~Dpf() = default;\n> +\n> +\tint init(IPAContext &context, const YamlObject &tuningData) override;\n> +\tvoid queueRequest(IPAContext &context, const uint32_t frame,\n> +\t\t\t  const ControlList &controls) override;\n> +\tvoid prepare(IPAContext &context, rkisp1_params_cfg *params) override;\n> +\n> +private:\n> +\tbool initialized_;\n> +\tstruct rkisp1_cif_isp_dpf_config config_;\n> +\tstruct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n> +};\n> +\n> +} /* namespace ipa::rkisp1::algorithms */\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build\n> index e48974b454b5..93a483292753 100644\n> --- a/src/ipa/rkisp1/algorithms/meson.build\n> +++ b/src/ipa/rkisp1/algorithms/meson.build\n> @@ -6,6 +6,7 @@ rkisp1_ipa_algorithms = files([\n>       'blc.cpp',\n>       'cproc.cpp',\n>       'dpcc.cpp',\n> +    'dpf.cpp',\n>       'filter.cpp',\n>       'gsl.cpp',\n>       'lsc.cpp',\n> diff --git a/src/ipa/rkisp1/data/ov5640.yaml b/src/ipa/rkisp1/data/ov5640.yaml\n> index 45d4bb77f8ca..3dc369ac3681 100644\n> --- a/src/ipa/rkisp1/data/ov5640.yaml\n> +++ b/src/ipa/rkisp1/data/ov5640.yaml\n> @@ -156,5 +156,20 @@ algorithms:\n>             rnd-offsets:\n>               green: 2\n>               red-blue: 2\n> +  - Dpf:\n> +      DomainFilter:\n> +        g: [ 16, 16, 16, 16, 16, 16 ]\n> +        rb: [ 16, 16, 16, 16, 16, 16 ]\n> +      NoiseLevelFunction:\n> +        coeff: [\n> +          1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,\n> +          1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,\n> +          1023\n> +        ]\n\n\nI am not not sure, where these Domain filter coefficients and Noise \nlevel function lookup table comes from... Other than that,\n\nReviewed-by: Umang Jain <umang.jain@ideasonboard.com>\n\n> +        scale-mode: \"linear\"\n> +      FilterStrength:\n> +        r: 64\n> +        g: 64\n> +        b: 64\n>     - Filter:\n>   ...\n> diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp\n> index 1a549c092d73..17f15fd4e6b5 100644\n> --- a/src/ipa/rkisp1/ipa_context.cpp\n> +++ b/src/ipa/rkisp1/ipa_context.cpp\n> @@ -164,6 +164,17 @@ namespace libcamera::ipa::rkisp1 {\n>    * \\brief Indicates if ISP parameters need to be updated\n>    */\n>   \n> +/**\n> + * \\var IPAFrameContext::dpf\n> + * \\brief Context for the Denoise Pre-Filter algorithm\n> + *\n> + * \\var IPAFrameContext::dpf.denoise\n> + * \\brief Indicates if denoise is activated\n> + *\n> + * \\var IPAFrameContext::dpf.updateParams\n> + * \\brief Indicates if ISP parameters need to be updated\n> + */\n> +\n>   /**\n>    * \\var IPAFrameContext::filter\n>    * \\brief Context for the Filter algorithm\n> diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h\n> index 0cd6aadb83ed..3a743ac325da 100644\n> --- a/src/ipa/rkisp1/ipa_context.h\n> +++ b/src/ipa/rkisp1/ipa_context.h\n> @@ -69,6 +69,11 @@ struct IPAFrameContext {\n>   \t\tbool updateParams;\n>   \t} cproc;\n>   \n> +\tstruct {\n> +\t\tbool denoise;\n> +\t\tbool updateParams;\n> +\t} dpf;\n> +\n>   \tstruct {\n>   \t\tuint8_t denoise;\n>   \t\tuint8_t sharpness;","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 8C32BBE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 15 Aug 2022 15:52:22 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E604E61FC0;\n\tMon, 15 Aug 2022 17:52:21 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3BFDE61FB9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 15 Aug 2022 17:52:20 +0200 (CEST)","from [IPV6:2401:4900:1f3f:a731:6fd:fef1:9e01:7e0f] (unknown\n\t[IPv6:2401:4900:1f3f:a731:6fd:fef1:9e01:7e0f])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 0C51C4A8;\n\tMon, 15 Aug 2022 17:52:18 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1660578741;\n\tbh=2rESgRxYgp5j7LsQZMNmrq6t+c641UMTFA/Eg/zp5A0=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=Id8+cx3qLUCGVp/3UTgiC/37ZOQuIYoZ99nnuNakYEoHYwKxarUevfKsI6+Mwkevx\n\t6c0extSKt2AS4PGV32c628MUBU0U5NluX+tjnlMh1u5etBgVQmloEhu0FbSpRrk2q0\n\tXQMB7Q8YvnEg3q8vuemFz1AndRgcGOZjCCRUgGSAkEFcQDHZgDCKAFNUDQDHibsOFG\n\tqj4PaNUUvfLfYMGOs9elWZ9SPmrcGex9p7PKyqDK41Ldihhp1gvzj9YczDqXaFyIkQ\n\thkRN3+0c4mGGpdj4bdXez0oYWmNaBAAJnrhA/tccuLyOYfOn45JbmPlmalz2TwF2Vu\n\tVzOBck7HYJ79A==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1660578739;\n\tbh=2rESgRxYgp5j7LsQZMNmrq6t+c641UMTFA/Eg/zp5A0=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=blwPDu2qo3b6I3ak7H3Nosm/7IhOcB0JIPTLWm9xeLN3hhvYiCksdr0fQw8wCcV7y\n\torUV1kbM9+oQm9O3WuzrQPM2m+l6Ntj6V7/LEapYIWQsUANMsmnx+tqwSzN8JZgIKZ\n\tw5HFaw5/UBVMKpNcNh+Mru/VWI2IEGYi3568Vq5A="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"blwPDu2q\"; dkim-atps=neutral","Message-ID":"<fe119c11-ef12-13ad-da80-65ec11809098@ideasonboard.com>","Date":"Mon, 15 Aug 2022 21:22:12 +0530","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n\tThunderbird/91.4.1","Content-Language":"en-US","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20220812223351.22609-1-laurent.pinchart@ideasonboard.com>\n\t<20220812223351.22609-4-laurent.pinchart@ideasonboard.com>","In-Reply-To":"<20220812223351.22609-4-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH v3 3/3] ipa: rkisp1: Add support of\n\tDenoise Pre-Filter control","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>","From":"Umang Jain via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Umang Jain <umang.jain@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":24583,"web_url":"https://patchwork.libcamera.org/comment/24583/","msgid":"<YvqT6Glt879JjD7k@pendragon.ideasonboard.com>","date":"2022-08-15T18:43:52","subject":"Re: [libcamera-devel] [PATCH v3 3/3] ipa: rkisp1: Add support of\n\tDenoise Pre-Filter control","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Umang,\n\nOn Mon, Aug 15, 2022 at 09:22:12PM +0530, Umang Jain wrote:\n> On 8/13/22 04:03, Laurent Pinchart via libcamera-devel wrote:\n> > From: Florian Sylvestre <fsylvestre@baylibre.com>\n> >\n> > The denoise pre-filter algorithm is a bilateral filter which combines a range\n> > filter and a domain filter. The denoise pre-filter is applied before\n> > demosaicing.\n> >\n> > Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>\n> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> > Changes since v2:\n> >\n> > - Change the scope of some variables in Dpf::prepare()\n> > - Line-wrap coefficients in tuning file\n> > ---\n> >   src/ipa/rkisp1/algorithms/dpf.cpp     | 249 ++++++++++++++++++++++++++\n> >   src/ipa/rkisp1/algorithms/dpf.h       |  36 ++++\n> >   src/ipa/rkisp1/algorithms/meson.build |   1 +\n> >   src/ipa/rkisp1/data/ov5640.yaml       |  15 ++\n> >   src/ipa/rkisp1/ipa_context.cpp        |  11 ++\n> >   src/ipa/rkisp1/ipa_context.h          |   5 +\n> >   6 files changed, 317 insertions(+)\n> >   create mode 100644 src/ipa/rkisp1/algorithms/dpf.cpp\n> >   create mode 100644 src/ipa/rkisp1/algorithms/dpf.h\n> >\n> > diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\n> > new file mode 100644\n> > index 000000000000..33fe3066b9e3\n> > --- /dev/null\n> > +++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n> > @@ -0,0 +1,249 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2021-2022, Ideas On Board\n> > + *\n> > + * dpf.cpp - RkISP1 Denoise Pre-Filter control\n> > + */\n> > +\n> > +#include \"dpf.h\"\n> > +\n> > +#include <cmath>\n> > +\n> > +#include <libcamera/base/log.h>\n> > +\n> > +#include <libcamera/control_ids.h>\n> > +\n> > +#include \"linux/rkisp1-config.h\"\n> > +\n> > +/**\n> > + * \\file dpf.h\n> > + */\n> > +\n> > +namespace libcamera {\n> > +\n> > +namespace ipa::rkisp1::algorithms {\n> > +\n> > +/**\n> > + * \\class Dpf\n> > + * \\brief RkISP1 Denoise Pre-Filter control\n> > + *\n> > + * The denoise pre-filter algorithm is a bilateral filter which combines a\n> > + * range filter and a domain filter. The denoise pre-filter is applied before\n> > + * demosaicing.\n> > + */\n> > +\n> > +LOG_DEFINE_CATEGORY(RkISP1Dpf)\n> > +\n> > +Dpf::Dpf()\n> > +\t: initialized_(false), config_({}), strengthConfig_({})\n> > +{\n> > +}\n> > +\n> > +/**\n> > + * \\copydoc libcamera::ipa::Algorithm::init\n> > + */\n> > +int Dpf::init([[maybe_unused]] IPAContext &context,\n> > +\t      const YamlObject &tuningData)\n> > +{\n> > +\tstd::vector<uint16_t> values;\n> > +\n> > +\t/*\n> > +\t * The domain kernel is configured with a 9x9 kernel for the green\n> > +\t * pixels, and a 13x9 or 9x9 kernel for red and blue pixels.\n> > +\t */\n> > +\tconst YamlObject &dFObject = tuningData[\"DomainFilter\"];\n> > +\n> > +\t/*\n> > +\t * For the green component, we have the 9x9 kernel specified\n> > +\t * as 6 coefficients:\n> > +\t *    Y\n> > +\t *    ^\n> > +\t *  4 | 6   5   4   5   6\n> > +\t *  3 |   5   3   3   5\n> > +\t *  2 | 5   3   2   3   5\n> > +\t *  1 |   3   1   1   3\n> > +\t *  0 - 4   2   0   2   4\n> > +\t * -1 |   3   1   1   3\n> > +\t * -2 | 5   3   2   3   5\n> > +\t * -3 |   5   3   3   5\n> > +\t * -4 | 6   5   4   5   6\n> > +\t *    +---------|--------> X\n> > +\t *     -4....-1 0 1 2 3 4\n> > +\t */\n> > +\tvalues = dFObject[\"g\"].getList<uint16_t>().value_or(utils::defopt);\n> > +\tif (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) {\n> > +\t\tLOG(RkISP1Dpf, Error)\n> > +\t\t\t<< \"Invalid 'DomainFilter:g': expected \"\n> > +\t\t\t<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n> > +\t\t\t<< \" elements, got \" << values.size();\n> > +\t\treturn -EINVAL;\n> > +\t}\n> > +\n> > +\tstd::copy_n(values.begin(), values.size(),\n> > +\t\t    std::begin(config_.g_flt.spatial_coeff));\n> > +\n> > +\tconfig_.g_flt.gr_enable = true;\n> > +\tconfig_.g_flt.gb_enable = true;\n> > +\n> > +\t/*\n> > +\t * For the red and blue components, we have the 13x9 kernel specified\n> > +\t * as 6 coefficients:\n> > +\t *\n> > +\t *    Y\n> > +\t *    ^\n> > +\t *  4 | 6   5   4   3   4   5   6\n> > +\t *    |\n> > +\t *  2 | 5   4   2   1   2   4   5\n> > +\t *    |\n> > +\t *  0 - 5   3   1   0   1   3   5\n> > +\t *    |\n> > +\t * -2 | 5   4   2   1   2   4   5\n> > +\t *    |\n> > +\t * -4 | 6   5   4   3   4   5   6\n> > +\t *    +-------------|------------> X\n> > +\t *     -6  -4  -2   0   2   4   6\n> > +\t *\n> > +\t * For a 9x9 kernel, columns -6 and 6 are dropped, so coefficient\n> > +\t * number 6 is not used.\n> > +\t */\n> > +\tvalues = dFObject[\"rb\"].getList<uint16_t>().value_or(utils::defopt);\n> > +\tif (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS &&\n> > +\t    values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1) {\n> > +\t\tLOG(RkISP1Dpf, Error)\n> > +\t\t\t<< \"Invalid 'DomainFilter:rb': expected \"\n> > +\t\t\t<< RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1\n> > +\t\t\t<< \" or \" << RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n> > +\t\t\t<< \" elements, got \" << values.size();\n> > +\t\treturn -EINVAL;\n> > +\t}\n> > +\n> > +\tconfig_.rb_flt.fltsize = values.size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS\n> > +\t\t\t       ? RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9\n> > +\t\t\t       : RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9;\n> > +\n> > +\tstd::copy_n(values.begin(), values.size(),\n> > +\t\t    std::begin(config_.rb_flt.spatial_coeff));\n> > +\n> > +\tconfig_.rb_flt.r_enable = true;\n> > +\tconfig_.rb_flt.b_enable = true;\n> > +\n> > +\t/*\n> > +\t * The range kernel is configured with a noise level lookup table (NLL)\n> > +\t * which stores a piecewise linear function that characterizes the\n> > +\t * sensor noise profile as a noise level function curve (NLF).\n> > +\t */\n> > +\tconst YamlObject &rFObject = tuningData[\"NoiseLevelFunction\"];\n> > +\n> > +\tvalues = rFObject[\"coeff\"].getList<uint16_t>().value_or(utils::defopt);\n> > +\tif (values.size() != RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS) {\n> > +\t\tLOG(RkISP1Dpf, Error)\n> > +\t\t\t<< \"Invalid 'RangeFilter:coeff': expected \"\n> > +\t\t\t<< RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS\n> > +\t\t\t<< \" elements, got \" << values.size();\n> > +\t\treturn -EINVAL;\n> > +\t}\n> > +\n> > +\tstd::copy_n(values.begin(), values.size(),\n> > +\t\t    std::begin(config_.nll.coeff));\n> > +\n> > +\tstd::string scaleMode = rFObject[\"scale-mode\"].get<std::string>(\"\");\n> > +\tif (scaleMode == \"linear\") {\n> > +\t\tconfig_.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LINEAR;\n> > +\t} else if (scaleMode == \"logarithmic\") {\n> > +\t\tconfig_.nll.scale_mode = RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC;\n> > +\t} else {\n> > +\t\tLOG(RkISP1Dpf, Error)\n> > +\t\t\t<< \"Invalid 'RangeFilter:scale-mode': expected \"\n> > +\t\t\t<< \"'linear' or 'logarithmic' value, got \"\n> > +\t\t\t<< scaleMode;\n> > +\t\treturn -EINVAL;\n> > +\t}\n> > +\n> > +\tconst YamlObject &fSObject = tuningData[\"FilterStrength\"];\n> > +\n> > +\tstrengthConfig_.r = fSObject[\"r\"].get<uint16_t>(64);\n> > +\tstrengthConfig_.g = fSObject[\"g\"].get<uint16_t>(64);\n> > +\tstrengthConfig_.b = fSObject[\"b\"].get<uint16_t>(64);\n> > +\n> > +\tinitialized_ = true;\n> > +\n> > +\treturn 0;\n> > +}\n> > +\n> > +/**\n> > + * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> > + */\n> > +void Dpf::queueRequest(IPAContext &context,\n> > +\t\t       [[maybe_unused]] const uint32_t frame,\n> > +\t\t       const ControlList &controls)\n> > +{\n> > +\tauto &dpf = context.frameContext.dpf;\n> > +\n> > +\tconst auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n> > +\tif (denoise) {\n> > +\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n> > +\n> > +\t\tswitch (*denoise) {\n> > +\t\tcase controls::draft::NoiseReductionModeOff:\n> > +\t\t\tdpf.denoise = false;\n> > +\t\t\tdpf.updateParams = true;\n> > +\t\t\tbreak;\n> > +\t\tcase controls::draft::NoiseReductionModeMinimal:\n> > +\t\tcase controls::draft::NoiseReductionModeHighQuality:\n> > +\t\tcase controls::draft::NoiseReductionModeFast:\n> > +\t\t\tdpf.denoise = true;\n> > +\t\t\tdpf.updateParams = true;\n> > +\t\t\tbreak;\n> > +\t\tdefault:\n> > +\t\t\tLOG(RkISP1Dpf, Error)\n> > +\t\t\t\t<< \"Unsupported denoise value \"\n> > +\t\t\t\t<< *denoise;\n> > +\t\t}\n> > +\t}\n> > +}\n> > +\n> > +/**\n> > + * \\copydoc libcamera::ipa::Algorithm::prepare\n> > + */\n> > +void Dpf::prepare(IPAContext &context, rkisp1_params_cfg *params)\n> > +{\n> > +\tif (!initialized_)\n> > +\t\treturn;\n> > +\n> > +\tauto &dpf = context.frameContext.dpf;\n> > +\n> > +\tif (context.frameContext.frameCount == 0) {\n> > +\t\tparams->others.dpf_config = config_;\n> > +\t\tparams->others.dpf_strength_config = strengthConfig_;\n> > +\n> > +\t\tconst auto &awb = context.configuration.awb;\n> > +\t\tconst auto &lsc = context.configuration.lsc;\n> > +\t\tauto &mode = params->others.dpf_config.gain.mode;\n> > +\n> > +\t\tif (awb.enabled && lsc.enabled)\n> > +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS;\n> > +\t\telse if (awb.enabled)\n> > +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS;\n> > +\t\telse if (lsc.enabled)\n> > +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS;\n> > +\t\telse\n> > +\t\t\tmode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED;\n> > +\n> \n> It might be worth to mention as a comment that usage of *_GAIN_USAGE_* \n> mode will inherently supply AWB/LSC gain values to the DPF h/w block.\n\nI'll add this:\n\n                /*\n                 * The DPF needs to take into account the total amount of\n                 * digital gain, which comes from the AWB and LSC modules. The\n                 * DPF hardware can be programmed with a digital gain value\n                 * manually, but can also use the gains supplied by the AWB and\n                 * LSC modules automatically when they are enabled. Use that\n                 * mode of operation as it simplifies control of the DPF.\n                 */\n\n> Also a question on whether the _GAIN_USAGE_ is allowed to change between \n> frames somehow? Or once it's set to AWB's or LSC's - it should continue \n> to use that for the entire session.\n> \n> hmm, now this is looking like something at configure() time operation - \n> ah but we won't have rkisp1_params_cfg* at configure().\n\nIt could change from frame to frame if we were to enable/disable the AWB\nand LSC modules per frame, but I don't think we will ever do that. Note\nthat in this case, \"enabled AWB\" doesn't meant that white balance is\nautomatic, it means that the hardware block applies colour gains.\n\n> > +\t\tparams->module_cfg_update |= RKISP1_CIF_ISP_MODULE_DPF |\n> > +\t\t\t\t\t     RKISP1_CIF_ISP_MODULE_DPF_STRENGTH;\n> > +\t}\n> > +\n> > +\tif (dpf.updateParams) {\n> > +\t\tparams->module_en_update |= RKISP1_CIF_ISP_MODULE_DPF;\n> > +\t\tif (dpf.denoise)\n> > +\t\t\tparams->module_ens |= RKISP1_CIF_ISP_MODULE_DPF;\n> > +\n> > +\t\tdpf.updateParams = false;\n> > +\t}\n> > +}\n> > +\n> > +REGISTER_IPA_ALGORITHM(Dpf, \"Dpf\")\n> > +\n> > +} /* namespace ipa::rkisp1::algorithms */\n> > +\n> > +} /* namespace libcamera */\n> > diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\n> > new file mode 100644\n> > index 000000000000..128ebd5e02e3\n> > --- /dev/null\n> > +++ b/src/ipa/rkisp1/algorithms/dpf.h\n> > @@ -0,0 +1,36 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2021-2022, Ideas On Board\n> > + *\n> > + * dpf.h - RkISP1 Denoise Pre-Filter control\n> > + */\n> > +\n> > +#pragma once\n> > +\n> > +#include <sys/types.h>\n> > +\n> > +#include \"algorithm.h\"\n> > +\n> > +namespace libcamera {\n> > +\n> > +namespace ipa::rkisp1::algorithms {\n> > +\n> > +class Dpf : public Algorithm\n> > +{\n> > +public:\n> > +\tDpf();\n> > +\t~Dpf() = default;\n> > +\n> > +\tint init(IPAContext &context, const YamlObject &tuningData) override;\n> > +\tvoid queueRequest(IPAContext &context, const uint32_t frame,\n> > +\t\t\t  const ControlList &controls) override;\n> > +\tvoid prepare(IPAContext &context, rkisp1_params_cfg *params) override;\n> > +\n> > +private:\n> > +\tbool initialized_;\n> > +\tstruct rkisp1_cif_isp_dpf_config config_;\n> > +\tstruct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n> > +};\n> > +\n> > +} /* namespace ipa::rkisp1::algorithms */\n> > +} /* namespace libcamera */\n> > diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build\n> > index e48974b454b5..93a483292753 100644\n> > --- a/src/ipa/rkisp1/algorithms/meson.build\n> > +++ b/src/ipa/rkisp1/algorithms/meson.build\n> > @@ -6,6 +6,7 @@ rkisp1_ipa_algorithms = files([\n> >       'blc.cpp',\n> >       'cproc.cpp',\n> >       'dpcc.cpp',\n> > +    'dpf.cpp',\n> >       'filter.cpp',\n> >       'gsl.cpp',\n> >       'lsc.cpp',\n> > diff --git a/src/ipa/rkisp1/data/ov5640.yaml b/src/ipa/rkisp1/data/ov5640.yaml\n> > index 45d4bb77f8ca..3dc369ac3681 100644\n> > --- a/src/ipa/rkisp1/data/ov5640.yaml\n> > +++ b/src/ipa/rkisp1/data/ov5640.yaml\n> > @@ -156,5 +156,20 @@ algorithms:\n> >             rnd-offsets:\n> >               green: 2\n> >               red-blue: 2\n> > +  - Dpf:\n> > +      DomainFilter:\n> > +        g: [ 16, 16, 16, 16, 16, 16 ]\n> > +        rb: [ 16, 16, 16, 16, 16, 16 ]\n> > +      NoiseLevelFunction:\n> > +        coeff: [\n> > +          1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,\n> > +          1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,\n> > +          1023\n> > +        ]\n> \n> I am not not sure, where these Domain filter coefficients and Noise \n> level function lookup table comes from... Other than that,\n\nAll those are the hardware defaults. They will likely result in a pretty\nblurred image, but I think that's fine for now. The goal is to implement\nmanual control of the hardware block, the right values should be\ncomputed by a tuning tool (and possibly by the IPA module for some of\nthem) later.\n\n> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>\n> \n> > +        scale-mode: \"linear\"\n> > +      FilterStrength:\n> > +        r: 64\n> > +        g: 64\n> > +        b: 64\n> >     - Filter:\n> >   ...\n> > diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp\n> > index 1a549c092d73..17f15fd4e6b5 100644\n> > --- a/src/ipa/rkisp1/ipa_context.cpp\n> > +++ b/src/ipa/rkisp1/ipa_context.cpp\n> > @@ -164,6 +164,17 @@ namespace libcamera::ipa::rkisp1 {\n> >    * \\brief Indicates if ISP parameters need to be updated\n> >    */\n> >   \n> > +/**\n> > + * \\var IPAFrameContext::dpf\n> > + * \\brief Context for the Denoise Pre-Filter algorithm\n> > + *\n> > + * \\var IPAFrameContext::dpf.denoise\n> > + * \\brief Indicates if denoise is activated\n> > + *\n> > + * \\var IPAFrameContext::dpf.updateParams\n> > + * \\brief Indicates if ISP parameters need to be updated\n> > + */\n> > +\n> >   /**\n> >    * \\var IPAFrameContext::filter\n> >    * \\brief Context for the Filter algorithm\n> > diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h\n> > index 0cd6aadb83ed..3a743ac325da 100644\n> > --- a/src/ipa/rkisp1/ipa_context.h\n> > +++ b/src/ipa/rkisp1/ipa_context.h\n> > @@ -69,6 +69,11 @@ struct IPAFrameContext {\n> >   \t\tbool updateParams;\n> >   \t} cproc;\n> >   \n> > +\tstruct {\n> > +\t\tbool denoise;\n> > +\t\tbool updateParams;\n> > +\t} dpf;\n> > +\n> >   \tstruct {\n> >   \t\tuint8_t denoise;\n> >   \t\tuint8_t sharpness;","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 773A4C3272\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 15 Aug 2022 18:44:08 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BDBB861FC0;\n\tMon, 15 Aug 2022 20:44:07 +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 D167061FB9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 15 Aug 2022 20:44:05 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 349764A8;\n\tMon, 15 Aug 2022 20:44:05 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1660589047;\n\tbh=vcYwg/EZ11o+fHyJFyXCkM0QDWHdyTtEYDKYfwIieL4=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=bjLud8AOUHaPGg1jlI7HkkXsCalfjDqBatgUXVxFPQkH9WMjOaomRz6V9dgqLA8Vc\n\tpCpG6adNWaRPeYjpw9HnbyONHHmle1euCBMtnNEZULpgZ60iKwU+vTNup3T5Mn1u65\n\tlyu46zlLKUQ4dbNl0yxjAO70TB3FAupo8hWBU5PZfMp7yUpdACovftUrh1Feoowc0s\n\tFQxEnjKNJmBUVReN0uH2jzVVMc9yJgPqguebFULHDlAphLCHm6l0iHLQgFjLjm6A6d\n\tyAAWMrAIT+zxBfOXBWmrVX0q10lt5f+N8h1ItQn2fbpPl2MtyrH12uzlKDUvILE2gt\n\ttSm5j2DtxVZQw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1660589045;\n\tbh=vcYwg/EZ11o+fHyJFyXCkM0QDWHdyTtEYDKYfwIieL4=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=JiQOKDV1BPmAM7+84RXZOs4xBx2GfsDKQCVS+f5Ue1WvnXvVZPykrEIVRXm606YmF\n\tF8w9sGww4/iZOmxTOm77lk8qV0bx+aMy9P1L6Y7Sz4rYQQMaPnEFVV8khay2H7+pYg\n\t5msfnLOj+jzZ7vuRREcHeY0Hszyh2UE0o7okBBDM="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"JiQOKDV1\"; dkim-atps=neutral","Date":"Mon, 15 Aug 2022 21:43:52 +0300","To":"Umang Jain <umang.jain@ideasonboard.com>","Message-ID":"<YvqT6Glt879JjD7k@pendragon.ideasonboard.com>","References":"<20220812223351.22609-1-laurent.pinchart@ideasonboard.com>\n\t<20220812223351.22609-4-laurent.pinchart@ideasonboard.com>\n\t<fe119c11-ef12-13ad-da80-65ec11809098@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<fe119c11-ef12-13ad-da80-65ec11809098@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v3 3/3] ipa: rkisp1: Add support of\n\tDenoise Pre-Filter control","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]