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
