[libcamera-devel] [PATCH 06/10] libcamera: pipeline: simple: Open all video devices at match() time

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Aug 6 00:24:32 CEST 2021


Move opening of video devices at match() time, the same way as subdevs
are opened, to make the handling of V4L2 video devices and subdevices
more consistent.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 src/libcamera/pipeline/simple/simple.cpp | 67 ++++++++++++------------
 1 file changed, 33 insertions(+), 34 deletions(-)

diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index 6b808bfbe6fa..17ef3f43ad41 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -82,14 +82,12 @@ LOG_DEFINE_CATEGORY(SimplePipeline)
  * handled by this heuristic.
  *
  * Once the camera data instances have been created, the match() function
- * creates a V4L2Subdevice instance for each entity used by any of the cameras
- * and stores the instances in SimplePipelineHandler::subdevs_, accessible by
- * the SimpleCameraData class through the SimplePipelineHandler::subdev()
- * function. This avoids duplication of subdev instances between different
- * cameras when the same entity is used in multiple paths. A similar mechanism
- * is used for V4L2VideoDevice instances, but instances are in this case created
- * on demand when accessed through SimplePipelineHandler::video() instead of all
- * in one go at initialization time.
+ * creates a V4L2VideoDevice or V4L2Subdevice instance for each entity used by
+ * any of the cameras and stores them in SimplePipelineHandler::entities_,
+ * accessible by the SimpleCameraData class through the
+ * SimplePipelineHandler::subdev() and SimplePipelineHandler::video() functions.
+ * This avoids duplication of subdev instances between different cameras when
+ * the same entity is used in multiple paths.
  *
  * Finally, all camera data instances are initialized to gather information
  * about the possible pipeline configurations for the corresponding camera. If
@@ -397,10 +395,7 @@ int SimpleCameraData::init()
 	int ret;
 
 	video_ = pipe->video(entities_.back().entity);
-	if (!video_) {
-		LOG(SimplePipeline, Error) << "Failed to open video device";
-		return -ENODEV;
-	}
+	ASSERT(video_);
 
 	/*
 	 * Setup links first as some subdev drivers take active links into
@@ -1069,24 +1064,44 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 
 	/*
 	 * Insert all entities in the global entities list. Create and open
-	 * V4L2Subdevice instances for each entity corresponding to a V4L2
-	 * subdevice.
+	 * V4L2VideoDevice and V4L2Subdevice instances for the corresponding
+	 * entities.
 	 */
 	for (MediaEntity *entity : entities) {
+		std::unique_ptr<V4L2VideoDevice> video;
 		std::unique_ptr<V4L2Subdevice> subdev;
+		int ret;
 
-		if (entity->type() == MediaEntity::Type::V4L2Subdevice) {
+		switch (entity->type()) {
+		case MediaEntity::Type::V4L2VideoDevice:
+			video = std::make_unique<V4L2VideoDevice>(entity);
+			ret = video->open();
+			if (ret < 0) {
+				LOG(SimplePipeline, Error)
+					<< "Failed to open " << video->deviceNode()
+					<< ": " << strerror(-ret);
+				return false;
+			}
+
+			video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady);
+			break;
+
+		case MediaEntity::Type::V4L2Subdevice:
 			subdev = std::make_unique<V4L2Subdevice>(entity);
-			int ret = subdev->open();
+			ret = subdev->open();
 			if (ret < 0) {
 				LOG(SimplePipeline, Error)
 					<< "Failed to open " << subdev->deviceNode()
 					<< ": " << strerror(-ret);
 				return false;
 			}
+			break;
+
+		default:
+			break;
 		}
 
-		entities_[entity] = { nullptr, std::move(subdev) };
+		entities_[entity] = { std::move(video), std::move(subdev) };
 	}
 
 	/* Initialize each pipeline and register a corresponding camera. */
@@ -1113,27 +1128,11 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 
 V4L2VideoDevice *SimplePipelineHandler::video(const MediaEntity *entity)
 {
-	/*
-	 * Return the V4L2VideoDevice corresponding to the media entity, either
-	 * as a previously constructed device if available from the cache, or
-	 * by constructing a new one.
-	 */
-
 	auto iter = entities_.find(entity);
 	if (iter == entities_.end())
 		return nullptr;
 
-	EntityData &data = iter->second;
-	if (data.video)
-		return data.video.get();
-
-	data.video = std::make_unique<V4L2VideoDevice>(entity);
-	if (data.video->open() < 0)
-		return nullptr;
-
-	data.video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady);
-
-	return data.video.get();
+	return iter->second.video.get();
 }
 
 V4L2Subdevice *SimplePipelineHandler::subdev(const MediaEntity *entity)
-- 
Regards,

Laurent Pinchart



More information about the libcamera-devel mailing list