libcamera: camera: Associate cameras with their pipeline handler

The PipelineHandler which creates a Camera is responsible for serving
any operation requested by the user. In order forward the public API
calls, the camera needs to store a reference to its pipeline handler.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Create pipeline handlers is shared pointers, make them inherit from
  std::enable_shared_from_this<> and stored them in shared pointers.
This commit is contained in:
Niklas Söderlund 2019-01-22 16:31:39 +01:00 committed by Laurent Pinchart
parent a29b7fc7d5
commit 5b02e03199
9 changed files with 44 additions and 31 deletions

View file

@ -12,10 +12,13 @@
namespace libcamera { namespace libcamera {
class PipelineHandler;
class Camera final class Camera final
{ {
public: public:
static std::shared_ptr<Camera> create(const std::string &name); static std::shared_ptr<Camera> create(PipelineHandler *pipe,
const std::string &name);
Camera(const Camera &) = delete; Camera(const Camera &) = delete;
void operator=(const Camera &) = delete; void operator=(const Camera &) = delete;
@ -23,9 +26,10 @@ public:
const std::string &name() const; const std::string &name() const;
private: private:
explicit Camera(const std::string &name); Camera(PipelineHandler *pipe, const std::string &name);
~Camera(); ~Camera();
std::shared_ptr<PipelineHandler> pipe_;
std::string name_; std::string name_;
}; };

View file

@ -41,7 +41,7 @@ private:
~CameraManager(); ~CameraManager();
std::unique_ptr<DeviceEnumerator> enumerator_; std::unique_ptr<DeviceEnumerator> enumerator_;
std::vector<PipelineHandler *> pipes_; std::vector<std::shared_ptr<PipelineHandler>> pipes_;
std::vector<std::shared_ptr<Camera>> cameras_; std::vector<std::shared_ptr<Camera>> cameras_;
std::unique_ptr<EventDispatcher> dispatcher_; std::unique_ptr<EventDispatcher> dispatcher_;

View file

@ -8,6 +8,7 @@
#include <libcamera/camera.h> #include <libcamera/camera.h>
#include "log.h" #include "log.h"
#include "pipeline_handler.h"
/** /**
* \file camera.h * \file camera.h
@ -52,17 +53,20 @@ namespace libcamera {
/** /**
* \brief Create a camera instance * \brief Create a camera instance
* \param[in] name The name of the camera device * \param[in] name The name of the camera device
* \param[in] pipe The pipeline handler responsible for the camera device
* *
* The caller is responsible for guaranteeing unicity of the camera name. * The caller is responsible for guaranteeing unicity of the camera name.
* *
* \return A shared pointer to the newly created camera object * \return A shared pointer to the newly created camera object
*/ */
std::shared_ptr<Camera> Camera::create(const std::string &name) std::shared_ptr<Camera> Camera::create(PipelineHandler *pipe,
const std::string &name)
{ {
struct Allocator : std::allocator<Camera> { struct Allocator : std::allocator<Camera> {
void construct(void *p, const std::string &name) void construct(void *p, PipelineHandler *pipe,
const std::string &name)
{ {
::new(p) Camera(name); ::new(p) Camera(pipe, name);
} }
void destroy(Camera *p) void destroy(Camera *p)
{ {
@ -70,7 +74,7 @@ std::shared_ptr<Camera> Camera::create(const std::string &name)
} }
}; };
return std::allocate_shared<Camera>(Allocator(), name); return std::allocate_shared<Camera>(Allocator(), pipe, name);
} }
/** /**
@ -83,8 +87,8 @@ const std::string &Camera::name() const
return name_; return name_;
} }
Camera::Camera(const std::string &name) Camera::Camera(PipelineHandler *pipe, const std::string &name)
: name_(name) : pipe_(pipe->shared_from_this()), name_(name)
{ {
} }

View file

@ -98,16 +98,14 @@ int CameraManager::start()
* all pipelines it can provide. * all pipelines it can provide.
*/ */
while (1) { while (1) {
PipelineHandler *pipe = factory->create(this); std::shared_ptr<PipelineHandler> pipe = factory->create(this);
if (!pipe->match(enumerator_.get())) { if (!pipe->match(enumerator_.get()))
delete pipe;
break; break;
}
LOG(Camera, Debug) LOG(Camera, Debug)
<< "Pipeline handler \"" << factory->name() << "Pipeline handler \"" << factory->name()
<< "\" matched"; << "\" matched";
pipes_.push_back(pipe); pipes_.push_back(std::move(pipe));
} }
} }
@ -130,10 +128,13 @@ void CameraManager::stop()
{ {
/* TODO: unregister hot-plug callback here */ /* TODO: unregister hot-plug callback here */
for (PipelineHandler *pipe : pipes_) /*
delete pipe; * Release all references to cameras and pipeline handlers to ensure
* they all get destroyed before the device enumerator deletes the
* media devices.
*/
pipes_.clear(); pipes_.clear();
cameras_.clear();
enumerator_.reset(nullptr); enumerator_.reset(nullptr);
} }

