[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