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:
parent
a29b7fc7d5
commit
5b02e03199
9 changed files with 44 additions and 31 deletions
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue