[libcamera-devel] [PATCH 8/8] libcamera: pipeline_handler: Implement factories through class templates
Xavier Roumegue (OSS)
xavier.roumegue at oss.nxp.com
Wed Oct 5 13:17:30 CEST 2022
Hi Laurent,
Thanks for the patch.
On 10/3/22 23:21, Laurent Pinchart via libcamera-devel wrote:
> The REGISTER_PIPELINE_HANDLER() macro defines a class type that inherits
> from the PipelineHandlerFactory class, and implements a constructor and
> a createInstance() function. Replace the code generation through macro
> with the C++ equivalent, a class template, as done in libipa with the
> Algorithm and CameraSensorHelper factories.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> include/libcamera/internal/pipeline_handler.h | 44 +++++++------
> src/libcamera/camera_manager.cpp | 6 +-
> src/libcamera/pipeline_handler.cpp | 65 ++++++++++++-------
> test/ipa/ipa_interface_test.cpp | 6 +-
> 4 files changed, 71 insertions(+), 50 deletions(-)
>
> diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
> index ad74dc823290..b6139a88d421 100644
> --- a/include/libcamera/internal/pipeline_handler.h
> +++ b/include/libcamera/internal/pipeline_handler.h
> @@ -95,23 +95,23 @@ private:
> Mutex lock_;
> unsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_);
>
> - friend class PipelineHandlerFactory;
> + friend class PipelineHandlerFactoryBase;
> };
>
> -class PipelineHandlerFactory
> +class PipelineHandlerFactoryBase
> {
> public:
> - PipelineHandlerFactory(const char *name);
> - virtual ~PipelineHandlerFactory() = default;
> + PipelineHandlerFactoryBase(const char *name);
> + virtual ~PipelineHandlerFactoryBase() = default;
>
> std::shared_ptr<PipelineHandler> create(CameraManager *manager) const;
>
> const std::string &name() const { return name_; }
>
> - static std::vector<PipelineHandlerFactory *> &factories();
> + static std::vector<PipelineHandlerFactoryBase *> &factories();
>
> private:
> - static void registerType(PipelineHandlerFactory *factory);
> + static void registerType(PipelineHandlerFactoryBase *factory);
>
> virtual std::unique_ptr<PipelineHandler>
> createInstance(CameraManager *manager) const = 0;
> @@ -119,19 +119,23 @@ private:
> std::string name_;
> };
>
> -#define REGISTER_PIPELINE_HANDLER(handler) \
> -class handler##Factory final : public PipelineHandlerFactory \
> -{ \
> -public: \
> - handler##Factory() : PipelineHandlerFactory(#handler) {} \
> - \
> -private: \
> - std::unique_ptr<PipelineHandler> \
> - createInstance(CameraManager *manager) const \
> - { \
> - return std::make_unique<handler>(manager); \
> - } \
> -}; \
> -static handler##Factory global_##handler##Factory;
> +template<typename _PipelineHandler>
> +class PipelineHandlerFactory final : public PipelineHandlerFactoryBase
> +{
> +public:
> + PipelineHandlerFactory(const char *name)
> + : PipelineHandlerFactoryBase(name)
> + {
> + }
> +
> + std::unique_ptr<PipelineHandler>
> + createInstance(CameraManager *manager) const override
> + {
> + return std::make_unique<_PipelineHandler>(manager);
> + }
> +};
> +
> +#define REGISTER_PIPELINE_HANDLER(handler) \
> +static PipelineHandlerFactory<handler> global_##handler##Factory(#handler);
>
> } /* namespace libcamera */
> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp
> index 2c3f2d86c469..2c100c24af4d 100644
> --- a/src/libcamera/camera_manager.cpp
> +++ b/src/libcamera/camera_manager.cpp
> @@ -142,10 +142,10 @@ void CameraManager::Private::createPipelineHandlers()
> * file and only fallback on all handlers if there is no
> * configuration file.
> */
> - const std::vector<PipelineHandlerFactory *> &factories =
> - PipelineHandlerFactory::factories();
> + const std::vector<PipelineHandlerFactoryBase *> &factories =
> + PipelineHandlerFactoryBase::factories();
>
> - for (const PipelineHandlerFactory *factory : factories) {
> + for (const PipelineHandlerFactoryBase *factory : factories) {
> LOG(Camera, Debug)
> << "Found registered pipeline handler '"
> << factory->name() << "'";
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 488dd8d32cdf..44f6fc531ad7 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -64,8 +64,7 @@ LOG_DEFINE_CATEGORY(Pipeline)
> *
> * In order to honour the std::enable_shared_from_this<> contract,
> * PipelineHandler instances shall never be constructed manually, but always
> - * through the PipelineHandlerFactory::create() function implemented by the
> - * respective factories.
> + * through the PipelineHandlerFactoryBase::create() function.
> */
> PipelineHandler::PipelineHandler(CameraManager *manager)
> : manager_(manager), useCount_(0)
> @@ -643,27 +642,25 @@ void PipelineHandler::disconnect()
> */
>
> /**
> - * \class PipelineHandlerFactory
> - * \brief Registration of PipelineHandler classes and creation of instances
> + * \class PipelineHandlerFactoryBase
> + * \brief Base class for pipeline handler factories
> *
> - * To facilitate discovery and instantiation of PipelineHandler classes, the
> - * PipelineHandlerFactory class maintains a registry of pipeline handler
> - * classes. Each PipelineHandler subclass shall register itself using the
> - * REGISTER_PIPELINE_HANDLER() macro, which will create a corresponding
> - * instance of a PipelineHandlerFactory subclass and register it with the
> - * static list of factories.
> + * The PipelineHandlerFactoryBase class is the base of all specializations of
> + * the PipelineHandlerFactory class template. It implements the factory
> + * registration, maintains a registry of factories, and provides access to the
> + * registered factories.
> */
>
> /**
> - * \brief Construct a pipeline handler factory
> + * \brief Construct a pipeline handler factory base
> * \param[in] name Name of the pipeline handler class
> *
> - * Creating an instance of the factory registers is with the global list of
> + * Creating an instance of the factory base registers is with the global list of
s/is/it/
> * factories, accessible through the factories() function.
> *
> * The factory \a name is used for debug purpose and shall be unique.
> */
> -PipelineHandlerFactory::PipelineHandlerFactory(const char *name)
> +PipelineHandlerFactoryBase::PipelineHandlerFactoryBase(const char *name)
> : name_(name)
> {
> registerType(this);
> @@ -676,7 +673,7 @@ PipelineHandlerFactory::PipelineHandlerFactory(const char *name)
> * \return A shared pointer to a new instance of the PipelineHandler subclass
> * corresponding to the factory
> */
> -std::shared_ptr<PipelineHandler> PipelineHandlerFactory::create(CameraManager *manager) const
> +std::shared_ptr<PipelineHandler> PipelineHandlerFactoryBase::create(CameraManager *manager) const
> {
> std::unique_ptr<PipelineHandler> handler = createInstance(manager);
> handler->name_ = name_.c_str();
> @@ -684,7 +681,7 @@ std::shared_ptr<PipelineHandler> PipelineHandlerFactory::create(CameraManager *m
> }
>
> /**
> - * \fn PipelineHandlerFactory::name()
> + * \fn PipelineHandlerFactoryBase::name()
> * \brief Retrieve the factory name
> * \return The factory name
> */
> @@ -696,9 +693,10 @@ std::shared_ptr<PipelineHandler> PipelineHandlerFactory::create(CameraManager *m
> * The caller is responsible to guarantee the uniqueness of the pipeline handler
> * name.
> */
> -void PipelineHandlerFactory::registerType(PipelineHandlerFactory *factory)
> +void PipelineHandlerFactoryBase::registerType(PipelineHandlerFactoryBase *factory)
> {
> - std::vector<PipelineHandlerFactory *> &factories = PipelineHandlerFactory::factories();
> + std::vector<PipelineHandlerFactoryBase *> &factories =
> + PipelineHandlerFactoryBase::factories();
>
> factories.push_back(factory);
> }
> @@ -707,26 +705,45 @@ void PipelineHandlerFactory::registerType(PipelineHandlerFactory *factory)
> * \brief Retrieve the list of all pipeline handler factories
> * \return the list of pipeline handler factories
> */
> -std::vector<PipelineHandlerFactory *> &PipelineHandlerFactory::factories()
> +std::vector<PipelineHandlerFactoryBase *> &PipelineHandlerFactoryBase::factories()
> {
> /*
> * The static factories map is defined inside the function to ensure
> * it gets initialized on first use, without any dependency on
> * link order.
> */
> - static std::vector<PipelineHandlerFactory *> factories;
> + static std::vector<PipelineHandlerFactoryBase *> factories;
> return factories;
> }
>
> +/**
> + * \class PipelineHandlerFactory
> + * \brief Registration of PipelineHandler classes and creation of instances
> + * \tparam _PipelineHandler The pipeline handler class type for this factory
> + *
> + * To facilitate discovery and instantiation of PipelineHandler classes, the
> + * PipelineHandlerFactory class implements auto-registration of pipeline
> + * handlers. Each PipelineHandler subclass shall register itself using the
> + * REGISTER_PIPELINE_HANDLER() macro, which will create a corresponding
> + * instance of a PipelineHandlerFactory and register it with the static list of
> + * factories.
> + */
> +
> +/**
> + * \fn PipelineHandlerFactory::PipelineHandlerFactory(const char *name)
> + * \brief Construct a pipeline handler factory
> + * \param[in] name Name of the pipeline handler class
> + *
> + * Creating an instance of the factory registers is with the global list ofs/is/it/
> + * factories, accessible through the factories() function.
> + *
> + * The factory \a name is used for debug purpose and shall be unique.
> + */
> +
> /**
> * \fn PipelineHandlerFactory::createInstance() const
> * \brief Create an instance of the PipelineHandler corresponding to the factory
> * \param[in] manager The camera manager
> - *
> - * This virtual function is implemented by the REGISTER_PIPELINE_HANDLER()
> - * macro. It creates a pipeline handler instance associated with the camera
> - * \a manager.
> - *
> * \return A unique pointer to a newly constructed instance of the
> * PipelineHandler subclass corresponding to the factory
> */
> diff --git a/test/ipa/ipa_interface_test.cpp b/test/ipa/ipa_interface_test.cpp
> index a629abc28da7..6b93e976a587 100644
> --- a/test/ipa/ipa_interface_test.cpp
> +++ b/test/ipa/ipa_interface_test.cpp
> @@ -52,9 +52,9 @@ protected:
> ipaManager_ = make_unique<IPAManager>();
>
> /* Create a pipeline handler for vimc. */
> - const std::vector<PipelineHandlerFactory *> &factories =
> - PipelineHandlerFactory::factories();
> - for (const PipelineHandlerFactory *factory : factories) {
> + const std::vector<PipelineHandlerFactoryBase *> &factories =
> + PipelineHandlerFactoryBase::factories();
> + for (const PipelineHandlerFactoryBase *factory : factories) {
> if (factory->name() == "PipelineHandlerVimc") {
> pipe_ = factory->create(nullptr);
> break;
With the typos fixed:
Reviewed-by: Xavier Roumegue <xavier.roumegue at oss.nxp.com>
More information about the libcamera-devel
mailing list