[libcamera-devel] [PATCH 5/5] ipa: rkisp1: Add support of Defect Pixel Cluster Correction control
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Wed Jul 13 02:51:17 CEST 2022
Hi Florian,
Thank you for the patch.
The comments to patch 3/5 apply here too.
On Wed, Jun 22, 2022 at 05:19:18PM +0200, Florian Sylvestre via libcamera-devel wrote:
> The Defect Pixel Cluster Correction algorithm is responsible to minimize
> the impact of defective pixels. The on-the-fly method is actually used,
> based on coefficient provided by the tuning file.
>
> Signed-off-by: Florian Sylvestre <fsylvestre at baylibre.com>
> ---
> src/ipa/rkisp1/algorithms/dpcc.cpp | 273 ++++++++++++++++++++++++++
> src/ipa/rkisp1/algorithms/dpcc.h | 35 ++++
> src/ipa/rkisp1/algorithms/meson.build | 1 +
> src/ipa/rkisp1/data/ov5640.yaml | 60 ++++++
> src/ipa/rkisp1/rkisp1.cpp | 1 +
> 5 files changed, 370 insertions(+)
> create mode 100644 src/ipa/rkisp1/algorithms/dpcc.cpp
> create mode 100644 src/ipa/rkisp1/algorithms/dpcc.h
>
> diff --git a/src/ipa/rkisp1/algorithms/dpcc.cpp b/src/ipa/rkisp1/algorithms/dpcc.cpp
> new file mode 100644
> index 00000000..0c78ba9d
> --- /dev/null
> +++ b/src/ipa/rkisp1/algorithms/dpcc.cpp
> @@ -0,0 +1,273 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2021-2022, Ideas On Board
> + *
> + * lsc.cpp - RkISP1 Defect Pixel Cluster Correction control
> + */
> +
> +#include "dpcc.h"
> +
> +#include <libcamera/base/log.h>
> +
> +#include "libcamera/internal/yaml_parser.h"
> +#include "linux/rkisp1-config.h"
> +
> +/**
> + * \file dpcc.h
> + */
> +
> +namespace libcamera {
> +
> +namespace ipa::rkisp1::algorithms {
> +
> +/**
> + * \class DefectPixelClusterCorrection
> + * \brief RkISP1 Defect Pixel Cluster Correction control
> + *
> + * Depending of the sensor quality, some pixels can be defective and then
> + * appear significantly brighter or darker than the other pixels.
> + *
> + * The Defect Pixel Cluster Correction algorithms is responsible to minimize
> + * the impact of the pixels.
> + * This can be done with algorithms applied at run time (on-the-fly method) or
> + * with a table of defective pixels. Only first method is supported for the
> + * moment.
> + */
> +
> +LOG_DEFINE_CATEGORY(RkISP1Dpcc)
> +
> +DefectPixelClusterCorrection::DefectPixelClusterCorrection()
> + : tuningParameters_(false)
> +{
> +}
> +
> +/**
> + * \copydoc libcamera::ipa::Algorithm::init
> + */
> +int DefectPixelClusterCorrection::init([[maybe_unused]] IPAContext &context,
> + const YamlObject &tuningData)
> +{
> + bool fixedSet = tuningData["fixed-set"].get<bool>(true);
I'd default this to false, considering an element that is not present in
the file as true would be confusing.
> + tuning_.set_use =
> + fixedSet ? RKISP1_CIF_ISP_DPCC_SET_USE_STAGE1_USE_FIX_SET : 0;
tuning_.set_use = tuningData["fixed-set"].get<bool>(true)
? RKISP1_CIF_ISP_DPCC_SET_USE_STAGE1_USE_FIX_SET : 0;
> +
> + /* Get all defined sets to apply (up to 3). */
> + const YamlObject &setsObject = tuningData["sets"];
> + if (!setsObject.isList()) {
> + LOG(RkISP1Dpcc, Error)
> + << "'sets' list parameternot found in tuning file";
s/list parameternot/parameter not/
> + return -EINVAL;
> + }
> +
> + if (setsObject.size() > RKISP1_CIF_ISP_DPCC_METHODS_MAX) {
> + LOG(RkISP1Dpcc, Error)
> + << "'sets' size in tuning file (" << setsObject.size()
> + << ") exceed HW maximum capacity(3)";
<< ") exceeds the maximum hardware capacity (3)";
> + return -EINVAL;
> + }
> +
> + tuning_.ro_limits = 0;
> + tuning_.rnd_offs = 0;
How about zeroing tuning_ in the constructor
: tuningParameters_(false), tuning_({})
and avoiding all the initializations to 0 in this function ?
> +
> + for (std::size_t i = 0; i < setsObject.size(); ++i) {
struct rkisp1_cif_isp_dpcc_methods_config &method = tuning_.methods[i];
const YamlObject &set = setsObject[i];
and use them everywhere below.
> + uint16_t value;
> +
> + /* Enable set if described in Yaml tuning file. */
> + tuning_.set_use |= 0x1 << i;
s/0x1/1/
> +
> + /* Disable all methods by default. */
> + tuning_.methods[i].method = 0;
> +
> + /* PG Method */
> + const YamlObject &pgObject = setsObject[i]["pg-factor"];
> + tuning_.methods[i].pg_fac = 0;
> +
> + if (pgObject.contains("green")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_PG_GREEN_ENABLE;
> +
> + value = pgObject["green"].get<uint16_t>(0);
> + tuning_.methods[i].pg_fac |=
> + RKISP1_CIF_ISP_DPCC_PG_FAC_G(value);
> + }
> +
> + if (pgObject.contains("red-blue")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_PG_RED_BLUE_ENABLE;
> +
> + value = pgObject["red-blue"].get<uint16_t>(0);
> + tuning_.methods[i].pg_fac |=
> + RKISP1_CIF_ISP_DPCC_PG_FAC_RB(value);
> + }
> +
> + /* RO Method */
> + const YamlObject &roObject = setsObject[i]["ro-limits"];
> +
> + if (roObject.contains("green")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RO_GREEN_ENABLE;
> +
> + value = roObject["green"].get<uint16_t>(0);
> + tuning_.ro_limits |=
> + RKISP1_CIF_ISP_DPCC_RO_LIMITS_n_G(i, value);
> + }
> +
> + if (roObject.contains("red-blue")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RO_RED_BLUE_ENABLE;
> +
> + value = roObject["red-blue"].get<uint16_t>(0);
> + tuning_.ro_limits |=
> + RKISP1_CIF_ISP_DPCC_RO_LIMITS_n_RB(i, value);
> + }
> +
> + /* RG Method */
> + const YamlObject &rgObject = setsObject[i]["rg-factor"];
> + tuning_.methods[i].rg_fac = 0;
> +
> + if (rgObject.contains("green")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RG_GREEN_ENABLE;
> +
> + value = rgObject["green"].get<uint16_t>(0);
> + tuning_.methods[i].rg_fac |=
> + RKISP1_CIF_ISP_DPCC_RG_FAC_G(value);
> + }
> +
> + if (rgObject.contains("red-blue")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RG_RED_BLUE_ENABLE;
> +
> + value = rgObject["red-blue"].get<uint16_t>(0);
> + tuning_.methods[i].rg_fac |=
> + RKISP1_CIF_ISP_DPCC_RG_FAC_RB(value);
> + }
> +
> + /* RND Method */
> + const YamlObject &rndOffsetsObject = setsObject[i]["rnd-offsets"];
> +
> + if (rndOffsetsObject.contains("green")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_GREEN_ENABLE;
> +
> + value = rndOffsetsObject["green"].get<uint16_t>(0);
> + tuning_.rnd_offs |=
> + RKISP1_CIF_ISP_DPCC_RND_OFFS_n_G(i, value);
> + }
> +
> + if (rndOffsetsObject.contains("red-blue")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_RED_BLUE_ENABLE;
> +
> + value = rndOffsetsObject["red-blue"].get<uint16_t>(0);
> + tuning_.rnd_offs |=
> + RKISP1_CIF_ISP_DPCC_RND_OFFS_n_RB(i, value);
> + }
> +
> + const YamlObject &rndThresholdObject = setsObject[i]["rnd-threshold"];
> + tuning_.methods[i].rnd_thresh = 0;
> +
> + if (rndThresholdObject.contains("green")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_GREEN_ENABLE;
> +
> + value = rndThresholdObject["green"].get<uint16_t>(0);
> + tuning_.methods[i].rnd_thresh |=
> + RKISP1_CIF_ISP_DPCC_RND_THRESH_G(value);
> + }
> +
> + if (rndThresholdObject.contains("red-blue")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_RED_BLUE_ENABLE;
> +
> + value = rndThresholdObject["red-blue"].get<uint16_t>(0);
> + tuning_.methods[i].rnd_thresh |=
> + RKISP1_CIF_ISP_DPCC_RND_THRESH_RB(value);
> + }
> +
> + /* LC Method */
> + const YamlObject &lcThresholdObject = setsObject[i]["line-threshold"];
> + tuning_.methods[i].line_thresh = 0;
> +
> + if (lcThresholdObject.contains("green")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_GREEN_ENABLE;
> +
> + value = lcThresholdObject["green"].get<uint16_t>(0);
> + tuning_.methods[i].line_thresh |=
> + RKISP1_CIF_ISP_DPCC_LINE_THRESH_G(value);
> + }
> +
> + if (lcThresholdObject.contains("red-blue")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_RED_BLUE_ENABLE;
> +
> + value = lcThresholdObject["red-blue"].get<uint16_t>(0);
> + tuning_.methods[i].line_thresh |=
> + RKISP1_CIF_ISP_DPCC_LINE_THRESH_RB(value);
> + }
> +
> + const YamlObject &lcTMadFactorObject = setsObject[i]["line-mad-factor"];
> + tuning_.methods[i].line_mad_fac = 0;
> +
> + if (lcTMadFactorObject.contains("green")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_GREEN_ENABLE;
> +
> + value = lcTMadFactorObject["green"].get<uint16_t>(0);
> + tuning_.methods[i].line_mad_fac |=
> + RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_G(value);
> + }
> +
> + if (lcTMadFactorObject.contains("red-blue")) {
> + tuning_.methods[i].method |=
> + RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_RED_BLUE_ENABLE;
> +
> + value = lcTMadFactorObject["red-blue"].get<uint16_t>(0);
> + tuning_.methods[i].line_mad_fac |=
> + RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_RB(value);
> + }
That's lots of manually-written code, I wonder if we could do better.
I'll sleep over it.
> + }
> +
> + tuningParameters_ = true;
> +
> + return 0;
> +}
> +
> +/**
> + * \copydoc libcamera::ipa::Algorithm::prepare
> + */
> +void DefectPixelClusterCorrection::prepare(IPAContext &context,
> + rkisp1_params_cfg *params)
> +{
> + if (context.frameContext.frameCount > 0)
> + return;
> +
> + if (!tuningParameters_)
> + return;
> +
> + params->others.dpcc_config.mode =
> + RKISP1_CIF_ISP_DPCC_MODE_STAGE1_ENABLE;
> + params->others.dpcc_config.output_mode =
> + RKISP1_CIF_ISP_DPCC_OUTPUT_MODE_STAGE1_INCL_G_CENTER |
> + RKISP1_CIF_ISP_DPCC_OUTPUT_MODE_STAGE1_INCL_RB_CENTER;
I would set all of these in tuning_ in init(), and replace the code
below
> + params->others.dpcc_config.rnd_offs = tuning_.rnd_offs;
> + params->others.dpcc_config.ro_limits = tuning_.ro_limits;
> + params->others.dpcc_config.set_use = tuning_.set_use;
> +
> + for (std::size_t i = 0; i < RKISP1_CIF_ISP_DPCC_METHODS_MAX; ++i) {
> + memcpy(¶ms->others.dpcc_config.methods[i],
> + &tuning_.methods[i],
> + sizeof(rkisp1_cif_isp_dpcc_methods_config));
> + }
with
params->others.dpcc_config = tuning_;
> +
> + params->module_en_update |= RKISP1_CIF_ISP_MODULE_DPCC;
> + params->module_ens |= RKISP1_CIF_ISP_MODULE_DPCC;
> + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_DPCC;
> +}
> +
> +REGISTER_IPA_ALGORITHM(DefectPixelClusterCorrection)
> +
> +} /* namespace ipa::rkisp1::algorithms */
> +
> +} /* namespace libcamera */
> diff --git a/src/ipa/rkisp1/algorithms/dpcc.h b/src/ipa/rkisp1/algorithms/dpcc.h
> new file mode 100644
> index 00000000..6c6c6aaa
> --- /dev/null
> +++ b/src/ipa/rkisp1/algorithms/dpcc.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2021-2022, Ideas On Board
> + *
> + * dpcc.h - RkISP1 Defect Pixel Cluster Correction control
> + */
> +
> +#pragma once
> +
> +#include <linux/rkisp1-config.h>
> +
> +#include "algorithm.h"
> +
> +namespace libcamera {
> +
> +struct IPACameraSensorInfo;
> +
> +namespace ipa::rkisp1::algorithms {
> +
> +class DefectPixelClusterCorrection : public Algorithm
> +{
> +public:
> + DefectPixelClusterCorrection();
> + ~DefectPixelClusterCorrection() = default;
> +
> + int init(IPAContext &context, const YamlObject &tuningData) override;
> + void prepare(IPAContext &context, rkisp1_params_cfg *params) override;
> +
> +private:
> + bool tuningParameters_;
> + rkisp1_cif_isp_dpcc_config tuning_;
I'd name the variable config_ insteead of tuning_, as it stores the
configuration data, not the tuning data.
> +};
> +
> +} /* namespace ipa::rkisp1::algorithms */
> +} /* namespace libcamera */
> diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build
> index 64e11dce..87007493 100644
> --- a/src/ipa/rkisp1/algorithms/meson.build
> +++ b/src/ipa/rkisp1/algorithms/meson.build
> @@ -4,6 +4,7 @@ rkisp1_ipa_algorithms = files([
> 'agc.cpp',
> 'awb.cpp',
> 'blc.cpp',
> + 'dpcc.cpp',
> 'gsl.cpp',
> 'lsc.cpp',
> ])
> diff --git a/src/ipa/rkisp1/data/ov5640.yaml b/src/ipa/rkisp1/data/ov5640.yaml
> index 154ed3b5..51228218 100644
> --- a/src/ipa/rkisp1/data/ov5640.yaml
> +++ b/src/ipa/rkisp1/data/ov5640.yaml
> @@ -97,4 +97,64 @@ algorithms:
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> ]
> + - DefectPixelClusterCorrection:
> + fixed-set: false
> + sets:
> + # PG, LC, RO, RND, RG
> + - line-threshold:
> + green: 8
> + red-blue: 8
> + line-mad-factor:
> + green: 4
> + red-blue: 4
> + pg-factor:
> + green: 8
> + red-blue: 8
> + rnd-threshold:
> + green: 10
> + red-blue: 10
> + rg-factor:
> + green: 32
> + red-blue: 32
> + ro-limits:
> + green: 1
> + red-blue: 1
> + rnd-offsets:
> + green: 2
> + red-blue: 2
> + # PG, LC, RO
> + - line-threshold:
> + green: 24
> + red-blue: 32
> + line-mad-factor:
> + green: 16
> + red-blue: 24
> + pg-factor:
> + green: 6
> + red-blue: 8
> + ro-limits:
> + green: 2
> + red-blue: 2
> + # PG, LC, RO, RND, RG
> + - line-threshold:
> + green: 32
> + red-blue: 32
> + line-mad-factor:
> + green: 4
> + red-blue: 4
> + pg-factor:
> + green: 10
> + red-blue: 10
> + rnd-threshold:
> + green: 6
> + red-blue: 8
> + rg-factor:
> + green: 4
> + red-blue: 4
> + ro-limits:
> + green: 1
> + red-blue: 2
> + rnd-offsets:
> + green: 2
> + red-blue: 2
> ...
> diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
> index 996edc0a..a32bb9d1 100644
> --- a/src/ipa/rkisp1/rkisp1.cpp
> +++ b/src/ipa/rkisp1/rkisp1.cpp
> @@ -31,6 +31,7 @@
> #include "algorithms/algorithm.h"
> #include "algorithms/awb.h"
> #include "algorithms/blc.h"
> +#include "algorithms/dpcc.h"
> #include "algorithms/gsl.h"
> #include "algorithms/lsc.h"
> #include "libipa/camera_sensor_helper.h"
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list