diff options
-rw-r--r-- | src/ipa/libipa/camera_sensor_helper.cpp | 318 | ||||
-rw-r--r-- | src/ipa/libipa/camera_sensor_helper.h | 87 | ||||
-rw-r--r-- | src/ipa/libipa/meson.build | 2 |
3 files changed, 407 insertions, 0 deletions
diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp new file mode 100644 index 00000000..23335ed6 --- /dev/null +++ b/src/ipa/libipa/camera_sensor_helper.cpp @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * camera_sensor_helper.cpp - Helper class that performs sensor-specific parameter computations + */ +#include "camera_sensor_helper.h" + +#include "libcamera/base/log.h" + +/** + * \file camera_sensor_helper.h + * \brief Helper class that performs sensor-specific parameter computations + * + * Computation of sensor configuration parameters is a sensor specific + * operation. Each CameraHelper derived class computes the value of + * configuration parameters, for example the analogue gain value, using + * sensor-specific functions and constants. + * + * Every subclass of CameraSensorHelper shall be registered with libipa using + * the REGISTER_CAMERA_SENSOR_HELPER() macro. + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(CameraSensorHelper) + +namespace ipa { + +/** + * \class CameraSensorHelper + * \brief Base class for computing sensor tuning parameters using sensor-specific constants + * + * Instances derived from CameraSensorHelper class are sensor specific. + * Each supported sensor will have an associated base class defined. + */ + +/** + * \brief Construct a CameraSensorHelper instance + * + * CameraSensorHelper derived class instances shall never be constructed manually + * but always through the CameraSensorHelperFactory::create() method. + */ + +/** + * \brief Compute gain code from the analogue gain absolute value + * \param[in] gain The real gain to pass + * + * This function aims to abstract the calculation of the gain letting the IPA + * use the real gain for its estimations. + * + * The parameters come from the MIPI Alliance Camera Specification for + * Camera Command Set (CCS). + * + * \return The gain code to pass to V4l2 + */ +uint32_t CameraSensorHelper::gainCode(double gain) const +{ + ASSERT((analogueGainConstants_.m0 == 0) || (analogueGainConstants_.m1 == 0)); + ASSERT(analogueGainConstants_.type == AnalogueGainLinear); + + return (analogueGainConstants_.c0 - analogueGainConstants_.c1 * gain) / + (analogueGainConstants_.m1 * gain - analogueGainConstants_.m0); +} + +/** + * \brief Compute the real gain from the V4l2 subdev control gain code + * \param[in] gainCode The V4l2 subdev control gain + * + * This function aims to abstract the calculation of the gain letting the IPA + * use the real gain for its estimations. It is the counterpart of the function + * CameraSensorHelper::gainCode. + * + * The parameters come from the MIPI Alliance Camera Specification for + * Camera Command Set (CCS). + * + * \return The real gain + */ +double CameraSensorHelper::gain(uint32_t gainCode) const +{ + ASSERT((analogueGainConstants_.m0 == 0) || (analogueGainConstants_.m1 == 0)); + ASSERT(analogueGainConstants_.type == AnalogueGainLinear); + + return (analogueGainConstants_.m0 * static_cast<double>(gainCode) + analogueGainConstants_.c0) / + (analogueGainConstants_.m1 * static_cast<double>(gainCode) + analogueGainConstants_.c1); +} + +/** + * \enum CameraSensorHelper::AnalogueGainType + * \brief The gain calculation modes as defined by the MIPI CCS + * + * Describes the image sensor analogue gain capabilities. + * Two modes are possible, depending on the sensor: Global and Alternate. + */ + +/** + * \var CameraSensorHelper::AnalogueGainLinear + * \brief Gain is computed using linear gain estimation + * + * The relationship between the integer gain parameter and the resulting gain + * multiplier is given by the following equation: + * + * \f$gain=\frac{m0x+c0}{m1x+c1}\f$ + * + * Where 'x' is the gain control parameter, and m0, m1, c0 and c1 are + * image-sensor-specific constants of the sensor. + * These constants are static parameters, and for any given image sensor either + * m0 or m1 shall be zero. + * + * The full Gain equation therefore reduces to either: + * + * \f$gain=\frac{c0}{m1x+c1}\f$ or \f$\frac{m0x+c0}{c1}\f$ + */ + +/** + * \var CameraSensorHelper::AnalogueGainExponential + * \brief Gain is computed using exponential gain estimation (introduced in CCS v1.1) + * + * Starting with CCS v1.1, Alternate Global Analogue Gain is also available. + * If the image sensor supports it, then the global analogue gain can be controlled + * by linear and exponential gain formula: + * + * \f$gain = analogLinearGainGlobal * 2^{analogExponentialGainGlobal}\f$ + * \todo not implemented in libipa + */ + +/** + * \struct CameraSensorHelper::AnalogueGainConstants + * \brief Analogue gain constants used for gain calculation + */ + +/** + * \var CameraSensorHelper::AnalogueGainConstants::type + * \brief Analogue gain calculation mode + */ + +/** + * \var CameraSensorHelper::AnalogueGainConstants::m0 + * \brief Constant used in the analogue Gain coding/decoding + * + * \note Either m0 or m1 shall be zero. + */ + +/** + * \var CameraSensorHelper::AnalogueGainConstants::c0 + * \brief Constant used in the analogue gain coding/decoding + */ + +/** + * \var CameraSensorHelper::AnalogueGainConstants::m1 + * \brief Constant used in the analogue gain coding/decoding + * + * \note Either m0 or m1 shall be zero. + */ + +/** + * \var CameraSensorHelper::AnalogueGainConstants::c1 + * \brief Constant used in the analogue gain coding/decoding + */ + +/** + * \var CameraSensorHelper::analogueGainConstants_ + * \brief The analogue gain parameters used for calculation + * + * The analogue gain is calculated through a formula, and its parameters are + * sensor specific. Use this variable to store the values at init time. + */ + +/** + * \class CameraSensorHelperFactory + * \brief Registration of CameraSensorHelperFactory classes and creation of instances + * + * To facilitate discovery and instantiation of CameraSensorHelper classes, the + * CameraSensorHelperFactory class maintains a registry of camera sensor helper + * sub-classes. Each CameraSensorHelper subclass shall register itself using the + * REGISTER_CAMERA_SENSOR_HELPER() macro, which will create a corresponding + * instance of a CameraSensorHelperFactory subclass and register it with the + * static list of factories. + */ + +/** + * \brief Construct a camera sensor helper factory + * \param[in] name Name of the camera sensor helper class + * + * Creating an instance of the factory registers it with the global list of + * factories, accessible through the factories() function. + * + * The factory \a name is used for debug purpose and shall be unique. + */ +CameraSensorHelperFactory::CameraSensorHelperFactory(const std::string name) + : name_(name) +{ + registerType(this); +} + +/** + * \brief Create an instance of the CameraSensorHelper corresponding to the factory + * \param[in] name Name of the factory + * + * \return A unique pointer to a new instance of the CameraSensorHelper subclass + * corresponding to the factory + */ +std::unique_ptr<CameraSensorHelper> CameraSensorHelperFactory::create(const std::string &name) +{ + std::vector<CameraSensorHelperFactory *> &factories = + CameraSensorHelperFactory::factories(); + + for (CameraSensorHelperFactory *factory : factories) { + if (name != factory->name_) + continue; + + CameraSensorHelper *helper = factory->createInstance(); + return std::unique_ptr<CameraSensorHelper>(helper); + } + + return nullptr; +} + +/** + * \brief Add a camera sensor helper class to the registry + * \param[in] factory Factory to use to construct the camera sensor helper + * + * The caller is responsible to guarantee the uniqueness of the camera sensor helper + * name. + */ +void CameraSensorHelperFactory::registerType(CameraSensorHelperFactory *factory) +{ + std::vector<CameraSensorHelperFactory *> &factories = CameraSensorHelperFactory::factories(); + + factories.push_back(factory); +} + +/** + * \brief Retrieve the list of all camera sensor helper factories + * + * The static factories map is defined inside the function to ensures it gets + * initialized on first use, without any dependency on link order. + * + * \return The list of camera sensor helper factories + */ +std::vector<CameraSensorHelperFactory *> &CameraSensorHelperFactory::factories() +{ + static std::vector<CameraSensorHelperFactory *> factories; + return factories; +} + +/** + * \fn CameraSensorHelperFactory::createInstance() + * \brief Create an instance of the CameraSensorHelper corresponding to the factory + * + * This virtual function is implemented by the REGISTER_CAMERA_SENSOR_HELPER() + * macro. It creates a camera sensor helper instance associated with the camera + * sensor model. + * + * \return A pointer to a newly constructed instance of the CameraSensorHelper + * subclass corresponding to the factory + */ + +/** + * \var CameraSensorHelperFactory::name_ + * \brief The name of the factory + */ + +/** + * \def REGISTER_CAMERA_SENSOR_HELPER + * \brief Register a camera sensor helper with the camera sensor helper factory + * \param[in] name Sensor model name used to register the class + * \param[in] helper Class name of CameraSensorHelper derived class to register + * + * Register a CameraSensorHelper subclass with the factory and make it available to + * try and match devices. + */ + +/** + * \class CameraSensorHelperImx219 + * \brief Create and give helpers for the imx219 sensor + */ +class CameraSensorHelperImx219 : public CameraSensorHelper +{ +public: + CameraSensorHelperImx219() + { + analogueGainConstants_ = { AnalogueGainLinear, 0, -1, 256, 256 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219) + +/** + * \class CameraSensorHelperOv5670 + * \brief Create and give helpers for the ov5670 sensor + */ +class CameraSensorHelperOv5670 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv5670() + { + analogueGainConstants_ = { AnalogueGainLinear, 1, 0, 0, 256 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670) + +/** + * \class CameraSensorHelperOv5693 + * \brief Create and give helpers for the ov5693 sensor + */ +class CameraSensorHelperOv5693 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv5693() + { + analogueGainConstants_ = { AnalogueGainLinear, 1, 0, 0, 16 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693) + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h new file mode 100644 index 00000000..1c47e8d5 --- /dev/null +++ b/src/ipa/libipa/camera_sensor_helper.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * camera_sensor_helper.h - Helper class that performs sensor-specific parameter computations + */ +#ifndef __LIBCAMERA_IPA_LIBIPA_CAMERA_SENSOR_HELPER_H__ +#define __LIBCAMERA_IPA_LIBIPA_CAMERA_SENSOR_HELPER_H__ + +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include <libcamera/base/class.h> + +namespace libcamera { + +namespace ipa { + +class CameraSensorHelper +{ +public: + CameraSensorHelper() = default; + virtual ~CameraSensorHelper() = default; + + virtual uint32_t gainCode(double gain) const; + virtual double gain(uint32_t gainCode) const; + +protected: + enum AnalogueGainType { + AnalogueGainLinear = 0, + AnalogueGainExponential = 2, + }; + + struct AnalogueGainConstants { + AnalogueGainType type; + int16_t m0; + int16_t c0; + int16_t m1; + int16_t c1; + }; + + AnalogueGainConstants analogueGainConstants_; + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelper) +}; + +class CameraSensorHelperFactory +{ +public: + CameraSensorHelperFactory(const std::string name); + virtual ~CameraSensorHelperFactory() = default; + + static std::unique_ptr<CameraSensorHelper> create(const std::string &name); + + static void registerType(CameraSensorHelperFactory *factory); + static std::vector<CameraSensorHelperFactory *> &factories(); + +protected: + LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelperFactory) + virtual CameraSensorHelper *createInstance() = 0; + + std::string name_; +}; + +#define REGISTER_CAMERA_SENSOR_HELPER(name, helper) \ +class helper##Factory final : public CameraSensorHelperFactory \ +{ \ +public: \ + helper##Factory() : CameraSensorHelperFactory(name) {} \ + \ +private: \ + CameraSensorHelper *createInstance() \ + { \ + return new helper(); \ + } \ +}; \ +static helper##Factory global_##helper##Factory; + +} /* namespace ipa */ + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_IPA_LIBIPA_CAMERA_SENSOR_HELPER_H__ */ diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index ca541a5a..3fda7c00 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -2,11 +2,13 @@ libipa_headers = files([ 'algorithm.h', + 'camera_sensor_helper.h', 'histogram.h' ]) libipa_sources = files([ 'algorithm.cpp', + 'camera_sensor_helper.cpp', 'histogram.cpp' ]) |