[01/11] libcamera: Infrastructure to ask for "memory" cameras
diff mbox series

Message ID 20251210164055.17856-2-david.plowman@raspberrypi.com
State New
Headers show
Series
  • Bayer re-processing
Related show

Commit Message

David Plowman Dec. 10, 2025, 4:15 p.m. UTC
"Memory" cameras are used to make it easier to process raw camera
images that are stored in memory buffers. There may be no actual
camera attached to the system at all.

Memory cameras are not created when the system starts. Depending on
the pipeline handler, it may be possible to open many memory cameras
simultaneously, or none at all. So any time an application requests a
memory camera, we check with the pipeline handler whether it can
provide one.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
---
 include/libcamera/camera_manager.h            |  4 ++
 include/libcamera/internal/camera_manager.h   |  5 ++
 include/libcamera/internal/pipeline_handler.h |  8 +++
 src/libcamera/camera_manager.cpp              | 64 +++++++++++++++++++
 src/libcamera/pipeline_handler.cpp            | 23 +++++++
 5 files changed, 104 insertions(+)

Patch
diff mbox series

diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h
index 27835500..436db409 100644
--- a/include/libcamera/camera_manager.h
+++ b/include/libcamera/camera_manager.h
@@ -7,6 +7,7 @@ 
 
 #pragma once
 
+#include <map>
 #include <memory>
 #include <string>
 #include <string_view>
