diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
index b4321f0fa0f7..7f2ec2975db0 100644
--- a/src/libcamera/include/pipeline_handler.h
+++ b/src/libcamera/include/pipeline_handler.h
@@ -14,10 +14,12 @@
 
 namespace libcamera {
 
+class BufferPool;
 class Camera;
 class CameraManager;
 class DeviceEnumerator;
 class MediaDevice;
+class Request;
 class Stream;
 class StreamConfiguration;
 
@@ -45,6 +47,14 @@ public:
 	virtual int configureStreams(Camera *camera,
 				     std::map<Stream *, StreamConfiguration> &config) = 0;
 
+	virtual int allocateBuffers(Camera *camera, Stream *stream) = 0;
+	virtual int freeBuffers(Camera *camera, Stream *stream) = 0;
+
+	virtual int start(const Camera *camera) = 0;
+	virtual void stop(const Camera *camera) = 0;
+
+	virtual int queueRequest(const Camera *camera, Request *request) = 0;
+
 	virtual bool match(DeviceEnumerator *enumerator) = 0;
 
 protected:
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index fa3c5224f6d5..3f096bf1251b 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -34,6 +34,14 @@ public:
 	int configureStreams(Camera *camera,
 			     std::map<Stream *, StreamConfiguration> &config) override;
 
+	int allocateBuffers(Camera *camera, Stream *stream) override;
+	int freeBuffers(Camera *camera, Stream *stream) override;
+
+	int start(const Camera *camera) override;
+	void stop(const Camera *camera) override;
+
+	int queueRequest(const Camera *camera, Request *request) override;
+
 	bool match(DeviceEnumerator *enumerator);
 
 private:
@@ -104,6 +112,32 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,
 	return 0;
 }
 
+int PipelineHandlerIPU3::allocateBuffers(Camera *camera, Stream *stream)
+{
+	return -ENOTRECOVERABLE;
+}
+
+int PipelineHandlerIPU3::freeBuffers(Camera *camera, Stream *stream)
+{
+	return 0;
+}
+
+int PipelineHandlerIPU3::start(const Camera *camera)
+{
+	LOG(IPU3, Error) << "TODO: start camera";
+	return 0;
+}
+
+void PipelineHandlerIPU3::stop(const Camera *camera)
+{
+	LOG(IPU3, Error) << "TODO: stop camera";
+}
+
+int PipelineHandlerIPU3::queueRequest(const Camera *camera, Request *request)
+{
+	return 0;
+}
+
 bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch cio2_dm("ipu3-cio2");
diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
index ecec4e659ac8..74bdf5c5aea5 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -30,6 +30,14 @@ public:
 	int configureStreams(Camera *camera,
 			     std::map<Stream *, StreamConfiguration> &config) override;
 
+	int allocateBuffers(Camera *camera, Stream *stream) override;
+	int freeBuffers(Camera *camera, Stream *stream) override;
+
+	int start(const Camera *camera) override;
+	void stop(const Camera *camera) override;
+
+	int queueRequest(const Camera *camera, Request *request) override;
+
 	bool match(DeviceEnumerator *enumerator);
 
 private:
@@ -82,6 +90,32 @@ int PipelineHandlerUVC::configureStreams(Camera *camera,
 	return 0;
 }
 
+int PipelineHandlerUVC::allocateBuffers(Camera *camera, Stream *stream)
+{
+	return -ENOTRECOVERABLE;
+}
+
+int PipelineHandlerUVC::freeBuffers(Camera *camera, Stream *stream)
+{
+	return 0;
+}
+
+int PipelineHandlerUVC::start(const Camera *camera)
+{
+	LOG(UVC, Error) << "TODO: start camera";
+	return 0;
+}
+
+void PipelineHandlerUVC::stop(const Camera *camera)
+{
+	LOG(UVC, Error) << "TODO: stop camera";
+}
+
+int PipelineHandlerUVC::queueRequest(const Camera *camera, Request *request)
+{
+	return 0;
+}
+
 bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch dm("uvcvideo");
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index 86a89c63fab1..ea6f28c64cc0 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -30,6 +30,14 @@ public:
 	int configureStreams(Camera *camera,
 			     std::map<Stream *, StreamConfiguration> &config) override;
 
