[PATCH v4 3/3] ipa: rkisp1: Add GammaOutCorrection algorithm

Stefan Klug stefan.klug at ideasonboard.com
Mon Jun 10 14:46:43 CEST 2024


On Mon, Jun 10, 2024 at 09:41:50PM +0900, Paul Elder wrote:
> On Wed, Jun 05, 2024 at 11:53:51AM +0200, Stefan Klug wrote:
> > Add a gamma algorithm for the rkisp1. It defaults to a gamma of 2.2 which
> > closely resembles sRGB.  No seperate sRGB mode was implemented because the pwl
> > that models the gamma curve is so coarse that there is basically no difference
> > between srgb and gamma=2.2. The default can be overridden within the tuning
> > file or set at runtime using the gamma control.
> > 
> > The gamma algorithm is not enabled by default. This will be done in future
> > tuning file updates.
> > 
> > Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>
> > Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> > ---
> >  src/ipa/rkisp1/algorithms/goc.cpp     | 153 ++++++++++++++++++++++++++
> >  src/ipa/rkisp1/algorithms/goc.h       |  42 +++++++
> >  src/ipa/rkisp1/algorithms/meson.build |   1 +
> >  src/ipa/rkisp1/ipa_context.h          |   9 ++
> >  4 files changed, 205 insertions(+)
> >  create mode 100644 src/ipa/rkisp1/algorithms/goc.cpp
> >  create mode 100644 src/ipa/rkisp1/algorithms/goc.h
> > 
> > diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp
> > new file mode 100644
> > index 000000000000..ab634c1c9709
> > --- /dev/null
> > +++ b/src/ipa/rkisp1/algorithms/goc.cpp
> > @@ -0,0 +1,153 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +/*
> > + * Copyright (C) 2024, Ideas On Board
> > + *
> > + * RkISP1 Gamma out control
> > + */
> > +#include "goc.h"
> > +
> > +#include <cmath>
> > +
> > +#include <libcamera/base/log.h>
> > +#include <libcamera/base/utils.h>
> > +
> > +#include <libcamera/control_ids.h>
> > +
> > +#include "libcamera/internal/yaml_parser.h"
> > +
> > +#include "linux/rkisp1-config.h"
> > +
> > +/**
> > + * \file goc.h
> > + */
> > +
> > +namespace libcamera {
> > +
> > +namespace ipa::rkisp1::algorithms {
> > +
> > +/**
> > + * \class GammaOutCorrection
> > + * \brief RkISP1 Gamma out correction
> > + *
> > + * This algorithm implements the gamma out curve for the RkISP1.
> > + * It defaults to a gamma value of 2.2
> > + * As gamma is internally represented as a piecewise linear function with only
> > + * 17 knots, the difference between gamma=2.2 and sRGB gamma is minimal.
> > + * Therefore sRGB gamma was not implemented as special case.
> > + *
> > + * Useful links:
> > + * https://www.cambridgeincolour.com/tutorials/gamma-correction.htm
> > + * https://en.wikipedia.org/wiki/SRGB
> > + */
> > +
> > +LOG_DEFINE_CATEGORY(RkISP1Gamma)
> > +
> > +const float kDefaultGamma = 2.2f;
> > +
> > +/**
> > + * \copydoc libcamera::ipa::Algorithm::init
> > + */
> > +int GammaOutCorrection::init([[maybe_unused]] IPAContext &context,
> > +			     [[maybe_unused]] const YamlObject &tuningData)
> > +{
> > +	if (context.hw->numGammaOutSamples !=
> > +	    RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10) {
> > +		LOG(RkISP1Gamma, Error)
> > +			<< "Gamma is not implemented for RkISP1 V12";
> > +		return -EINVAL;
> > +	}
> > +
> > +	context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, kDefaultGamma);
> > +	defaultGamma_ = tuningData["gamma"].get<double>(kDefaultGamma);
> 
> I think these should be switched so that the default gamma that's read
> from the tuning file will be set as the default gamma in the
> ControlInfo. Otherwise the default that's set and reported via metadata
> wouldn't be consistent with the default that's reported in the
> ControlInfo.

Oh, good catch. I'll fix that. 
Thank you.

> 
> With that changed:
> 
> Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>
> 
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * \brief Configure the Gamma given a configInfo
> > + * \param[in] context The shared IPA context
> > + * \param[in] configInfo The IPA configuration data
> > + *
> > + * \return 0
> > + */
> > +int GammaOutCorrection::configure(IPAContext &context,
> > +				  [[maybe_unused]] const IPACameraSensorInfo &configInfo)
> > +{
> > +	context.activeState.goc.gamma = defaultGamma_;
> > +	return 0;
> > +}
> > +
> > +/**
> > + * \copydoc libcamera::ipa::Algorithm::queueRequest
> > + */
> > +void GammaOutCorrection::queueRequest([[maybe_unused]] IPAContext &context,
> > +				      [[maybe_unused]] const uint32_t frame,
> > +				      IPAFrameContext &frameContext,
> > +				      const ControlList &controls)
> > +{
> > +	if (frame == 0)
> > +		frameContext.goc.update = true;
> > +
> > +	const auto &gamma = controls.get(controls::Gamma);
> > +	if (gamma) {
> > +		context.activeState.goc.gamma = *gamma;
> > +		frameContext.goc.update = true;
> > +		LOG(RkISP1Gamma, Debug) << "Set gamma to " << *gamma;
> > +	}
> > +
> > +	frameContext.goc.gamma = context.activeState.goc.gamma;
> > +}
> > +
> > +/**
> > + * \copydoc libcamera::ipa::Algorithm::prepare
> > + */
> > +void GammaOutCorrection::prepare([[maybe_unused]] IPAContext &context,
> > +				 [[maybe_unused]] const uint32_t frame,
> > +				 [[maybe_unused]] IPAFrameContext &frameContext,
> > +				 rkisp1_params_cfg *params)
> > +{
> > +	ASSERT(context.hw->numGammaOutSamples ==
> > +	       RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10);
> > +
> > +	/*
> > +	 * The logarithmic segments as specified in the reference.
> > +	 * Plus an additional 0 to make the loop easier
> > +	 */
> > +	std::array<unsigned, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10> segments = {
> > +		64, 64, 64, 64, 128, 128, 128, 128, 256,
> > +		256, 256, 512, 512, 512, 512, 512, 0
> > +	};
> > +	auto gamma_y = params->others.goc_config.gamma_y;
> > +
> > +	if (!frameContext.goc.update)
> > +		return;
> > +
> > +	unsigned x = 0;
> > +	for (const auto [i, size] : utils::enumerate(segments)) {
> > +		gamma_y[i] = std::pow(x / 4096.0, 1.0 / frameContext.goc.gamma) * 1023.0;
> > +		x += size;
> > +	}
> > +
> > +	params->others.goc_config.mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC;
> > +	params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_GOC;
> > +	params->module_en_update |= RKISP1_CIF_ISP_MODULE_GOC;
> > +	params->module_ens |= RKISP1_CIF_ISP_MODULE_GOC;
> > +}
> > +
> > +/**
> > + * \copydoc libcamera::ipa::Algorithm::process
> > + */
> > +void GammaOutCorrection::process([[maybe_unused]] IPAContext &context,
> > +				 [[maybe_unused]] const uint32_t frame,
> > +				 IPAFrameContext &frameContext,
> > +				 [[maybe_unused]] const rkisp1_stat_buffer *stats,
> > +				 ControlList &metadata)
> > +{
> > +	metadata.set(controls::Gamma, frameContext.goc.gamma);
> > +}
> > +
> > +REGISTER_IPA_ALGORITHM(GammaOutCorrection, "GammaOutCorrection")
> > +
> > +} /* namespace ipa::rkisp1::algorithms */
> > +
> > +} /* namespace libcamera */
> > diff --git a/src/ipa/rkisp1/algorithms/goc.h b/src/ipa/rkisp1/algorithms/goc.h
> > new file mode 100644
> > index 000000000000..3be8e500be67
> > --- /dev/null
> > +++ b/src/ipa/rkisp1/algorithms/goc.h
> > @@ -0,0 +1,42 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +/*
> > + * Copyright (C) 2024, Ideas On Board
> > + *
> > + * RkISP1 Gamma out control
> > + */
> > +
> > +#pragma once
> > +
> > +#include "algorithm.h"
> > +
> > +namespace libcamera {
> > +
> > +namespace ipa::rkisp1::algorithms {
> > +
> > +class GammaOutCorrection : public Algorithm
> > +{
> > +public:
> > +	GammaOutCorrection() = default;
> > +	~GammaOutCorrection() = default;
> > +
> > +	int init(IPAContext &context, const YamlObject &tuningData) override;
> > +	int configure(IPAContext &context,
> > +		      const IPACameraSensorInfo &configInfo) override;
> > +	void queueRequest(IPAContext &context,
> > +			  const uint32_t frame,
> > +			  IPAFrameContext &frameContext,
> > +			  const ControlList &controls) override;
> > +	void prepare(IPAContext &context, const uint32_t frame,
> > +		     IPAFrameContext &frameContext,
> > +		     rkisp1_params_cfg *params) override;
> > +	void process(IPAContext &context, const uint32_t frame,
> > +		     IPAFrameContext &frameContext,
> > +		     const rkisp1_stat_buffer *stats,
> > +		     ControlList &metadata) override;
> > +
> > +private:
> > +	double defaultGamma_;
> > +};
> > +
> > +} /* namespace ipa::rkisp1::algorithms */
> > +} /* namespace libcamera */
> > diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build
> > index 93a483292753..6ee71a9b5da3 100644
> > --- a/src/ipa/rkisp1/algorithms/meson.build
> > +++ b/src/ipa/rkisp1/algorithms/meson.build
> > @@ -8,6 +8,7 @@ rkisp1_ipa_algorithms = files([
> >      'dpcc.cpp',
> >      'dpf.cpp',
> >      'filter.cpp',
> > +    'goc.cpp',
> >      'gsl.cpp',
> >      'lsc.cpp',
> >  ])
> > diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
> > index bd02a7a24fdd..f261e42fc2fd 100644
> > --- a/src/ipa/rkisp1/ipa_context.h
> > +++ b/src/ipa/rkisp1/ipa_context.h
> > @@ -104,6 +104,10 @@ struct IPAActiveState {
> >  		uint8_t denoise;
> >  		uint8_t sharpness;
> >  	} filter;
> > +
> > +	struct {
> > +		double gamma;
> > +	} goc;
> >  };
> >  
> >  struct IPAFrameContext : public FrameContext {
> > @@ -146,6 +150,11 @@ struct IPAFrameContext : public FrameContext {
> >  		uint32_t exposure;
> >  		double gain;
> >  	} sensor;
> > +
> > +	struct {
> > +		double gamma;
> > +		bool update;
> > +	} goc;
> >  };
> >  
> >  struct IPAContext {
> > -- 
> > 2.43.0
> > 


More information about the libcamera-devel mailing list