[libcamera-devel] [PATCH v2 18/25] libcamera: pipelines: Add FrameBuffer handlers

Niklas Söderlund niklas.soderlund at ragnatech.se
Mon Dec 30 13:05:03 CET 2019


Extend the pipeline handlers to support the FrameBuffer API with three
new methods to handle allocation, importing and freeing of buffers. The
new methods will replace allocateBuffers() and freeBuffers().

The FrameBuffer API will use the methods on a stream level and either
allocate or import buffers for each active stream controlled from the
Camera class and an upcoming FrameBufferAllocator helper. With this new
API the implementation in pipeline handlers can be made simpler as all
streams don't need to be handled in allocateBuffers().

Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
---
 src/libcamera/include/pipeline_handler.h |  7 +++
 src/libcamera/pipeline/ipu3/ipu3.cpp     | 34 +++++++++++++
 src/libcamera/pipeline/rkisp1/rkisp1.cpp | 25 ++++++++++
 src/libcamera/pipeline/uvcvideo.cpp      | 31 ++++++++++++
 src/libcamera/pipeline/vimc.cpp          | 31 ++++++++++++
 src/libcamera/pipeline_handler.cpp       | 62 ++++++++++++++++++++++++
 6 files changed, 190 insertions(+)

diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
index f3622631022d87b9..520d3fccaaa130cc 100644
--- a/src/libcamera/include/pipeline_handler.h
+++ b/src/libcamera/include/pipeline_handler.h
@@ -69,6 +69,13 @@ public:
 		const StreamRoles &roles) = 0;
 	virtual int configure(Camera *camera, CameraConfiguration *config) = 0;
 