@@ -20,6 +21,7 @@ 
 namespace libcamera {
 
 class Camera;
+class PipelineHandler;
 
 class CameraManager : public Object, public Extensible
 {
@@ -33,6 +35,8 @@  public:
 
 	std::vector<std::shared_ptr<Camera>> cameras() const;
 	std::shared_ptr<Camera> get(std::string_view id);
+	std::vector<std::string> memoryCameras() const;
+	std::shared_ptr<Camera> getMemoryCamera(std::string_view id, std::string_view settings);
 
 	static const std::string &version() { return version_; }
 
diff --git a/include/libcamera/internal/camera_manager.h b/include/libcamera/internal/camera_manager.h
index 755928ce..4dbc1dc8 100644
--- a/include/libcamera/internal/camera_manager.h
+++ b/include/libcamera/internal/camera_manager.h
@@ -55,6 +55,9 @@  private:
 	void pipelineFactoryMatch(const PipelineHandlerFactoryBase *factory);
 	void cleanup() LIBCAMERA_TSA_EXCLUDES(mutex_);
 
+	std::shared_ptr<Camera> getMemoryCamera(const PipelineHandlerFactoryBase *factory,
+						std::string_view settings);
+
 	/*
 	 * This mutex protects
 	 *
@@ -70,6 +73,8 @@  private:
 
 	std::unique_ptr<DeviceEnumerator> enumerator_;
 
+	std::vector<std::string> memoryCameras_;
+
 	std::unique_ptr<IPAManager> ipaManager_;
 
 	const GlobalConfiguration configuration_;
diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
index b4f97477..cb631529 100644
--- a/include/libcamera/internal/pipeline_handler.h
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -70,6 +70,14 @@  public:
 
 	CameraManager *cameraManager() const { return manager_; }
 
+	virtual bool supportsMemoryCamera() { return false; }
+
+	virtual std::shared_ptr<Camera> createMemoryCamera([[maybe_unused]] DeviceEnumerator *enumerator,
+							   [[maybe_unused]] std::string_view settings)
+	{
+		return nullptr;
+	}
+
 protected:
 	void registerCamera(std::shared_ptr<Camera> camera);
 	void hotplugMediaDevice(std::shared_ptr<MediaDevice> media);
diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp
index 83510e06..734f5836 100644
--- a/src/libcamera/camera_manager.cpp
+++ b/src/libcamera/camera_manager.cpp
@@ -155,6 +155,13 @@  void CameraManager::Private::pipelineFactoryMatch(const PipelineHandlerFactoryBa
 {
 	CameraManager *const o = LIBCAMERA_O_PTR();
 
+	/* First check for any memory-to-memory camera pipelines. */
+	{
+		std::shared_ptr<PipelineHandler> pipe = factory->create(o);
+		if (pipe->supportsMemoryCamera())
+			memoryCameras_.push_back(std::string(pipe->name()));
+	}
+
 	/* Provide as many matching pipelines as possible. */
 	while (1) {
 		std::shared_ptr<PipelineHandler> pipe = factory->create(o);
@@ -167,6 +174,19 @@  void CameraManager::Private::pipelineFactoryMatch(const PipelineHandlerFactoryBa
 	}
 }
 
+std::shared_ptr<Camera> CameraManager::Private::getMemoryCamera(const PipelineHandlerFactoryBase *factory,
+								std::string_view settings)
+{
+	CameraManager *const o = LIBCAMERA_O_PTR();
+
+	std::shared_ptr<PipelineHandler> pipe = factory->create(o);
+
+	pipe->moveToThread(this);
+
+	return pipe->invokeMethod(&PipelineHandler::createMemoryCamera,
+				  ConnectionTypeBlocking, enumerator_.get(), settings);
+}
+
 void CameraManager::Private::cleanup()
 {
 	enumerator_->devicesAdded.disconnect(this);
@@ -371,6 +391,9 @@  void CameraManager::stop()
  * Before calling this function the caller is responsible for ensuring that
  * the camera manager is running.
  *
+ * This function does not list any memory cameras (for processing raw images
+ * held in memory buffers) that may be available.
+ *
  * \context This function is \threadsafe.
  *
  * \return List of all available cameras
@@ -409,6 +432,47 @@  std::shared_ptr<Camera> CameraManager::get(std::string_view id)
 	return nullptr;
 }
 
+/**
+ * \brief List the pipeline handlers that support memory cameras
+ *
+ * Lists the pipeline handlers in the system that have indicated they
+ * support memory cameras. Memory cameras are used for processing raw
+ * camera images stored in memory buffers, where no corresponding
+ * camera is available.
+ *
+ * \return Vector of pipeline handler ids (strings)
+ */
+std::vector<std::string> CameraManager::memoryCameras() const
+{
+	return _d()->memoryCameras_;
+}
+
+/**
+ * \brief Get a memory camera from the named pipeline handler
+ * \param[in] id ID of the pipeline handler that should create the memory camera
+ *
+ * This function causes the named pipeline handler to create and return a
+ * memory camera to the application. Pipeline handlers may support multiple
+ * simultaneous memory cameras, or none at all.
+ *
+ * \return Shared pointer to Camera object or nullptr if no memory camera
+ * could be provided
+ */
+std::shared_ptr<Camera> CameraManager::getMemoryCamera(std::string_view id,
+						       std::string_view settings)
+{
+	for (const auto &name : _d()->memoryCameras_) {
+		if (name == id) {
+			const PipelineHandlerFactoryBase *factory;
+			factory = PipelineHandlerFactoryBase::getFactoryByName(name);
+
+			return _d()->getMemoryCamera(factory, settings);
+		}
+	}
+
+	return nullptr;
+}
+
 /**
  * \var CameraManager::cameraAdded
  * \brief Notify of a new camera added to the system
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 5c469e5b..c0f3c84e 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -835,6 +835,29 @@  void PipelineHandler::disconnect()
  * \return The CameraManager for this pipeline handler
  */
 
+/**
+ * \fn PipelineHandler::supportsMemoryCamera()
+ * \brief Indicate whether this pipeline handler supports memory cameras.
+ * \return True if the pipeline handler supports memory cameras, otherwise false.
+ */
+
+/**
+ * \fn PipelineHandler::createMemoryCamera()
+ * \brief Create a memory camera to process raw camera images from a memory buffer
+ * \param[in] enumerator The enumerator providing all media devices found in the
+ * system
+ * \param[in] settings A string of settings that the pipeline handler should use
+ *
+ * The pipeline handler should create a memory camera, which an application can
+ * use to process raw camera images that are stored in memory buffers (rather
+ * than being delivered from a live camera).
+ *
+ * The settings should indicate exactly what processing the application requires
+ * to be performed on the raw image.
+ *
+ * \return Shared pointer to a camera, or a nullptr if none could be created
+ */
+
 /**
  * \class PipelineHandlerFactoryBase
  * \brief Base class for pipeline handler factories