<div dir="ltr"><div dir="ltr">Hi Jean-Michel,<div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, 7 Jun 2021 at 20:35, Jean-Michel Hautbois <<a href="mailto:jeanmichel.hautbois@ideasonboard.com">jeanmichel.hautbois@ideasonboard.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Naushir,<br>
<br>
On 07/06/2021 20:15, Jean-Michel Hautbois wrote:<br>
> Hi Naushir,<br>
> <br>
> On 07/06/2021 19:31, Naushir Patuck wrote:<br>
>> Hi Jean-Michel,<br>
>><br>
>><br>
>><br>
>> On Mon, 7 Jun 2021 at 13:35, Jean-Michel Hautbois<br>
>> <<a href="mailto:jeanmichel.hautbois@ideasonboard.com" target="_blank">jeanmichel.hautbois@ideasonboard.com</a><br>
>> <mailto:<a href="mailto:jeanmichel.hautbois@ideasonboard.com" target="_blank">jeanmichel.hautbois@ideasonboard.com</a>>> wrote:<br>
>><br>
>>     Setting analogue gain for a specific sensor is not a straghtforward<br>
>>     operation, as one needs to know how the gain is calculated for it.<br>
>><br>
>>     This commit introduces a new camera sensor helper in libipa which aims<br>
>>     to solve this specific issue.<br>
>>     It is based on the MIPI alliance Specification for Camera Command Set<br>
>>     and implements, for now, only the analogue "Global gain" mode.<br>
>><br>
>><br>
>> I know this has probably been discussed in detail internally, but what<br>
>> provisions<br>
>> do you expect for gain formulas that do not conform to the CCI formula,<br>
>> or  those<br>
>> that are entirely table based?<br>
> <br>
> It has not been discussed in detail no, and I am sure I have missed a<br>
> lot of cases.<br>
> For those specific cases, we may, for instance, have a new value in<br>
> AnalogueGainCapability enum and let the subclass calculate the proper<br>
> value ?<br>
> I don't have this case right now in my hands, so it is difficult to know<br>
> precisely what is the best way to do so ;-).<br>
> <br>
>> Thanks,<br>
>> Naush<br>
>><br>
>><br>
>>     Is makes it possible to only have 4 parameters to store per sensor, and<br>
>>     the gain calculation is then done identically for all of them. This<br>
>>     commit gives the gains for imx219 (based on RPi cam_helper), ov5670 and<br>
>>     ov5693.<br>
>><br>
>>     Adding a new sensor is pretty straightfoward as one only needs to<br>
>>     implement the sub-class for it and register that class to the<br>
>>     CameraSensorHelperFactory.<br>
>><br>
>>     Signed-off-by: Jean-Michel Hautbois<br>
>>     <<a href="mailto:jeanmichel.hautbois@ideasonboard.com" target="_blank">jeanmichel.hautbois@ideasonboard.com</a><br>
>>     <mailto:<a href="mailto:jeanmichel.hautbois@ideasonboard.com" target="_blank">jeanmichel.hautbois@ideasonboard.com</a>>><br>
>>     ---<br>
>>      src/ipa/libipa/camera_sensor_helper.cpp | 361 ++++++++++++++++++++++++<br>
>>      src/ipa/libipa/camera_sensor_helper.h   |  91 ++++++<br>
>>      src/ipa/libipa/meson.build              |   2 +<br>
>>      3 files changed, 454 insertions(+)<br>
>>      create mode 100644 src/ipa/libipa/camera_sensor_helper.cpp<br>
>>      create mode 100644 src/ipa/libipa/camera_sensor_helper.h<br>
>><br>
>>     diff --git a/src/ipa/libipa/camera_sensor_helper.cpp<br>
>>     b/src/ipa/libipa/camera_sensor_helper.cpp<br>
>>     new file mode 100644<br>
>>     index 00000000..2bd82861<br>
>>     --- /dev/null<br>
>>     +++ b/src/ipa/libipa/camera_sensor_helper.cpp<br>
>>     @@ -0,0 +1,361 @@<br>
>>     +/* SPDX-License-Identifier: BSD-2-Clause */<br>
>>     +/*<br>
>>     + * Copyright (C) 2021 Ideas On Board<br>
>>     + *<br>
>>     + * camera_sensor_helper.cpp - helper class providing camera<br>
>>     informations<br>
>>     + */<br>
>>     +#include "camera_sensor_helper.h"<br>
>>     +<br>
>>     +#include <map><br>
>>     +<br>
>>     +#include "libcamera/internal/log.h"<br>
>>     +<br>
>>     +/**<br>
>>     + * \file camera_sensor_helper.h<br>
>>     + * \brief Create helper class for each sensor<br>
>>     + *<br>
>>     + * Each camera sensor supported by libcamera may need specific<br>
>>     informations to<br>
>>     + * be sent (analogue gain is sensor dependant for instance).<br>
>>     + *<br>
>>     + * Every subclass of CameraSensorHelper shall be registered with<br>
>>     libipa using<br>
>>     + * the REGISTER_CAMERA_SENSOR_HELPER() macro.<br>
>>     + */<br>
>>     +<br>
>>     +namespace libcamera {<br>
>>     +<br>
>>     +LOG_DEFINE_CATEGORY(CameraSensorHelper)<br>
>>     +<br>
>>     +namespace ipa {<br>
>>     +<br>
>>     +/**<br>
>>     + * \class CameraSensorHelper<br>
>>     + * \brief Create and give helpers for each camera sensor in the<br>
>>     pipeline<br>
>>     + *<br>
>>     + * CameraSensorHelper instances are unique and sensor dependant.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \brief Construct a CameraSensorHelper instance<br>
>>     + * \param[in] name The sensor model name<br>
>>     + *<br>
>>     + * The CameraSensorHelper instances shall never be constructed<br>
>>     manually, but always<br>
>>     + * through the CameraSensorHelperFactory::create() method<br>
>>     implemented by the<br>
>>     + * respective factories.<br>
>>     + */<br>
>>     +<br>
>>     +CameraSensorHelper::CameraSensorHelper(const char *name)<br>
>>     +       : name_(name)<br>
>>     +{<br>
>>     +       analogueGain_ = { GlobalGain, 1, 1, 0, 0 };<br>
>>     +}<br>
>>     +<br>
>>     +CameraSensorHelper::~CameraSensorHelper()<br>
>>     +{<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelper::getGainCode(double gain)<br>
>>     + * \brief Get the analogue gain code to pass to V4L2 subdev control<br>
>>     + * \param[in] gain The real gain to pass<br>
>>     + *<br>
>>     + * This function aims to abstract the calculation of the gain<br>
>>     letting the IPA<br>
>>     + * use the real gain for its estimations.<br>
>>     + *<br>
>>     + * The parameters come from the MIPI Alliance Camera Specification for<br>
>>     + * Camera Command Set (CCS).<br>
>>     + */<br>
>>     +uint32_t CameraSensorHelper::getGainCode(double gain) const<br>
>>     +{<br>
>>     +       /* \todo we only support the global gain mode for now */<br>
>>     +       if (analogueGain_.type != GlobalGain)<br>
>>     +               return UINT32_MAX;<br>
>>     +<br>
>>     +       if (analogueGain_.m0 == 0)<br>
>>     +               return (analogueGain_.c0 - gain * analogueGain_.c1)<br>
>>     / (gain * analogueGain_.m1);<br>
>>     +       if (analogueGain_.m1 == 0)<br>
>>     +               return (gain * analogueGain_.c1 - analogueGain_.c0)<br>
>>     / analogueGain_.m0;<br>
>>     +<br>
>>     +       LOG(CameraSensorHelper, Error) << "For any given image<br>
>>     sensor either m0 or m1 shall be zero.";<br>
>>     +       return 1;<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelper::getGain<br>
>>     + * \brief Get the real gain from the V4l2 subdev control gain<br>
>>     + * \param[in] gainCode The V4l2 subdev control gain<br>
>>     + *<br>
>>     + * This function aims to abstract the calculation of the gain<br>
>>     letting the IPA<br>
>>     + * use the real gain for its estimations. It is the counterpart of<br>
>>     the function<br>
>>     + * CameraSensorHelper::getGainCode.<br>
>>     + *<br>
>>     + * The parameters come from the MIPI Alliance Camera Specification for<br>
>>     + * Camera Command Set (CCS).<br>
>>     + */<br>
>>     +double CameraSensorHelper::getGain(uint32_t gainCode) const<br>
>>     +{<br>
>>     +       if (analogueGain_.type != GlobalGain)<br>
>>     +               return UINT32_MAX;<br>
>>     +<br>
>>     +       if (analogueGain_.m0 == 0)<br>
>>     +               return analogueGain_.c0 / (analogueGain_.m1 *<br>
>>     gainCode + analogueGain_.c1);<br>
>>     +       if (analogueGain_.m1 == 0)<br>
>>     +               return (analogueGain_.m0 * gainCode +<br>
>>     analogueGain_.c0) / analogueGain_.c1;<br>
>>     +<br>
>>     +       LOG(CameraSensorHelper, Error) << "For any given image<br>
>>     sensor either m0 or m1 shall be zero.";<br>
>>     +       return 1.0;<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelper::name()<br>
>>     + * \brief Retrieve the camera sensor helper name<br>
>>     + * \return The camera sensor helper name<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \enum CameraSensorHelper::AnalogueGainCapability<br>
>>     + * \brief Specify the Gain mode supported by the sensor<br>
>>     + *<br>
>>     + * Describes the image sensor analog Gain capabilities.<br>
>>     + * Two modes are possible, depending on the sensor: Global and<br>
>>     Alternate.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::GlobalGain<br>
>>     + * \brief Sensor supports Global gain<br>
>>     + *<br>
>>     + * The relationship between the integer Gain parameter and the<br>
>>     resulting Gain<br>
>>     + * multiplier is given by the following equation:<br>
>>     + *<br>
>>     + * \f$\frac{m0x+c0}{m1x+c1}\f$<br>
>>     + *<br>
>>     + * Where 'x' is the gain control parameter, and m0, m1, c0 and c1 are<br>
>>     + * image-sensor-specific constants exposed by the sensor.<br>
>>     + * These constants are static parameters, and for any given image<br>
>>     sensor either<br>
>>     + * m0 or m1 shall be zero.<br>
>>     + *<br>
>>     + * The full Gain equation therefore reduces to either:<br>
>>     + *<br>
>>     + * \f$\frac{c0}{m1x+c1}\f$ or \f$\frac{m0x+c0}{c1}\f$<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::AlternateGlobalGain<br>
>>     + * \brief Sensor supports Analogue Global gain (introduced in CCS v1.1)<br>
>>     + *<br>
>>     + * Starting with CCS v1.1, Alternate Global Analog Gain is also<br>
>>     available.<br>
>>     + * If the image sensor supports it, then the global analog Gain can<br>
>>     be controlled<br>
>>     + * by linear and exponential gain formula:<br>
>>     + *<br>
>>     + * \f$gain = analogLinearGainGlobal *<br>
>>     2^{analogExponentialGainGlobal} \f$<br>
>>     + * \todo not implemented in libipa<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \struct CameraSensorHelper::analogueGainConstants<br>
>>     + * \brief Analogue gain constants used for gain calculation<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::analogueGainConstants::type<br>
>>     + * \brief Analogue gain coding type<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::analogueGainConstants::m0<br>
>>     + * \brief Constant used in the analog Gain control coding/decoding.<br>
>>     + *<br>
>>     + * Note: either m0 or m1 shall be zero.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::analogueGainConstants::c0<br>
>>     + * \brief Constant used in the analog Gain control coding/decoding.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::analogueGainConstants::m1<br>
>>     + * \brief Constant used in the analog Gain control coding/decoding.<br>
>>     + *<br>
>>     + * Note: either m0 or m1 shall be zero.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::analogueGainConstants::c1<br>
>>     + * \brief Constant used in the analog Gain control coding/decoding.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \var CameraSensorHelper::analogueGain_<br>
>>     + * \brief The analogue gain parameters used for calculation<br>
>>     + *<br>
>>     + * The analogue gain is calculated through a formula, and its<br>
>>     parameters are<br>
>>     + * sensor specific. Use this variable to store the values at init time.<br>
>>     + *<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \class CameraSensorHelperFactory<br>
>>     + * \brief Registration of CameraSensorHelperFactory classes and<br>
>>     creation of instances<br>
>>     + *<br>
>>     + * To facilitate discovery and instantiation of CameraSensorHelper<br>
>>     classes, the<br>
>>     + * CameraSensorHelperFactory class maintains a registry of camera<br>
>>     sensor helper<br>
>>     + * classes. Each CameraSensorHelper subclass shall register itself<br>
>>     using the<br>
>>     + * REGISTER_CAMERA_SENSOR_HELPER() macro, which will create a<br>
>>     corresponding<br>
>>     + * instance of a CameraSensorHelperFactory subclass and register it<br>
>>     with the<br>
>>     + * static list of factories.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \brief Construct a camera sensor helper factory<br>
>>     + * \param[in] name Name of the camera sensor helper class<br>
>>     + *<br>
>>     + * Creating an instance of the factory registers it with the global<br>
>>     list of<br>
>>     + * factories, accessible through the factories() function.<br>
>>     + *<br>
>>     + * The factory \a name is used for debug purpose and shall be unique.<br>
>>     + */<br>
>>     +<br>
>>     +CameraSensorHelperFactory::CameraSensorHelperFactory(const char *name)<br>
>>     +       : name_(name)<br>
>>     +{<br>
>>     +       registerType(this);<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \brief Create an instance of the CameraSensorHelper<br>
>>     corresponding to the factory<br>
>>     + *<br>
>>     + * \return A unique pointer to a new instance of the<br>
>>     CameraSensorHelper subclass<br>
>>     + * corresponding to the factory<br>
>>     + */<br>
>>     +std::unique_ptr<CameraSensorHelper> CameraSensorHelperFactory::create()<br>
>>     +{<br>
>>     +       CameraSensorHelper *handler = createInstance();<br>
>>     +       return std::unique_ptr<CameraSensorHelper>(handler);<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelperFactory::name()<br>
>>     + * \brief Retrieve the factory name<br>
>>     + * \return The factory name<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \brief Add a camera sensor helper class to the registry<br>
>>     + * \param[in] factory Factory to use to construct the camera sensor<br>
>>     helper<br>
>>     + *<br>
>>     + * The caller is responsible to guarantee the uniqueness of the<br>
>>     camera sensor helper<br>
>>     + * name.<br>
>>     + */<br>
>>     +void<br>
>>     CameraSensorHelperFactory::registerType(CameraSensorHelperFactory<br>
>>     *factory)<br>
>>     +{<br>
>>     +       std::vector<CameraSensorHelperFactory *> &factories =<br>
>>     CameraSensorHelperFactory::factories();<br>
>>     +<br>
>>     +       factories.push_back(factory);<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \brief Retrieve the list of all camera sensor helper factories<br>
>>     + *<br>
>>     + * The static factories map is defined inside the function to<br>
>>     ensures it gets<br>
>>     + * initialized on first use, without any dependency on link order.<br>
>>     + *<br>
>>     + * \return The list of camera sensor helper factories<br>
>>     + */<br>
>>     +std::vector<CameraSensorHelperFactory *><br>
>>     &CameraSensorHelperFactory::factories()<br>
>>     +{<br>
>>     +       static std::vector<CameraSensorHelperFactory *> factories;<br>
>>     +       return factories;<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelperFactory::createInstance()<br>
>>     + * \brief Create an instance of the CameraSensorHelper<br>
>>     corresponding to the factory<br>
>>     + *<br>
>>     + * This virtual function is implemented by the<br>
>>     REGISTER_CAMERA_SENSOR_HELPER()<br>
>>     + * macro. It creates a camera sensor helper instance associated<br>
>>     with the camera<br>
>>     + * sensor model.<br>
>>     + *<br>
>>     + * \return A pointer to a newly constructed instance of the<br>
>>     CameraSensorHelper<br>
>>     + * subclass corresponding to the factory<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \def REGISTER_CAMERA_SENSOR_HELPER<br>
>>     + * \brief Register a camera sensor helper with the camera sensor<br>
>>     helper factory<br>
>>     + * \param[in] name Sensor model name used to register the class<br>
>>     + * \param[in] handler Class name of CameraSensorHelper derived<br>
>>     class to register<br>
>>     + *<br>
>>     + * Register a CameraSensorHelper subclass with the factory and make<br>
>>     it available to<br>
>>     + * try and match devices.<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \class CameraSensorHelperImx219<br>
>>     + * \brief Create and give helpers for the imx219 sensor<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelperImx219::CameraSensorHelperImx219<br>
>>     + * \brief Construct a CameraSensorHelperImx219 instance for imx219<br>
>>     + * \param[in] name The sensor model name<br>
>>     + */<br>
>>     +class CameraSensorHelperImx219 : public CameraSensorHelper<br>
>>     +{<br>
>>     +public:<br>
>>     +       CameraSensorHelperImx219(const char *name);<br>
>>     +};<br>
>>     +REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219)<br>
>>     +CameraSensorHelperImx219::CameraSensorHelperImx219(const char *name)<br>
>>     +       : CameraSensorHelper(name)<br>
>>     +{<br>
>>     +       analogueGain_ = { GlobalGain, 0, -1, 256, 256 };<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \class CameraSensorHelperOv5670<br>
>>     + * \brief Create and give helpers for the ov5670 sensor<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelperOv5670::CameraSensorHelperOv5670<br>
>>     + * \brief Construct a CameraSensorHelperOv5670 instance for ov5670<br>
>>     + * \param[in] name The sensor model name<br>
>>     + */<br>
>>     +class CameraSensorHelperOv5670 : public CameraSensorHelper<br>
>>     +{<br>
>>     +public:<br>
>>     +       CameraSensorHelperOv5670(const char *name);<br>
>>     +};<br>
>>     +REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670)<br>
>>     +CameraSensorHelperOv5670::CameraSensorHelperOv5670(const char *name)<br>
>>     +       : CameraSensorHelper(name)<br>
>>     +{<br>
>>     +       analogueGain_ = { GlobalGain, 1, 0, 0, 256 };<br>
>>     +}<br>
>>     +<br>
>>     +/**<br>
>>     + * \class CameraSensorHelperOv5693<br>
>>     + * \brief Create and give helpers for the ov5693 sensor<br>
>>     + */<br>
>>     +<br>
>>     +/**<br>
>>     + * \fn CameraSensorHelperOv5693::CameraSensorHelperOv5693<br>
>>     + * \brief Construct a CameraSensorHelperOv5693 instance for ov5693<br>
>>     + * \param[in] name The sensor model name<br>
>>     + */<br>
>>     +class CameraSensorHelperOv5693 : public CameraSensorHelper<br>
>>     +{<br>
>>     +public:<br>
>>     +       CameraSensorHelperOv5693(const char *name);<br>
>>     +};<br>
>>     +REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693)<br>
>>     +CameraSensorHelperOv5693::CameraSensorHelperOv5693(const char *name)<br>
>>     +       : CameraSensorHelper(name)<br>
>>     +{<br>
>>     +       analogueGain_ = { GlobalGain, 1, 0, 0, 16 };<br>
>>     +}<br>
>>     +<br>
>>     +} /* namespace ipa */<br>
>>     +<br>
>>     +} /* namespace libcamera */<br>
>>     +<br>
>>     diff --git a/src/ipa/libipa/camera_sensor_helper.h<br>
>>     b/src/ipa/libipa/camera_sensor_helper.h<br>
>>     new file mode 100644<br>
>>     index 00000000..63031902<br>
>>     --- /dev/null<br>
>>     +++ b/src/ipa/libipa/camera_sensor_helper.h<br>
>>     @@ -0,0 +1,91 @@<br>
>>     +/* SPDX-License-Identifier: BSD-2-Clause */<br>
>>     +/*<br>
>>     + * Copyright (C) 2021 Ideas On Board<br>
>>     + *<br>
>>     + * camera_sensor_helper.h - helper class providing camera informations<br>
>>     + */<br>
>>     +#ifndef __LIBCAMERA_IPA_LIBIPA_CAMERA_SENSOR_HELPER_H__<br>
>>     +#define __LIBCAMERA_IPA_LIBIPA_CAMERA_SENSOR_HELPER_H__<br>
>>     +<br>
>>     +#include <stdint.h><br>
>>     +<br>
>>     +#include <string><br>
>>     +<br>
>>     +#include <libcamera/class.h><br>
>>     +#include <libcamera/object.h><br>
>>     +<br>
>>     +namespace libcamera {<br>
>>     +<br>
>>     +namespace ipa {<br>
>>     +<br>
>>     +class CameraSensorHelper;<br>
>>     +<br>
>>     +class CameraSensorHelper : public Object<br>
>>     +{<br>
>>     +public:<br>
>>     +       CameraSensorHelper(const char *name);<br>
>>     +       virtual ~CameraSensorHelper();<br>
>>     +<br>
>>     +       const std::string &name() const { return name_; }<br>
>>     +       uint32_t getGainCode(double gain) const;<br>
<br>
Would you prefer getGainCode and getGain to be virtual, having a default<br>
meyhod in CameraSensorHelper and letting those beeing overriden if a<br>
specific sensor needs to have a different formula ?<br></blockquote><div><br></div><div>The Raspberry Pi CamHelper does keep these functions as virtual.  However,</div><div>I know Laurent and others would have a preference of using static data where</div><div>possible.  Perhaps just something to consider for the future rather than doing</div><div>it now.</div><div><br></div><div>Regards,</div><div>Naush</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>>     +       double getGain(uint32_t gainCode) const;<br>
>>     +<br>
>>     +protected:<br>
>>     +       enum AnalogueGainCapability : uint16_t {<br>
>>     +               GlobalGain = 0,<br>
>>     +               AlternateGlobalGain = 2,<br>
>>     +       };<br>
>>     +<br>
>>     +       struct analogueGainConstants {<br>
>>     +               uint16_t type;<br>
>>     +               int16_t m0;<br>
>>     +               int16_t c0;<br>
>>     +               int16_t m1;<br>
>>     +               int16_t c1;<br>
>>     +       };<br>
>>     +       analogueGainConstants analogueGain_;<br>
>>     +<br>
>>     +private:<br>
>>     +       std::string name_;<br>
>>     +       friend class CameraSensorHelperFactory;<br>
>>     +};<br>
>>     +<br>
>>     +class CameraSensorHelperFactory<br>
>>     +{<br>
>>     +public:<br>
>>     +       CameraSensorHelperFactory(const char *name);<br>
>>     +       virtual ~CameraSensorHelperFactory() = default;<br>
>>     +<br>
>>     +       std::unique_ptr<CameraSensorHelper> create();<br>
>>     +<br>
>>     +       const std::string &name() const { return name_; }<br>
>>     +<br>
>>     +       static void registerType(CameraSensorHelperFactory *factory);<br>
>>     +       static std::vector<CameraSensorHelperFactory *> &factories();<br>
>>     +<br>
>>     +private:<br>
>>     +       virtual CameraSensorHelper *createInstance() = 0;<br>
>>     +<br>
>>     +       std::string name_;<br>
>>     +};<br>
>>     +<br>
>>     +#define REGISTER_CAMERA_SENSOR_HELPER(name, handler)               <br>
>>             \<br>
>>     +       class handler##Factory final : public<br>
>>     CameraSensorHelperFactory     \<br>
>>     +       {                                                           <br>
>>            \<br>
>>     +       public:                                                     <br>
>>            \<br>
>>     +               handler##Factory() :<br>
>>     CameraSensorHelperFactory(#handler) {} \<br>
>>     +                                                                   <br>
>>             \<br>
>>     +       private:                                                   <br>
>>             \<br>
>>     +               CameraSensorHelper *createInstance()               <br>
>>             \<br>
>>     +               {                                                   <br>
>>            \<br>
>>     +                       return new handler(name);                   <br>
>>            \<br>
>>     +               }                                                   <br>
>>            \<br>
>>     +       };                                                         <br>
>>             \<br>
>>     +       static handler##Factory global_##handler##Factory;<br>
>>     +<br>
>>     +} /* namespace ipa */<br>
>>     +<br>
>>     +} /* namespace libcamera */<br>
>>     +<br>
>>     +#endif /* __LIBCAMERA_IPA_LIBIPA_CAMERA_SENSOR_HELPER_H__ */<br>
>>     +<br>
>>     diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build<br>
>>     index 038fc490..dc90542c 100644<br>
>>     --- a/src/ipa/libipa/meson.build<br>
>>     +++ b/src/ipa/libipa/meson.build<br>
>>     @@ -2,11 +2,13 @@<br>
>><br>
>>      libipa_headers = files([<br>
>>          'algorithm.h',<br>
>>     +    'camera_sensor_helper.h',<br>
>>          'histogram.h'<br>
>>      ])<br>
>><br>
>>      libipa_sources = files([<br>
>>          'algorithm.cpp',<br>
>>     +    'camera_sensor_helper.cpp',<br>
>>          'histogram.cpp'<br>
>>      ])<br>
>><br>
>>     -- <br>
>>     2.30.2<br>
>><br>
</blockquote></div></div>