+	virtual int allocateFrameBuffers(Camera *camera, Stream *stream,
+					 unsigned int count,
+					 std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;
+	virtual int importFrameBuffers(Camera *camera, Stream *stream,
+				       unsigned int count) = 0;
+	virtual void freeFrameBuffers(Camera *camera, Stream *stream) = 0;
+
 	virtual int allocateBuffers(Camera *camera,
 				    const std::set<Stream *> &streams) = 0;
 	virtual int freeBuffers(Camera *camera,
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 030ba2b6a0df2e0b..f9bddcc88523301f 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -210,6 +210,13 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int allocateFrameBuffers(Camera *camera, Stream *stream,
+				 unsigned int count,
+				 std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream,
+			       unsigned int count) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 			    const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -616,6 +623,33 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
 	return 0;
 }
 
+int PipelineHandlerIPU3::allocateFrameBuffers(Camera *camera, Stream *stream,
+					      unsigned int count,
+					      std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
+	V4L2VideoDevice *video = ipu3stream->device_->dev;
+
+	return video->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerIPU3::importFrameBuffers(Camera *camera, Stream *stream,
+					    unsigned int count)
+{
+	IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
+	V4L2VideoDevice *video = ipu3stream->device_->dev;
+
+	return video->importBuffers(count);
+}
+
+void PipelineHandlerIPU3::freeFrameBuffers(Camera *camera, Stream *stream)
+{
+	IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
+	V4L2VideoDevice *video = ipu3stream->device_->dev;
+
+	video->releaseBuffers();
+}
+
 /**
  * \todo Clarify if 'viewfinder' and 'stat' nodes have to be set up and
  * started even if not in use. As of now, if not properly configured and
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index ea581aaaa85088cd..e77925f6f9deff08 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -175,6 +175,13 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int allocateFrameBuffers(Camera *camera, Stream *stream,
+				 unsigned int count,
+				 std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream,
+			       unsigned int count) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 		const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -666,6 +673,24 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
 	return 0;
 }
 
+int PipelineHandlerRkISP1::allocateFrameBuffers(Camera *camera, Stream *stream,
+						unsigned int count,
+						std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	return video_->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerRkISP1::importFrameBuffers(Camera *camera, Stream *stream,
+					      unsigned int count)
+{
+	return video_->importBuffers(count);
+}
+
+void PipelineHandlerRkISP1::freeFrameBuffers(Camera *camera, Stream *stream)
+{
+	video_->releaseBuffers();
+}
+
 int PipelineHandlerRkISP1::allocateBuffers(Camera *camera,
 					   const std::set<Stream *> &streams)
 {
diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
index 3043366bee38bcfc..655c5e6d96a696d6 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -64,6 +64,13 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int allocateFrameBuffers(Camera *camera, Stream *stream,
+				 unsigned int count,
+				 std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream,
+			       unsigned int count) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 			    const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -192,6 +199,30 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config)
 	return 0;
 }
 
+int PipelineHandlerUVC::allocateFrameBuffers(Camera *camera, Stream *stream,
+					     unsigned int count,
+					     std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	UVCCameraData *data = cameraData(camera);
+
+	return data->video_->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerUVC::importFrameBuffers(Camera *camera, Stream *stream,
+					   unsigned int count)
+{
+	UVCCameraData *data = cameraData(camera);
+
+	return data->video_->importBuffers(count);
+}
+
+void PipelineHandlerUVC::freeFrameBuffers(Camera *camera, Stream *stream)
+{
+	UVCCameraData *data = cameraData(camera);
+
+	data->video_->releaseBuffers();
+}
+
 int PipelineHandlerUVC::allocateBuffers(Camera *camera,
 					const std::set<Stream *> &streams)
 {
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index 292900bcf8d1b359..02235ffb0515982f 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -82,6 +82,13 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int allocateFrameBuffers(Camera *camera, Stream *stream,
+				 unsigned int count,
+				 std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream,
+			       unsigned int count) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 			    const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -259,6 +266,30 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
 	return 0;
 }
 
+int PipelineHandlerVimc::allocateFrameBuffers(Camera *camera, Stream *stream,
+					      unsigned int count,
+					      std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	VimcCameraData *data = cameraData(camera);
+
+	return data->video_->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerVimc::importFrameBuffers(Camera *camera, Stream *stream,
+					    unsigned int count)
+{
+	VimcCameraData *data = cameraData(camera);
+
+	return data->video_->importBuffers(count);
+}
+
+void PipelineHandlerVimc::freeFrameBuffers(Camera *camera, Stream *stream)
+{
+	VimcCameraData *data = cameraData(camera);
+
+	data->video_->releaseBuffers();
+}
+
 int PipelineHandlerVimc::allocateBuffers(Camera *camera,
 					 const std::set<Stream *> &streams)
 {
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 5badf31ce793edf8..fb69ca8e97216e6c 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -287,6 +287,68 @@ const ControlInfoMap &PipelineHandler::controls(Camera *camera)
  * \return 0 on success or a negative error code otherwise
  */
 
+/**
+ * \fn PipelineHandler::allocateFrameBuffers()
+ * \brief Allocate buffers for \a stream
+ * \param[in] camera The camera to allocate buffers on
+ * \param[in] stream The stream to allocate buffers for
+ * \param[in] count Number of buffers to allocate
+ * \param[out] buffers Array of buffers successfully allocated
+ *
+ * Allocate buffers for \a stream using the resources associated with the stream
+ * inside the pipelinehandler.
+ *
+ * The method could be called multiple times to operate on different streams.
+ * It is not allowed to call allocateFrameBuffers() and importFrameBuffers()
+ * on the same \a stream as they are mutually exclusive operations. The
+ * pipelinehandler must guarantee that all streams exposed as part of the Camera
+ * can be used simultaneously with all combinations of the two.
+ *
+ * This is a helper which may be used by libcamera helper classes to allocate
+ * buffers from the stream itself. The allocated buffers may then be treated
+ * in the same way as if they where externally allocated.
+ *
+ * The only intended caller is the FrameBufferAllocator helper.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+
+/**
+ * \fn PipelineHandler::importFrameBuffers()
+ * \brief Prepare \a stream to use external buffers
+ * \param[in] camera The camera to prepare for import on
+ * \param[in] stream The stream to prepare for import
+ * \param[in] count Number of buffers to import
+ *
+ * Prepare the \a stream to use \a count number of buffers allocated outside
+ * the pipelinehandler.
+ *
+ * The method could be called multiple times to operate on different streams.
+ * It is not allowed to call allocateFrameBuffers() and importFrameBuffers()
+ * on the same \a stream as they are mutually exclusive operations. The
+ * pipelinehandler must guarantee that all streams exposed as part of the Camera
+ * can be used simultaneously with all combinations of the two.
+ *
+ * This is a helper which may be used by libcamera helper classes to import
+ * buffers to the \a stream from external sources.
+ *
+ * The only intended caller is the FrameBufferAllocator helper.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+
+/**
+ * \fn PipelineHandler::freeFrameBuffers()
+ * \brief Free buffers allocated from the stram
+ * \param[in] camera The camera to free buffers on
+ * \param[in] stream The stream to free buffers for
+ *
+ * This is a helper that frees buffers and resources allocated using
+ * allocateFrameBuffers() or importFrameBuffers().
+ *
+ * The only intended caller is the FrameBufferAllocator helper.
+ */
+
 /**
  * \fn PipelineHandler::allocateBuffers()
  * \brief Allocate buffers for a stream
-- 
2.24.1



More information about the libcamera-devel mailing list