[libcamera-devel] [PATCH v3 24/33] libcamera: pipeline: Add FrameBuffer handlers

Niklas Söderlund niklas.soderlund at ragnatech.se
Fri Jan 10 20:37:59 CET 2020


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>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
* Changes since v2
- In the subject line, s/pipelines/pipeline/
- Rename allocateFrameBuffers() to exportFrameBuffers()
- Rewrite of documentation, thanks Laurent!
- Remove count argument from exportFrameBuffers() and
  importFrameBuffers() and instead get the buffer count from the stream
  configuration.
---
 src/libcamera/include/pipeline_handler.h |  5 ++
 src/libcamera/pipeline/ipu3/ipu3.cpp     | 32 +++++++++++
 src/libcamera/pipeline/rkisp1/rkisp1.cpp | 23 ++++++++
 src/libcamera/pipeline/uvcvideo.cpp      | 29 ++++++++++
 src/libcamera/pipeline/vimc.cpp          | 29 ++++++++++
 src/libcamera/pipeline_handler.cpp       | 67 ++++++++++++++++++++++++
 6 files changed, 185 insertions(+)

diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
index 067baef56278b577..560be3bad8d59b20 100644
--- a/src/libcamera/include/pipeline_handler.h
+++ b/src/libcamera/include/pipeline_handler.h
@@ -70,6 +70,11 @@ public:
 		const StreamRoles &roles) = 0;
 	virtual int configure(Camera *camera, CameraConfiguration *config) = 0;
 
+	virtual int exportFrameBuffers(Camera *camera, Stream *stream,
+				       std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;
+	virtual int importFrameBuffers(Camera *camera, Stream *stream) = 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 7c4539d488bd2d26..b73f0f0725ee2613 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -210,6 +210,11 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int exportFrameBuffers(Camera *camera, Stream *stream,
+			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 			    const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -616,6 +621,33 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
 	return 0;
 }
 
+int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream,
+					    std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
+	V4L2VideoDevice *video = ipu3stream->device_->dev;
+	unsigned int count = stream->configuration().bufferCount;
+
+	return video->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerIPU3::importFrameBuffers(Camera *camera, Stream *stream)
+{
+	IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
+	V4L2VideoDevice *video = ipu3stream->device_->dev;
+	unsigned int count = stream->configuration().bufferCount;
+
+	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 dbc5df801f30e76b..ba8f93e8584c97a9 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -174,6 +174,11 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int exportFrameBuffers(Camera *camera, Stream *stream,
+			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 		const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -665,6 +670,24 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
 	return 0;
 }
 
+int PipelineHandlerRkISP1::exportFrameBuffers(Camera *camera, Stream *stream,
+					      std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	unsigned int count = stream->configuration().bufferCount;
+	return video_->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerRkISP1::importFrameBuffers(Camera *camera, Stream *stream)
+{
+	unsigned int count = stream->configuration().bufferCount;
+	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 ce38445d2a48ca82..b72841edee572f99 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -65,6 +65,11 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int exportFrameBuffers(Camera *camera, Stream *stream,
+			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 			    const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -193,6 +198,30 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config)
 	return 0;
 }
 
+int PipelineHandlerUVC::exportFrameBuffers(Camera *camera, Stream *stream,
+					   std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	UVCCameraData *data = cameraData(camera);
+	unsigned int count = stream->configuration().bufferCount;
+
+	return data->video_->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerUVC::importFrameBuffers(Camera *camera, Stream *stream)
+{
+	UVCCameraData *data = cameraData(camera);
+	unsigned int count = stream->configuration().bufferCount;
+
+	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..3fb5cacde0dab5b6 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -82,6 +82,11 @@ public:
 		const StreamRoles &roles) override;
 	int configure(Camera *camera, CameraConfiguration *config) override;
 
+	int exportFrameBuffers(Camera *camera, Stream *stream,
+			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
+	int importFrameBuffers(Camera *camera, Stream *stream) override;
+	void freeFrameBuffers(Camera *camera, Stream *stream) override;
+
 	int allocateBuffers(Camera *camera,
 			    const std::set<Stream *> &streams) override;
 	int freeBuffers(Camera *camera,
@@ -259,6 +264,30 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
 	return 0;
 }
 
+int PipelineHandlerVimc::exportFrameBuffers(Camera *camera, Stream *stream,
+					    std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	VimcCameraData *data = cameraData(camera);
+	unsigned int count = stream->configuration().bufferCount;
+
+	return data->video_->exportBuffers(count, buffers);
+}
+
+int PipelineHandlerVimc::importFrameBuffers(Camera *camera, Stream *stream)
+{
+	VimcCameraData *data = cameraData(camera);
+	unsigned int count = stream->configuration().bufferCount;
+
+	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 698dd52560797d7c..572f751b5217eb5f 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -289,6 +289,73 @@ const ControlInfoMap &PipelineHandler::controls(Camera *camera)
  * \return 0 on success or a negative error code otherwise
  */
 
+/**
+ * \fn PipelineHandler::exportFrameBuffers()
+ * \brief Allocate buffers for \a stream
+ * \param[in] camera The camera
+ * \param[in] stream The stream to allocate buffers for
+ * \param[out] buffers Array of buffers successfully allocated
+ *
+ * This method allocates buffers for the \a stream from the devices associated
+ * with the stream in the corresponding pipeline handler. Those buffers shall be
+ * suitable to be added to a Request for the stream, and shall be mappable to
+ * the CPU through their associated dmabufs with mmap().
+ *
+ * exportFrameBuffers() shall also allocate all other resources required by
+ * the pipeline handler for the stream to prepare for starting the Camera. This
+ * responsibility is shared with importFrameBuffers(), and one and only one of
+ * those two methods shall be called for each stream until the buffers are
+ * freed. The pipeline handler shall support all combinations of
+ * exportFrameBuffers() and importFrameBuffers() for the streams contained in
+ * any camera configuration.
+ *
+ * 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
+ * \param[in] stream The stream to prepare for import
+ *
+ * This method prepares the pipeline handler to use buffers provided by the
+ * application for the \a stream.
+ *
+ * The method may only be called after the Camera has been configured and before
+ * it gets started, or after it gets stopped. It shall be called only for
+ * streams that are part of the active camera configuration, and at most once
+ * per stream until buffers for the stream are freed with freeFrameBuffers().
+ *
+ * importFrameBuffers() shall also allocate all other resources required by the
+ * pipeline handler for the stream to prepare for starting the Camera. This
+ * responsibility is shared with exportFrameBuffers(), and one and only one of
+ * those two methods shall be called for each stream until the buffers are
+ * freed. The pipeline handler shall support all combinations of
+ * exportFrameBuffers() and importFrameBuffers() for the streams contained in
+ * any camera configuration.
+ *
+ * The only intended caller is Camera::start().
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+
+/**
+ * \fn PipelineHandler::freeFrameBuffers()
+ * \brief Free buffers allocated from the stream
+ * \param[in] camera The camera
+ * \param[in] stream The stream to free buffers for
+ *
+ * This method shall free all buffers and all other resources allocated for the
+ * \a stream by exportFrameBuffers() or importFrameBuffers(). It shall be
+ * called only after a successful call to either of these two methods, and only
+ * once per stream.
+ *
+ * The only intended callers are Camera::stop() and the FrameBufferAllocator
+ * helper.
+ */
+
 /**
  * \fn PipelineHandler::allocateBuffers()
  * \brief Allocate buffers for a stream
-- 
2.24.1



More information about the libcamera-devel mailing list