diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2024-02-23 14:03:32 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2024-09-30 11:15:28 +0300 |
commit | e18441c81eb39095e895cba6a89989f6afcf3b40 (patch) | |
tree | 1d6e1055ac12fa3041d2db194b5cc54df145eea7 | |
parent | 616738943dbc26834479d1250f97fdfddac49bb3 (diff) |
libcamera: camera_sensor: Sort factories by priority
In order to support a default implementation for camera sensors when no
better implementation matches, libcamera needs to try "specialized"
implementations first and pick the default last. Make this possible by
adding a priority value for factories. Newly registered factories are
inserted in the factories list sorted by descending priority, and the
default factory uses a negative priority to be inserted as the last
element.
This mechanism may be a bit overkill in the sense that there is no
expected use cases for priorities other than trying the default last,
but the implementation is simple and easy to understand.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
---
Changes since combined RFC:
- Make the factory priority mandatory
-rw-r--r-- | include/libcamera/internal/camera_sensor.h | 14 | ||||
-rw-r--r-- | src/libcamera/sensor/camera_sensor.cpp | 34 | ||||
-rw-r--r-- | src/libcamera/sensor/camera_sensor_legacy.cpp | 2 |
3 files changed, 41 insertions, 9 deletions
diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index d18115bb..ccdb3a9b 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -78,11 +78,13 @@ public: class CameraSensorFactoryBase { public: - CameraSensorFactoryBase(); + CameraSensorFactoryBase(int priority); virtual ~CameraSensorFactoryBase() = default; static std::unique_ptr<CameraSensor> create(MediaEntity *entity); + int priority() const { return priority_; } + private: LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorFactoryBase) @@ -92,14 +94,16 @@ private: virtual std::variant<std::unique_ptr<CameraSensor>, int> match(MediaEntity *entity) const = 0; + + int priority_; }; template<typename _CameraSensor> class CameraSensorFactory final : public CameraSensorFactoryBase { public: - CameraSensorFactory() - : CameraSensorFactoryBase() + CameraSensorFactory(int priority) + : CameraSensorFactoryBase(priority) { } @@ -111,7 +115,7 @@ private: } }; -#define REGISTER_CAMERA_SENSOR(sensor) \ -static CameraSensorFactory<sensor> global_##sensor##Factory{}; +#define REGISTER_CAMERA_SENSOR(sensor, priority) \ +static CameraSensorFactory<sensor> global_##sensor##Factory{ priority }; } /* namespace libcamera */ diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp index e9b383a4..0ad2ab4f 100644 --- a/src/libcamera/sensor/camera_sensor.cpp +++ b/src/libcamera/sensor/camera_sensor.cpp @@ -349,11 +349,13 @@ CameraSensor::~CameraSensor() = default; /** * \brief Construct a camera sensor factory base + * \param[in] priority Priority order for factory selection * * Creating an instance of the factory base registers it with the global list of * factories, accessible through the factories() function. */ -CameraSensorFactoryBase::CameraSensorFactoryBase() +CameraSensorFactoryBase::CameraSensorFactoryBase(int priority) + : priority_(priority) { registerFactory(this); } @@ -362,6 +364,12 @@ CameraSensorFactoryBase::CameraSensorFactoryBase() * \brief Create an instance of the CameraSensor corresponding to a media entity * \param[in] entity The media entity on the source end of the sensor * + * When multiple factories match the same \a entity, this function selects the + * matching factory with the highest priority as specified to the + * REGISTER_CAMERA_SENSOR() macro at factory registration time. If multiple + * matching factories have the same highest priority value, which factory gets + * selected is undefined and may vary between runs. + * * \return A unique pointer to a new instance of the CameraSensor subclass * matching the entity, or a null pointer if no such factory exists */ @@ -389,7 +397,16 @@ std::unique_ptr<CameraSensor> CameraSensorFactoryBase::create(MediaEntity *entit } /** + * \fn CameraSensorFactoryBase::priority() + * \brief Retrieve the priority value for the factory + * \return The priority value for the factory + */ + +/** * \brief Retrieve the list of all camera sensor factories + * + * The factories are sorted in decreasing priority order. + * * \return The list of camera sensor factories */ std::vector<CameraSensorFactoryBase *> &CameraSensorFactoryBase::factories() @@ -412,7 +429,12 @@ void CameraSensorFactoryBase::registerFactory(CameraSensorFactoryBase *factory) std::vector<CameraSensorFactoryBase *> &factories = CameraSensorFactoryBase::factories(); - factories.push_back(factory); + auto pos = std::upper_bound(factories.begin(), factories.end(), factory, + [](const CameraSensorFactoryBase *value, + const CameraSensorFactoryBase *elem) { + return value->priority() > elem->priority(); + }); + factories.insert(pos, factory); } /** @@ -438,9 +460,10 @@ void CameraSensorFactoryBase::registerFactory(CameraSensorFactoryBase *factory) */ /** - * \def REGISTER_CAMERA_SENSOR(sensor) + * \def REGISTER_CAMERA_SENSOR(sensor, priority) * \brief Register a camera sensor type to the sensor factory * \param[in] sensor Class name of the CameraSensor derived class to register + * \param[in] priority Priority order for factory selection * * Register a CameraSensor subclass with the factory and make it available to * try and match sensors. The subclass needs to implement a static match @@ -458,6 +481,11 @@ void CameraSensorFactoryBase::registerFactory(CameraSensorFactoryBase *factory) * creation succeeded ; * - A non-zero error code if the entity matched and the creation failed ; or * - A zero error code if the entity didn't match. + * + * When multiple factories can support the same MediaEntity (as in the match() + * function of multiple factories returning true for the same entity), the \a + * priority argument selects which factory will be used. See + * CameraSensorFactoryBase::create() for more information. */ } /* namespace libcamera */ diff --git a/src/libcamera/sensor/camera_sensor_legacy.cpp b/src/libcamera/sensor/camera_sensor_legacy.cpp index 6affee78..dfb297bb 100644 --- a/src/libcamera/sensor/camera_sensor_legacy.cpp +++ b/src/libcamera/sensor/camera_sensor_legacy.cpp @@ -1010,6 +1010,6 @@ std::string CameraSensorLegacy::logPrefix() const return "'" + entity_->name() + "'"; } -REGISTER_CAMERA_SENSOR(CameraSensorLegacy) +REGISTER_CAMERA_SENSOR(CameraSensorLegacy, -100) } /* namespace libcamera */ |