[libcamera-devel] [RFC 06/11] libcamera: pipeline_handler: Keep track of MediaDevice

Niklas Söderlund niklas.soderlund at ragnatech.se
Sun Apr 14 03:35:01 CEST 2019


Instead of requiring each pipeline handle implementation to keep track
of calling release() on its media devices upon deletion keep track of
them in the base class. Add a helper which pipeline handlers shall use
to acquire a media device instead of directly interacting with the
DeviceEnumerator.

Centrally keeping track of media devices will also be beneficial
implementing pipeline exclusive access across processes.

Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
---
 src/libcamera/include/pipeline_handler.h |  4 ++++
 src/libcamera/pipeline/ipu3/ipu3.cpp     | 20 ++------------------
 src/libcamera/pipeline/uvcvideo.cpp      | 24 +++++++-----------------
 src/libcamera/pipeline/vimc.cpp          | 22 ++++++----------------
 src/libcamera/pipeline_handler.cpp       | 22 ++++++++++++++++++++++
 5 files changed, 41 insertions(+), 51 deletions(-)

diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
index b6cbd3bae51b08dc..d995a7e56d90f706 100644
--- a/src/libcamera/include/pipeline_handler.h
+++ b/src/libcamera/include/pipeline_handler.h
@@ -21,6 +21,7 @@ class Camera;
 class CameraConfiguration;
 class CameraManager;
 class DeviceEnumerator;
+class DeviceMatch;
 class MediaDevice;
 class PipelineHandler;
 class Request;
@@ -52,6 +53,8 @@ public:
 	virtual ~PipelineHandler();
 
 	virtual bool match(DeviceEnumerator *enumerator) = 0;
+	std::shared_ptr<MediaDevice> tryAcquire(DeviceEnumerator *enumerator,
+						const DeviceMatch &dm);
 
 	virtual CameraConfiguration
 	streamConfiguration(Camera *camera, const std::vector<StreamUsage> &usages) = 0;
@@ -81,6 +84,7 @@ private:
 	void mediaDeviceDisconnected(MediaDevice *media);
 	virtual void disconnect();
 
