libcamera: pipeline_handler: Add camera disconnection support
Pipeline handlers are responsible for creating camera instances, but also for destroying them when devices are unplugged. As camera objects are reference-counted this isn't a straightforward operation and involves the camera manager and camera object itself. Add two helper methods in the PipelineHandler base class to register a camera and to register a media device with the pipeline handler. When registering a camera, the registerCamera() helper method will add it to the camera manager. When registering a media device, the registerMediaDevice() helper method will listen to device disconnection events, and disconnect all cameras created by the pipeline handler as a response. Under the hood the PipelineHandler class needs to keep track of registered cameras in order to handle disconnection. They can't be stored as shared pointers as this would create a circular dependency (the Camera class owns a shared pointer to the pipeline handler). Store them as weak pointers instead. This is safe as a reference to the camera is stored in the camera manager, and doesn't get removed until the camera is unregistered from the manager by the PipelineHandler. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
8897260976
commit
607a9d7f56
5 changed files with 84 additions and 6 deletions
|
@ -16,6 +16,7 @@ namespace libcamera {
|
||||||
|
|
||||||
class CameraManager;
|
class CameraManager;
|
||||||
class DeviceEnumerator;
|
class DeviceEnumerator;
|
||||||
|
class MediaDevice;
|
||||||
|
|
||||||
class PipelineHandler : public std::enable_shared_from_this<PipelineHandler>
|
class PipelineHandler : public std::enable_shared_from_this<PipelineHandler>
|
||||||
{
|
{
|
||||||
|
@ -27,6 +28,15 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CameraManager *manager_;
|
CameraManager *manager_;
|
||||||
|
|
||||||
|
void registerCamera(std::shared_ptr<Camera> camera);
|
||||||
|
void hotplugMediaDevice(MediaDevice *media);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void disconnect();
|
||||||
|
void mediaDeviceDisconnected(MediaDevice *media);
|
||||||
|
|
||||||
|
std::vector<std::weak_ptr<Camera>> cameras_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineHandlerFactory
|
class PipelineHandlerFactory
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
#include <libcamera/camera_manager.h>
|
|
||||||
|
|
||||||
#include "device_enumerator.h"
|
#include "device_enumerator.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -169,7 +168,7 @@ void PipelineHandlerIPU3::registerCameras()
|
||||||
|
|
||||||
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(this, cameraName);
|
std::shared_ptr<Camera> camera = Camera::create(this, cameraName);
|
||||||
manager_->addCamera(std::move(camera));
|
registerCamera(std::move(camera));
|
||||||
|
|
||||||
LOG(IPU3, Info)
|
LOG(IPU3, Info)
|
||||||
<< "Registered Camera[" << numCameras << "] \""
|
<< "Registered Camera[" << numCameras << "] \""
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
#include <libcamera/camera_manager.h>
|
|
||||||
|
|
||||||
#include "device_enumerator.h"
|
#include "device_enumerator.h"
|
||||||
#include "media_device.h"
|
#include "media_device.h"
|
||||||
|
@ -49,7 +48,7 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
|
||||||
dev_->acquire();
|
dev_->acquire();
|
||||||
|
|
||||||
std::shared_ptr<Camera> camera = Camera::create(this, dev_->model());
|
std::shared_ptr<Camera> camera = Camera::create(this, dev_->model());
|
||||||
manager_->addCamera(std::move(camera));
|
registerCamera(std::move(camera));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
#include <libcamera/camera_manager.h>
|
|
||||||
|
|
||||||
#include "device_enumerator.h"
|
#include "device_enumerator.h"
|
||||||
#include "media_device.h"
|
#include "media_device.h"
|
||||||
|
@ -58,7 +57,7 @@ bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)
|
||||||
dev_->acquire();
|
dev_->acquire();
|
||||||
|
|
||||||
std::shared_ptr<Camera> camera = Camera::create(this, "Dummy VIMC Camera");
|
std::shared_ptr<Camera> camera = Camera::create(this, "Dummy VIMC Camera");
|
||||||
manager_->addCamera(std::move(camera));
|
registerCamera(std::move(camera));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,11 @@
|
||||||
* pipeline_handler.cpp - Pipeline handler infrastructure
|
* pipeline_handler.cpp - Pipeline handler infrastructure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libcamera/camera.h>
|
||||||
|
#include <libcamera/camera_manager.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "media_device.h"
|
||||||
#include "pipeline_handler.h"
|
#include "pipeline_handler.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,6 +101,73 @@ PipelineHandler::~PipelineHandler()
|
||||||
* constant for the whole lifetime of the pipeline handler.
|
* constant for the whole lifetime of the pipeline handler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Register a camera to the camera manager and pipeline handler
|
||||||
|
* \param[in] camera The camera to be added
|
||||||
|
*
|
||||||
|
* This function is called by pipeline handlers to register the cameras they
|
||||||
|
* handle with the camera manager.
|
||||||
|
*/
|
||||||
|
void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
|
||||||
|
{
|
||||||
|
cameras_.push_back(camera);
|
||||||
|
manager_->addCamera(std::move(camera));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enable hotplug handling for a media device
|
||||||
|
* \param[in] media The media device
|
||||||
|
*
|
||||||
|
* This function enables hotplug handling, and especially hot-unplug handling,
|
||||||
|
* of the \a media device. It shall be called by pipeline handlers for all the
|
||||||
|
* media devices that can be disconnected.
|
||||||
|
*
|
||||||
|
* When a media device passed to this function is later unplugged, the pipeline
|
||||||
|
* handler gets notified and automatically disconnects all the cameras it has
|
||||||
|
* registered without requiring any manual intervention.
|
||||||
|
*/
|
||||||
|
void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
|
||||||
|
{
|
||||||
|
media->disconnected.connect(this, &PipelineHandler::mediaDeviceDisconnected);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Device disconnection handler
|
||||||
|
*
|
||||||
|
* This virtual function is called to notify the pipeline handler that the
|
||||||
|
* device it handles has been disconnected. It notifies all cameras created by
|
||||||
|
* the pipeline handler that they have been disconnected, and unregisters them
|
||||||
|
* from the camera manager.
|
||||||
|
*
|
||||||
|
* The function can be overloaded by pipeline handlers to perform custom
|
||||||
|
* operations at disconnection time. Any overloaded version shall call the
|
||||||
|
* PipelineHandler::disconnect() base function for proper hot-unplug operation.
|
||||||
|
*/
|
||||||
|
void PipelineHandler::disconnect()
|
||||||
|
{
|
||||||
|
for (std::weak_ptr<Camera> ptr : cameras_) {
|
||||||
|
std::shared_ptr<Camera> camera = ptr.lock();
|
||||||
|
if (!camera)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
camera->disconnect();
|
||||||
|
manager_->removeCamera(camera.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
cameras_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Slot for the MediaDevice disconnected signal
|
||||||
|
*/
|
||||||
|
void PipelineHandler::mediaDeviceDisconnected(MediaDevice *media)
|
||||||
|
{
|
||||||
|
if (cameras_.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class PipelineHandlerFactory
|
* \class PipelineHandlerFactory
|
||||||
* \brief Registration of PipelineHandler classes and creation of instances
|
* \brief Registration of PipelineHandler classes and creation of instances
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue