[libcamera-devel] [PATCH v2 04/10] libcamera: ipa_module: allow instantiation of IPAInterface

Paul Elder paul.elder at ideasonboard.com
Tue Jun 4 22:45:00 CEST 2019


Hi Laurent,

On Tue, Jun 04, 2019 at 01:49:06PM +0300, Laurent Pinchart wrote:
> Hi Paul,
> 
> Thank you for the patch.

Thank you for the review.

> On Mon, Jun 03, 2019 at 07:16:31PM -0400, Paul Elder wrote:
> > Add functions for loading the IPAInterface factory function from an IPA
> > module shared object, and for creating an instance of an IPAInterface.
> > These functions will be used by IPAManager, from which a PipelineHandler
> > will request an IPAInterface.
> > 
> > Also update meson to add the "-ldl" linker argument, to allow loading of
> > the factory function from a shared object.
> > 
> > Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> > ---
> > Changes in v2:
> > - mostly just documentation
> > 
> >  src/libcamera/include/ipa_module.h | 12 +++++
> >  src/libcamera/ipa_module.cpp       | 83 ++++++++++++++++++++++++++++--
> >  src/libcamera/meson.build          |  3 +-
> >  3 files changed, 94 insertions(+), 4 deletions(-)
> > 
> > diff --git a/src/libcamera/include/ipa_module.h b/src/libcamera/include/ipa_module.h
> > index a4c6dbd..557435c 100644
> > --- a/src/libcamera/include/ipa_module.h
> > +++ b/src/libcamera/include/ipa_module.h
> > @@ -7,8 +7,10 @@
> >  #ifndef __LIBCAMERA_IPA_MODULE_H__
> >  #define __LIBCAMERA_IPA_MODULE_H__
> >  
> > +#include <memory>
> >  #include <string>
> >  
> > +#include <libcamera/ipa/ipa_interface.h>
> >  #include <libcamera/ipa/ipa_module_info.h>
> >  
> >  namespace libcamera {
> > @@ -17,16 +19,26 @@ class IPAModule
> >  {
> >  public:
> >  	explicit IPAModule(const std::string &libPath);
> > +	~IPAModule();
> >  
> >  	bool isValid() const;
> >  
> >  	const struct IPAModuleInfo &info() const;
> >  
> > +	bool load();
> > +
> > +	std::unique_ptr<IPAInterface> createInstance();
> > +
> >  private:
> >  	struct IPAModuleInfo info_;
> >  
> >  	std::string libPath_;
> >  	bool valid_;
> > +	bool loaded_;
> > +
> > +	void *dlHandle_;
> > +	typedef IPAInterface *(*ipaIntfFactory)(void);
> 
> This is a type so it should start with an uppercase letter. Furthermore,

Ah, right.

> as the type name is defined in the context of the IPAModule class, it
> doesn't have to start with IPA. How about just FactoryFunction ?

No, I'd prefer to have IPAIntfFactory. That way it's really clear what
the factory function is meant to produce. IntfFactory becomes kind of
vague too.

> > +	ipaIntfFactory ipaCreate_;
> >  
> >  	int loadIPAModuleInfo();
> >  };
> > diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp
> > index 067f868..91d97ae 100644
> > --- a/src/libcamera/ipa_module.cpp
> > +++ b/src/libcamera/ipa_module.cpp
> > @@ -7,6 +7,7 @@
> >  
> >  #include "ipa_module.h"
> >  
> > +#include <dlfcn.h>
> >  #include <elf.h>
> >  #include <errno.h>
> >  #include <fcntl.h>
> > @@ -257,13 +258,12 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
> >   * The IPA module shared object file must be of the same endianness and
> >   * bitness as libcamera.
> >   *
> > - * \todo load funtions from the IPA to be used by pipelines
> > - *
> >   * The caller shall call the isValid() method after constructing an
> >   * IPAModule instance to verify the validity of the IPAModule.
> >   */
> >  IPAModule::IPAModule(const std::string &libPath)
> > -	: libPath_(libPath), valid_(false)
> > +	: libPath_(libPath), valid_(false), loaded_(false),
> > +	  dlHandle_(nullptr), ipaCreate_(nullptr)
> >  {
> >  	if (loadIPAModuleInfo() < 0)
> >  		return;
> > @@ -271,6 +271,12 @@ IPAModule::IPAModule(const std::string &libPath)
> >  	valid_ = true;
> >  }
> >  
> > +IPAModule::~IPAModule()
> > +{
> > +	if (dlHandle_)
> > +		dlclose(dlHandle_);
> > +}
> > +
> >  int IPAModule::loadIPAModuleInfo()
> >  {
> >  	int fd = open(libPath_.c_str(), O_RDONLY);
> > @@ -340,4 +346,75 @@ const struct IPAModuleInfo &IPAModule::info() const
> >  	return info_;
> >  }
> >  
> > +/**
> > + * \brief Load the IPA implementation factory from the shared object
> > + *
> > + * The IPA module shared object implements an IPAInterface class to be used
> > + * by pipeline handlers. This function loads the factory function from the
> 
> s/This function/This method/
> 
> ("factory function" is correct as it's a pure C function)
> 
> > + * shared object. Later, createInstance() can be called to instantiate the
> > + * IPAInterface.
> > + *
> > + * This method only needs to be called successfully once, after which
> > + * createInstance can be called as many times as IPAInterface instances are
> 
> createInstance()
> 
> > + * needed.
> > + *
> > + * Calling this function on an invalid module (as returned by isValid()) is
> > + * an error.
> > + *
> > + * \return true if load was successful, or already loaded, and false otherwise
> 
> s/true/True/
> 
> > + */
> > +bool IPAModule::load()
> > +{
> > +	if (!valid_)
> > +		return false;
> > +
> > +	if (loaded_)
> > +		return true;
> > +
> > +	dlHandle_ = dlopen(libPath_.c_str(), RTLD_LAZY);
> > +	if (!dlHandle_) {
> > +		LOG(IPAModule, Error)
> > +			<< "Failed to open IPA module shared object "
> 
> s/object/object:/
> 
> > +			<< dlerror();
> > +		return false;
> > +	}
> > +
> > +	void *symbol = dlsym(dlHandle_, "ipaCreate");
> > +	if (!symbol) {
> > +		LOG(IPAModule, Error)
> > +			<< "Failed to load ipaCreate() from IPA module shared object "
> 
> s/object/object:/
> 
> > +			<< dlerror();
> > +		dlclose(dlHandle_);
> > +		dlHandle_ = nullptr;
> > +		return false;
> > +	}
> > +
> > +	ipaCreate_ = (ipaIntfFactory)symbol;
> 
> Let's use C++-style casts.
> 
> 	ipaCreate_ = reinterpret_cast<ipaIntfFactory>(symbol);
> 
> > +
> > +	loaded_ = true;
> > +
> > +	return true;
> > +}
> > +
> > +/**
> > + * \brief Instantiate an IPAInterface
> > + *
> > + * After loading the IPA module with load(), this method creates an
> > + * instance of the IPA module interface.
> > + *
> > + * Calling this function on a module that has not yet been loaded, or an
> > + * invalid module (as returned by load() and isValid(), respectively) is
> > + * an error.
> > + *
> > + * \return the IPA implementation as a new IPAInterface instance on success,
> 
> s/the/The/
> 
> With those small issues fixed,
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> 
> > + * or nullptr on error
> > + */
> > +std::unique_ptr<IPAInterface> IPAModule::createInstance()
> > +{
> > +	if (!valid_ || !loaded_)
> > +		return nullptr;
> > +
> > +	return std::unique_ptr<IPAInterface>(ipaCreate_());
> > +}
> > +
> >  } /* namespace libcamera */
> > diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> > index 07335e5..32f7da4 100644
> > --- a/src/libcamera/meson.build
> > +++ b/src/libcamera/meson.build
> > @@ -65,7 +65,8 @@ libcamera = shared_library('camera',
> >                             libcamera_sources,
> >                             install : true,
> >                             include_directories : includes,
> > -                           dependencies : libudev)
> > +                           dependencies : libudev,
> > +                           link_args : '-ldl')
> >  
> >  libcamera_dep = declare_dependency(sources : [libcamera_api, libcamera_h],
> >                                     include_directories : libcamera_includes,
> 

Thanks,

Paul


More information about the libcamera-devel mailing list