<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>