From patchwork Fri Mar 1 21:21:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 19612 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B0ADFBD160 for ; Fri, 1 Mar 2024 21:21:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 678E862C82; Fri, 1 Mar 2024 22:21:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="vZNL0+Wr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C58E6628AC for ; Fri, 1 Mar 2024 22:21:50 +0100 (CET) Received: from pendragon.ideasonboard.com (89-27-53-110.bb.dnainternet.fi [89.27.53.110]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5E882293D; Fri, 1 Mar 2024 22:21:36 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1709328096; bh=HTen9yhdwhNj3A4+larhQckfxT8mZx8SBdgV+NXMWkY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vZNL0+WrW3Eoy+VW4s8eXtxUawTzl3KdWrIK4gRuiNkBxHJN/qoxBVNbqZT8UgTAb yFM33iIukXHqDDCko0g5TRZGgXjzNYPkkA8XpBy/QEJ6G+zKuB1AAuw60x2KaZ2I9b KFJa6K9auV+XPqqTrjELTwaCeuJNshQerHjEmYLI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH/RFC 21/32] libcamera: camera_sensor: Sort factories by priority Date: Fri, 1 Mar 2024 23:21:10 +0200 Message-ID: <20240301212121.9072-22-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240301212121.9072-1-laurent.pinchart@ideasonboard.com> References: <20240301212121.9072-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Sakari Ailus Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 Reviewed-by: Stefan Klug --- include/libcamera/internal/camera_sensor.h | 18 +++++++--- src/libcamera/sensor/camera_sensor.cpp | 34 +++++++++++++++++-- src/libcamera/sensor/camera_sensor_legacy.cpp | 2 +- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index d37e66773195..59785ff62019 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -79,11 +79,13 @@ public: class CameraSensorFactoryBase { public: - CameraSensorFactoryBase(); + CameraSensorFactoryBase(int priority); virtual ~CameraSensorFactoryBase() = default; static std::unique_ptr create(MediaEntity *entity); + int priority() const { return priority_; } + private: LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorFactoryBase) @@ -93,14 +95,16 @@ private: virtual std::variant, int> match(MediaEntity *entity) const = 0; + + int priority_; }; template class CameraSensorFactory final : public CameraSensorFactoryBase { public: - CameraSensorFactory() - : CameraSensorFactoryBase() + CameraSensorFactory(int priority = 0) + : CameraSensorFactoryBase(priority) { } @@ -112,7 +116,11 @@ private: } }; -#define REGISTER_CAMERA_SENSOR(sensor) \ - static CameraSensorFactory global_##sensor##Factory{}; +#ifndef __DOXYGEN__ +#define REGISTER_CAMERA_SENSOR(sensor, ...) \ + static CameraSensorFactory global_##sensor##Factory{ __VA_ARGS__ }; +#else +#define REGISTER_CAMERA_SENSOR(sensor, priority) +#endif } /* namespace libcamera */ diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp index 7abbe2c76596..e7b526c2f050 100644 --- a/src/libcamera/sensor/camera_sensor.cpp +++ b/src/libcamera/sensor/camera_sensor.cpp @@ -348,11 +348,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); } @@ -361,6 +363,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 */ @@ -387,8 +395,17 @@ std::unique_ptr CameraSensorFactoryBase::create(MediaEntity *entit return nullptr; } +/** + * \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::factories() @@ -411,7 +428,12 @@ void CameraSensorFactoryBase::registerFactory(CameraSensorFactoryBase *factory) std::vector &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); } /** @@ -437,9 +459,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 @@ -457,6 +480,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 34677339241c..f9f889a125d0 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 */