libcamera: pipeline_handler: Implement factories through class templates

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@ideasonboard.com>
Reviewed-by: Xavier Roumegue <xavier.roumegue@oss.nxp.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Laurent Pinchart 2022-10-03 22:55:11 +03:00
parent ba3a1adc13
commit 0bc9286eb9
4 changed files with 71 additions and 50 deletions

View file

@ -95,23 +95,23 @@ private:
Mutex lock_; Mutex lock_;
unsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_); unsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_);
friend class PipelineHandlerFactory; friend class PipelineHandlerFactoryBase;
}; };
class PipelineHandlerFactory class PipelineHandlerFactoryBase
{ {
public: public:
PipelineHandlerFactory(const char *name); PipelineHandlerFactoryBase(const char *name);
virtual ~PipelineHandlerFactory() = default; virtual ~PipelineHandlerFactoryBase() = default;
std::shared_ptr<PipelineHandler> create(CameraManager *manager) const; std::shared_ptr<PipelineHandler> create(CameraManager *manager) const;
const std::string &name() const { return name_; } const std::string &name() const { return name_; }
static std::vector<PipelineHandlerFactory *> &factories(); static std::vector<PipelineHandlerFactoryBase *> &factories();
private: private:
static void registerType(PipelineHandlerFactory *factory); static void registerType(PipelineHandlerFactoryBase *factory);
virtual std::unique_ptr<PipelineHandler> virtual std::unique_ptr<PipelineHandler>
createInstance(CameraManager *manager) const = 0; createInstance(CameraManager *manager) const = 0;
@ -119,19 +119,23 @@ private:
std::string name_; std::string name_;
}; };
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) \ #define REGISTER_PIPELINE_HANDLER(handler) \
class handler##Factory final : public PipelineHandlerFactory \ static PipelineHandlerFactory<handler> global_##handler##Factory(#handler);
{ \
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;
} /* namespace libcamera */ } /* namespace libcamera */

View file

@ -142,10 +142,10 @@ void CameraManager::Private::createPipelineHandlers()
* file and only fallback on all handlers if there is no * file and only fallback on all handlers if there is no
* configuration file. * configuration file.
*/ */
const std::vector<PipelineHandlerFactory *> &factories = const std::vector<PipelineHandlerFactoryBase *> &factories =
PipelineHandlerFactory::factories(); PipelineHandlerFactoryBase::factories();
for (const PipelineHandlerFactory *factory : factories) { for (const PipelineHandlerFactoryBase *factory : factories) {
LOG(Camera, Debug) LOG(Camera, Debug)
<< "Found registered pipeline handler '" << "Found registered pipeline handler '"
<< factory->name() << "'"; << factory->name() << "'";

View file

@ -64,8 +64,7 @@ LOG_DEFINE_CATEGORY(Pipeline)
* *
* In order to honour the std::enable_shared_from_this<> contract, * In order to honour the std::enable_shared_from_this<> contract,
* PipelineHandler instances shall never be constructed manually, but always * PipelineHandler instances shall never be constructed manually, but always
* through the PipelineHandlerFactory::create() function implemented by the * through the PipelineHandlerFactoryBase::create() function.
* respective factories.
*/ */
PipelineHandler::PipelineHandler(CameraManager *manager) PipelineHandler::PipelineHandler(CameraManager *manager)
: manager_(manager), useCount_(0) : manager_(manager), useCount_(0)
@ -643,27 +642,25 @@ void PipelineHandler::disconnect()
*/ */
/** /**
* \class PipelineHandlerFactory * \class PipelineHandlerFactoryBase
* \brief Registration of PipelineHandler classes and creation of instances * \brief Base class for pipeline handler factories
* *
* To facilitate discovery and instantiation of PipelineHandler classes, the * The PipelineHandlerFactoryBase class is the base of all specializations of
* PipelineHandlerFactory class maintains a registry of pipeline handler * the PipelineHandlerFactory class template. It implements the factory
* classes. Each PipelineHandler subclass shall register itself using the * registration, maintains a registry of factories, and provides access to the
* REGISTER_PIPELINE_HANDLER() macro, which will create a corresponding * registered factories.
* instance of a PipelineHandlerFactory subclass and register it with the
* static list of factories.
*/ */
/** /**
* \brief Construct a pipeline handler factory * \brief Construct a pipeline handler factory base
* \param[in] name Name of the pipeline handler class * \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 it with the global list of
* factories, accessible through the factories() function. * factories, accessible through the factories() function.
* *
* The factory \a name is used for debug purpose and shall be unique. * 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) : name_(name)
{ {
registerType(this); registerType(this);
@ -676,7 +673,7 @@ PipelineHandlerFactory::PipelineHandlerFactory(const char *name)
* \return A shared pointer to a new instance of the PipelineHandler subclass * \return A shared pointer to a new instance of the PipelineHandler subclass
* corresponding to the factory * 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); std::unique_ptr<PipelineHandler> handler = createInstance(manager);
handler->name_ = name_.c_str(); 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 * \brief Retrieve the factory name
* \return 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 * The caller is responsible to guarantee the uniqueness of the pipeline handler
* name. * 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); factories.push_back(factory);
} }
@ -707,26 +705,45 @@ void PipelineHandlerFactory::registerType(PipelineHandlerFactory *factory)
* \brief Retrieve the list of all pipeline handler factories * \brief Retrieve the list of all pipeline handler factories
* \return the list of 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 * The static factories map is defined inside the function to ensure
* it gets initialized on first use, without any dependency on * it gets initialized on first use, without any dependency on
* link order. * link order.
*/ */
static std::vector<PipelineHandlerFactory *> factories; static std::vector<PipelineHandlerFactoryBase *> factories;
return 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 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.
*/
/** /**
* \fn PipelineHandlerFactory::createInstance() const * \fn PipelineHandlerFactory::createInstance() const
* \brief Create an instance of the PipelineHandler corresponding to the factory * \brief Create an instance of the PipelineHandler corresponding to the factory
* \param[in] manager The camera manager * \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 * \return A unique pointer to a newly constructed instance of the
* PipelineHandler subclass corresponding to the factory * PipelineHandler subclass corresponding to the factory
*/ */

View file

@ -52,9 +52,9 @@ protected:
ipaManager_ = make_unique<IPAManager>(); ipaManager_ = make_unique<IPAManager>();
/* Create a pipeline handler for vimc. */ /* Create a pipeline handler for vimc. */
const std::vector<PipelineHandlerFactory *> &factories = const std::vector<PipelineHandlerFactoryBase *> &factories =
PipelineHandlerFactory::factories(); PipelineHandlerFactoryBase::factories();
for (const PipelineHandlerFactory *factory : factories) { for (const PipelineHandlerFactoryBase *factory : factories) {
if (factory->name() == "PipelineHandlerVimc") { if (factory->name() == "PipelineHandlerVimc") {
pipe_ = factory->create(nullptr); pipe_ = factory->create(nullptr);
break; break;