+	int allocateBuffers(Camera *camera, Stream *stream) override;
+	int freeBuffers(Camera *camera, Stream *stream) override;
+
+	int start(const Camera *camera) override;
+	void stop(const Camera *camera) override;
+
+	int queueRequest(const Camera *camera, Request *request) override;
+
 	bool match(DeviceEnumerator *enumerator);
 
 private:
@@ -77,6 +85,32 @@ int PipeHandlerVimc::configureStreams(Camera *camera,
 	return 0;
 }
 
+int PipeHandlerVimc::allocateBuffers(Camera *camera, Stream *stream)
+{
+	return -ENOTRECOVERABLE;
+}
+
+int PipeHandlerVimc::freeBuffers(Camera *camera, Stream *stream)
+{
+	return 0;
+}
+
+int PipeHandlerVimc::start(const Camera *camera)
+{
+	LOG(VIMC, Error) << "TODO: start camera";
+	return 0;
+}
+
+void PipeHandlerVimc::stop(const Camera *camera)
+{
+	LOG(VIMC, Error) << "TODO: stop camera";
+}
+
+int PipeHandlerVimc::queueRequest(const Camera *camera, Request *request)
+{
+	return 0;
+}
+
 bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch dm("vimc");
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 3a560e10c442..cc2d4643ec2f 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -109,6 +109,73 @@ PipelineHandler::~PipelineHandler()
  * \return 0 on success or a negative error code on error.
  */
 
+/**
+ * \fn PipelineHandler::allocateBuffers()
+ * \brief Allocate buffers for a stream
+ * \param[in] camera The camera the \a stream belongs to
+ * \param[in] stream The stream to allocate buffers for
+ *
+ * This method allocates buffers internally in the pipeline handler and
+ * associates them with the stream's buffer pool.
+ *
+ * The intended caller of this method is the Camera class.
+ *
+ * \return 0 on success or a negative error code on error
+ */
+
+/**
+ * \fn PipelineHandler::freeBuffers()
+ * \brief Free all buffers associated with a stream
+ * \param[in] camera The camera the \a stream belongs to
+ * \param[in] stream The stream to free buffers from
+ *
+ * After a capture session has been stopped all buffers associated with the
+ * stream shall be freed.
+ *
+ * The intended caller of this method is the Camera class.
+ *
+ * \return 0 on success or a negative error code on error
+ */
+
+/**
+ * \fn PipelineHandler::start()
+ * \brief Start capturing from a group of streams
+ * \param[in] camera The camera to start
+ *
+ * Start the group of streams that have been configured for capture by
+ * \a configureStreams(). The intended caller of this method is the Camera
+ * class which will in turn be called from the application to indicate that it
+ * has configured the streams and is ready to capture.
+ *
+ * \return 0 on success or a negative error code on error
+ */
+
+/**
+ * \fn PipelineHandler::stop()
+ * \brief Stop capturing from all running streams
+ * \param[in] camera The camera to stop
+ *
+ * This method stops capturing and processing requests immediately. All pending
+ * requests are cancelled and complete immediately in an error state.
+ *
+ * \todo Complete the pending requests immediately
+ */
+
+/**
+ * \fn PipelineHandler::queueRequest()
+ * \brief Queue a request to the camera
+ * \param[in] camera The camera to queue the request to
+ * \param[in] request The request to queue
+ *
+ * This method queues a capture request to the pipeline handler for processing.
+ * The request contains a set of buffers associated with streams and a set of
+ * parameters. The pipeline handler shall program the device to ensure that the
+ * parameters will be applied to the frames captured in the buffers provided in
+ * the request.
+ *
+ * \return 0 on success or a negative error code on error
+ */
+
 /**
  * \fn PipelineHandler::match(DeviceEnumerator *enumerator)
  * \brief Match media devices and create camera instances