+	std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
 	std::vector<std::weak_ptr<Camera>> cameras_;
 	std::map<const Camera *, std::unique_ptr<CameraData>> cameraData_;
 };
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index a87eff8dfec6d143..77d14533e6bceb80 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -137,7 +137,6 @@ class PipelineHandlerIPU3 : public PipelineHandler
 {
 public:
 	PipelineHandlerIPU3(CameraManager *manager);
-	~PipelineHandlerIPU3();
 
 	CameraConfiguration
 	streamConfiguration(Camera *camera,
@@ -195,15 +194,6 @@ PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager *manager)
 {
 }
 
-PipelineHandlerIPU3::~PipelineHandlerIPU3()
-{
-	if (cio2MediaDev_)
-		cio2MediaDev_->release();
-
-	if (imguMediaDev_)
-		imguMediaDev_->release();
-}
-
 CameraConfiguration
 PipelineHandlerIPU3::streamConfiguration(Camera *camera,
 					 const std::vector<StreamUsage> &usages)
@@ -451,20 +441,14 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
 	imgu_dm.add("ipu3-imgu 1 viewfinder");
 	imgu_dm.add("ipu3-imgu 1 3a stat");
 
-	cio2MediaDev_ = enumerator->search(cio2_dm);
+	cio2MediaDev_ = tryAcquire(enumerator, cio2_dm);
 	if (!cio2MediaDev_)
 		return false;
 
-	if (!cio2MediaDev_->acquire())
-		return false;
-
-	imguMediaDev_ = enumerator->search(imgu_dm);
+	imguMediaDev_ = tryAcquire(enumerator, imgu_dm);
 	if (!imguMediaDev_)
 		return false;
 
-	if (!imguMediaDev_->acquire())
-		return false;
-
 	/*
 	 * Disable all links that are enabled by default on CIO2, as camera
 	 * creation enables all valid links it finds.
diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
index 5214bfd3097b8217..43a6d59670299376 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -24,7 +24,6 @@ class PipelineHandlerUVC : public PipelineHandler
 {
 public:
 	PipelineHandlerUVC(CameraManager *manager);
-	~PipelineHandlerUVC();
 
 	CameraConfiguration
 	streamConfiguration(Camera *camera,
@@ -68,20 +67,13 @@ private:
 			PipelineHandler::cameraData(camera));
 	}
 
-	std::shared_ptr<MediaDevice> media_;
 };
 
 PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager)
-	: PipelineHandler(manager), media_(nullptr)
+	: PipelineHandler(manager)
 {
 }
 
-PipelineHandlerUVC::~PipelineHandlerUVC()
-{
-	if (media_)
-		media_->release();
-}
-
 CameraConfiguration
 PipelineHandlerUVC::streamConfiguration(Camera *camera,
 					const std::vector<StreamUsage> &usages)
@@ -178,19 +170,17 @@ int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request)
 
 bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 {
+	std::shared_ptr<MediaDevice> media;
 	DeviceMatch dm("uvcvideo");
 
-	media_ = enumerator->search(dm);
-	if (!media_)
-		return false;
-
-	if (!media_->acquire())
+	media = tryAcquire(enumerator, dm);
+	if (!media)
 		return false;
 
 	std::unique_ptr<UVCCameraData> data = utils::make_unique<UVCCameraData>(this);
 
 	/* Locate and open the default video node. */
-	for (MediaEntity *entity : media_->entities()) {
+	for (MediaEntity *entity : media->entities()) {
 		if (entity->flags() & MEDIA_ENT_FL_DEFAULT) {
 			data->video_ = new V4L2Device(entity);
 			break;
@@ -209,11 +199,11 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 
 	/* Create and register the camera. */
 	std::set<Stream *> streams{ &data->stream_ };
-	std::shared_ptr<Camera> camera = Camera::create(this, media_->model(), streams);
+	std::shared_ptr<Camera> camera = Camera::create(this, media->model(), streams);
 	registerCamera(std::move(camera), std::move(data));
 
 	/* Enable hot-unplug notifications. */
-	hotplugMediaDevice(media_.get());
+	hotplugMediaDevice(media.get());
 
 	return true;
 }
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index e5e78ccedd59ae66..a80331e1cd4d1e46 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -24,7 +24,6 @@ class PipelineHandlerVimc : public PipelineHandler
 {
 public:
 	PipelineHandlerVimc(CameraManager *manager);
-	~PipelineHandlerVimc();
 
 	CameraConfiguration
 	streamConfiguration(Camera *camera,
@@ -67,21 +66,13 @@ private:
 		return static_cast<VimcCameraData *>(
 			PipelineHandler::cameraData(camera));
 	}
-
-	std::shared_ptr<MediaDevice> media_;
 };
 
 PipelineHandlerVimc::PipelineHandlerVimc(CameraManager *manager)
-	: PipelineHandler(manager), media_(nullptr)
+	: PipelineHandler(manager)
 {
 }
 
-PipelineHandlerVimc::~PipelineHandlerVimc()
-{
-	if (media_)
-		media_->release();
-}
-
 CameraConfiguration
 PipelineHandlerVimc::streamConfiguration(Camera *camera,
 					 const std::vector<StreamUsage> &usages)
@@ -178,6 +169,8 @@ int PipelineHandlerVimc::queueRequest(Camera *camera, Request *request)
 
 bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator)
 {
+	std::shared_ptr<MediaDevice> media;
+
 	DeviceMatch dm("vimc");
 
 	dm.add("Raw Capture 0");
@@ -190,17 +183,14 @@ bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator)
 	dm.add("RGB/YUV Input");
 	dm.add("Scaler");
 
-	media_ = enumerator->search(dm);
-	if (!media_)
-		return false;
-
-	if (!media_->acquire())
+	media = tryAcquire(enumerator, dm);
+	if (!media)
 		return false;
 
 	std::unique_ptr<VimcCameraData> data = utils::make_unique<VimcCameraData>(this);
 
 	/* Locate and open the capture video node. */
-	data->video_ = new V4L2Device(media_->getEntityByName("Raw Capture 1"));
+	data->video_ = new V4L2Device(media->getEntityByName("Raw Capture 1"));
 	if (data->video_->open())
 		return false;
 
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 43550c0e0210b7b3..7f4035c008f95f91 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -9,6 +9,7 @@
 #include <libcamera/camera.h>
 #include <libcamera/camera_manager.h>
 
+#include "device_enumerator.h"
 #include "log.h"
 #include "media_device.h"
 #include "pipeline_handler.h"
@@ -115,6 +116,8 @@ PipelineHandler::PipelineHandler(CameraManager *manager)
 
 PipelineHandler::~PipelineHandler()
 {
+	for (std::shared_ptr<MediaDevice> media : mediaDevices_)
+		media->release();
 };
 
 /**
@@ -148,6 +151,25 @@ PipelineHandler::~PipelineHandler()
  * created, or false otherwise
  */
 
+std::shared_ptr<MediaDevice>
+PipelineHandler::tryAcquire(DeviceEnumerator *enumerator, const DeviceMatch &dm)
+{
+	std::shared_ptr<MediaDevice> media;
+
+	media = enumerator->search(dm);
+	if (!media)
+		goto out;
+
+	if (!media->acquire()) {
+		media.reset();
+		goto out;
+	}
+
+	mediaDevices_.push_back(media);
+out:
+	return media;
+}
+
 /**
  * \fn PipelineHandler::streamConfiguration()
  * \brief Retrieve a group of stream configurations for a specified camera
-- 
2.21.0



More information about the libcamera-devel mailing list