[libcamera-devel] [PATCH v4 2/9] ipu3: Allow only one camera being started

Harvey Yang chenghaoyang at chromium.org
Tue Aug 2 12:29:36 CEST 2022


From: Harvey Yang <chenghaoyang at chromium.org>

As we hardly have use cases/applications that need both cameras at the
same time, this patch adds a rule that only one camera can be started
one time. This also allows the following patches that use both imgus to
process frames from one single camera.

Signed-off-by: Harvey Yang <chenghaoyang at chromium.org>
---
 include/libcamera/internal/pipeline_handler.h |  5 ++++
 src/libcamera/camera.cpp                      | 11 ++++++++
 src/libcamera/pipeline/ipu3/ipu3.cpp          | 18 +++++++++++++
 src/libcamera/pipeline_handler.cpp            | 26 +++++++++++++++++++
 4 files changed, 60 insertions(+)

diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
index c3e4c258..8277ceda 100644
--- a/include/libcamera/internal/pipeline_handler.h
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -55,6 +55,9 @@ public:
 	virtual int exportFrameBuffers(Camera *camera, Stream *stream,
 				       std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;
 
+	virtual bool acquire(Camera *camera);
+	virtual void release(Camera *camera);
+
 	virtual int start(Camera *camera, const ControlList *controls) = 0;
 	void stop(Camera *camera);
 	bool hasPendingRequests(const Camera *camera) const;
@@ -76,6 +79,8 @@ protected:
 
 	CameraManager *manager_;
 
+	std::set<Camera*> acquiredCameras_;
+
 private:
 	void mediaDeviceDisconnected(MediaDevice *media);
 	virtual void disconnect();
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index 713543fd..a31f8769 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -826,6 +826,8 @@ int Camera::exportFrameBuffers(Stream *stream,
  * \return 0 on success or a negative error code otherwise
  * \retval -ENODEV The camera has been disconnected from the system
  * \retval -EBUSY The camera is not free and can't be acquired by the caller
+ * \retval -EUSERS The maximum number of cameras that can be opened concurrently
+ * were opened already
  */
 int Camera::acquire()
 {
@@ -845,6 +847,14 @@ int Camera::acquire()
 		return -EBUSY;
 	}
 
+	if (!d->pipe_->acquire(this)) {
+		LOG(Camera, Info)
+			<< "The maximum number of cameras that can be opened"
+			   "concurrently were opened already";
+		d->pipe_->unlock();
+		return -EUSERS;
+	}
+
 	d->setState(Private::CameraAcquired);
 
 	return 0;
@@ -873,6 +883,7 @@ int Camera::release()
 	if (ret < 0)
 		return ret == -EACCES ? -EBUSY : ret;
 
+	d->pipe_->release(this);
 	d->pipe_->unlock();
 
 	d->setState(Private::CameraAvailable);
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index fd989e61..091a40e1 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -141,6 +141,8 @@ public:
 	int exportFrameBuffers(Camera *camera, Stream *stream,
 			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
 
+	bool acquire(Camera *camera) override;
+
 	int start(Camera *camera, const ControlList *controls) override;
 	void stopDevice(Camera *camera) override;
 
@@ -763,8 +765,24 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera)
 	return 0;
 }
 
+bool PipelineHandlerIPU3::acquire(Camera *camera) {
+	/*
+	 * Enforce that only a single camera can be used at a time to use both
+	 * ImgUs on the camera, so that StillCapture stream can adopt another
+	 * set of configuration.
+	 */
+	if (!acquiredCameras_.empty())
+		return false;
+
+	return PipelineHandler::acquire(camera);
+
+}
+
 int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] const ControlList *controls)
 {
+	if (acquiredCameras_.empty() || *acquiredCameras_.begin() != camera)
+		return -EUSERS;
+
 	IPU3CameraData *data = cameraData(camera);
 	CIO2Device *cio2 = &data->cio2_;
 	ImgUDevice *imgu = data->imgu_;
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 7ebd76ad..fff9ee59 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -270,6 +270,32 @@ void PipelineHandler::unlock()
  * otherwise
  */
 
+/**
+ * \fn PipelineHandler::acquire()
+ * \brief Check if \a camera can be acquired and supported with the current
+ * pipeline handler usage. If \a camera has already been acquired (by the same
+ * or another process), return false.
+ * \param[in] camera The camera
+ */
+bool PipelineHandler::acquire(Camera *camera)
+{
+	if (acquiredCameras_.find(camera) != acquiredCameras_.end())
+		return false;
+
+	acquiredCameras_.emplace(camera);
+	return true;
+}
+
+/**
+ * \fn PipelineHandler::release()
+ * \brief Release exclusive access to \a camera
+ * \param[in] camera The camera
+ */
+void PipelineHandler::release(Camera *camera)
+{
+	acquiredCameras_.erase(camera);
+}
+
 /**
  * \fn PipelineHandler::start()
  * \brief Start capturing from a group of streams
-- 
2.37.1.455.g008518b4e5-goog



More information about the libcamera-devel mailing list