View file

@ -8,6 +8,7 @@
#define __LIBCAMERA_PIPELINE_HANDLER_H__ #define __LIBCAMERA_PIPELINE_HANDLER_H__
#include <map> #include <map>
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -16,7 +17,7 @@ namespace libcamera {
class CameraManager; class CameraManager;
class DeviceEnumerator; class DeviceEnumerator;
class PipelineHandler class PipelineHandler : public std::enable_shared_from_this<PipelineHandler>
{ {
public: public:
PipelineHandler(CameraManager *manager); PipelineHandler(CameraManager *manager);
@ -34,7 +35,7 @@ public:
PipelineHandlerFactory(const char *name); PipelineHandlerFactory(const char *name);
virtual ~PipelineHandlerFactory() { }; virtual ~PipelineHandlerFactory() { };
virtual PipelineHandler *create(CameraManager *manager) = 0; virtual std::shared_ptr<PipelineHandler> create(CameraManager *manager) = 0;
const std::string &name() const { return name_; } const std::string &name() const { return name_; }
@ -50,9 +51,9 @@ class handler##Factory final : public PipelineHandlerFactory \
{ \ { \
public: \ public: \
handler##Factory() : PipelineHandlerFactory(#handler) {} \ handler##Factory() : PipelineHandlerFactory(#handler) {} \
PipelineHandler *create(CameraManager *manager) \ std::shared_ptr<PipelineHandler> create(CameraManager *manager) \
{ \ { \
return new handler(manager); \ return std::make_shared<handler>(manager); \
} \ } \
}; \ }; \
static handler##Factory global_##handler##Factory; static handler##Factory global_##handler##Factory;

View file

@ -171,7 +171,7 @@ void PipelineHandlerIPU3::registerCameras()
continue; continue;
std::string cameraName = sensor->name() + " " + std::to_string(id); std::string cameraName = sensor->name() + " " + std::to_string(id);
std::shared_ptr<Camera> camera = Camera::create(cameraName); std::shared_ptr<Camera> camera = Camera::create(this, cameraName);
manager_->addCamera(std::move(camera)); manager_->addCamera(std::move(camera));
LOG(IPU3, Info) LOG(IPU3, Info)

View file

@ -48,7 +48,7 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
dev_->acquire(); dev_->acquire();
std::shared_ptr<Camera> camera = Camera::create(dev_->model()); std::shared_ptr<Camera> camera = Camera::create(this, dev_->model());
manager_->addCamera(std::move(camera)); manager_->addCamera(std::move(camera));
return true; return true;

View file

@ -57,14 +57,7 @@ bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)
dev_->acquire(); dev_->acquire();
/* std::shared_ptr<Camera> camera = Camera::create(this, "Dummy VIMC Camera");
* NOTE: A more complete Camera implementation could
* be passed the MediaDevice(s) it controls here or
* a reference to the PipelineHandler. Which method
* will be chosen depends on how the Camera
* object is modeled.
*/
std::shared_ptr<Camera> camera = Camera::create("Dummy VIMC Camera");
manager_->addCamera(std::move(camera)); manager_->addCamera(std::move(camera));
return true; return true;

View file

@ -32,11 +32,21 @@ LOG_DEFINE_CATEGORY(Pipeline)
* *
* The PipelineHandler matches the media devices provided by a DeviceEnumerator * The PipelineHandler matches the media devices provided by a DeviceEnumerator
* with the pipelines it supports and creates corresponding Camera devices. * with the pipelines it supports and creates corresponding Camera devices.
*
* Pipeline handler instances are reference-counted through std::shared_ptr<>.
* They implement std::enable_shared_from_this<> in order to create new
* std::shared_ptr<> in code paths originating from member functions of the
* PipelineHandler class where only the 'this' pointer is available.
*/ */
/** /**
* \brief Construct a PipelineHandler instance * \brief Construct a PipelineHandler instance
* \param[in] manager The camera manager * \param[in] manager The camera manager
*
* In order to honour the std::enable_shared_from_this<> contract,
* PipelineHandler instances shall never be constructed manually, but always
* through the PipelineHandlerFactory::create() method implemented by the
* respective factories.
*/ */
PipelineHandler::PipelineHandler(CameraManager *manager) PipelineHandler::PipelineHandler(CameraManager *manager)
: manager_(manager) : manager_(manager)