diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index c46515110ffc..998ee3c813bc 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -1099,14 +1099,15 @@ int PipelineHandlerRkISP1::exportFrameBuffers([[maybe_unused]] Camera *camera, S
 int PipelineHandlerRkISP1::allocateBuffers(Camera *camera)
 {
 	RkISP1CameraData *data = cameraData(camera);
+	utils::ScopeExitActions actions;
 	unsigned int ipaBufferId = 1;
 	int ret;
 
-	auto errorCleanup = utils::scope_exit{ [&]() {
+	actions += [&]() {
 		paramBuffers_.clear();
 		statBuffers_.clear();
 		mainPathBuffers_.clear();
-	} };
+	};
 
 	if (!isRaw_) {
 		ret = param_->allocateBuffers(kRkISP1InternalBufferCount, &paramBuffers_);
@@ -1127,6 +1128,22 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera)
 
 		for (std::unique_ptr<FrameBuffer> &buffer : mainPathBuffers_)
 			availableMainPathBuffers_.push(buffer.get());
+	} else if (data->mainPath_->isEnabled()) {
+		ret = mainPath_.importBuffers(data->mainPathStream_.configuration().bufferCount);
+
+		if (ret < 0)
+			return ret;
+
+		actions += [&]() { mainPath_.releaseBuffers(); };
+	}
+
+	if (hasSelfPath_ && data->selfPath_->isEnabled()) {
+		ret = selfPath_.importBuffers(data->selfPathStream_.configuration().bufferCount);
+
+		if (ret < 0)
+			return ret;
+
+		actions += [&]() { selfPath_.releaseBuffers(); };
 	}
 
 	auto pushBuffers = [&](const std::vector<std::unique_ptr<FrameBuffer>> &buffers,
@@ -1147,7 +1164,7 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera)
 
 	data->ipa_->mapBuffers(data->ipaBuffers_);
 
-	errorCleanup.release();
+	actions.release();
 	return 0;
 }
 
@@ -1181,6 +1198,12 @@ int PipelineHandlerRkISP1::freeBuffers(Camera *camera)
 	if (stat_->releaseBuffers())
 		LOG(RkISP1, Error) << "Failed to release stat buffers";
 
+	if (mainPath_.releaseBuffers())
+		LOG(RkISP1, Error) << "Failed to release main path buffers";
+
+	if (hasSelfPath_ && selfPath_.releaseBuffers())
+		LOG(RkISP1, Error) << "Failed to release self path buffers";
+
 	return 0;
 }
 
@@ -1263,16 +1286,17 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL
 	}
 
 	if (data->mainPath_->isEnabled()) {
-		ret = mainPath_.start(data->mainPathStream_.configuration().bufferCount);
+		ret = mainPath_.streamOn();
 		if (ret)
 			return ret;
-		actions += [&]() { mainPath_.stop(); };
+		actions += [&]() { mainPath_.streamOff(); };
 	}
 
 	if (hasSelfPath_ && data->selfPath_->isEnabled()) {
-		ret = selfPath_.start(data->selfPathStream_.configuration().bufferCount);
+		ret = selfPath_.streamOn();
 		if (ret)
 			return ret;
+		actions += [&]() { selfPath_.streamOff(); };
 	}
 
 	isp_->setFrameStartEnabled(true);
@@ -1299,8 +1323,8 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera)
 	data->ipa_->stop();
 
 	if (hasSelfPath_)
-		selfPath_.stop();
-	mainPath_.stop();
+		selfPath_.streamOff();
+	mainPath_.streamOff();
 
 	if (!isRaw_) {
 		ret = stat_->streamOff();
@@ -1664,9 +1688,9 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)
 		return false;
 
 	isp_->frameStart.connect(this, &PipelineHandlerRkISP1::frameStart);
-	mainPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::imageBufferReady);
+	mainPath_.bufferReady.connect(this, &PipelineHandlerRkISP1::imageBufferReady);
 	if (hasSelfPath_)
-		selfPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::imageBufferReady);
+		selfPath_.bufferReady.connect(this, &PipelineHandlerRkISP1::imageBufferReady);
 	stat_->bufferReady.connect(this, &PipelineHandlerRkISP1::statBufferReady);
 	param_->bufferReady.connect(this, &PipelineHandlerRkISP1::paramBufferReady);
 
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index ef9cfbdc327a..80a01280e6f7 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -8,6 +8,7 @@
 #include "rkisp1_path.h"
 
 #include <array>
+#include <memory>
 
 #include <linux/media-bus-format.h>
 
@@ -58,7 +59,7 @@ const std::map<PixelFormat, uint32_t> formatToMediaBus = {
 
 RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats,
 		       const Size &minResolution, const Size &maxResolution)
-	: name_(name), running_(false), formats_(formats),
+	: name_(name), formats_(formats),
 	  minResolution_(minResolution), maxResolution_(maxResolution),
 	  link_(nullptr)
 {
@@ -77,6 +78,7 @@ bool RkISP1Path::init(std::shared_ptr<MediaDevice> media)
 	if (video_->open() < 0)
 		return false;
 
+	video_->bufferReady.connect(this, [this](FrameBuffer *buffer) { this->bufferReady.emit(buffer); });
 	populateFormats();
 
 	link_ = media->link("rkisp1_isp", 2, resizer, 0);
@@ -480,44 +482,6 @@ int RkISP1Path::configure(const StreamConfiguration &config,
 	return 0;
 }
 
-int RkISP1Path::start(unsigned int bufferCount)
-{
-	int ret;
-
-	if (running_)
-		return -EBUSY;
-
-	ret = video_->importBuffers(bufferCount);
-	if (ret)
-		return ret;
-
-	ret = video_->streamOn();
-	if (ret) {
-		LOG(RkISP1, Error)
-			<< "Failed to start " << name_ << " path";
-
-		video_->releaseBuffers();
-		return ret;
-	}
-
-	running_ = true;
-
-	return 0;
-}
-
-void RkISP1Path::stop()
-{
-	if (!running_)
-		return;
-
-	if (video_->streamOff())
-		LOG(RkISP1, Warning) << "Failed to stop " << name_ << " path";
-
-	video_->releaseBuffers();
-
-	running_ = false;
-}
-
 /*
  * \todo Remove the hardcoded resolutions and formats once kernels older than
  * v6.4 will stop receiving LTS support (scheduled for December 2027 for v6.1).
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
index 0c68e9eb99af..d2bce01c9336 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
@@ -58,19 +58,34 @@ public:
 		return video_->exportBuffers(bufferCount, buffers);
 	}
 
-	int start(unsigned int bufferCount);
-	void stop();
+	int allocateBuffers(unsigned int bufferCount,
+			    std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+	{
+		return video_->allocateBuffers(bufferCount, buffers);
+	}
+
+	int importBuffers(unsigned int count)
+	{
+		return video_->importBuffers(count);
+	}
+
+	int releaseBuffers()
+	{
+		return video_->releaseBuffers();
+	}
+
+	int streamOn() { return video_->streamOn(); };
+	int streamOff() { return video_->streamOff(); };
 
 	int queueBuffer(FrameBuffer *buffer) { return video_->queueBuffer(buffer); }
-	Signal<FrameBuffer *> &bufferReady() { return video_->bufferReady; }
 	const Size &maxResolution() const { return maxResolution_; }
 
+	Signal<FrameBuffer *> bufferReady;
 private:
 	void populateFormats();
 	Size filterSensorResolution(const CameraSensor *sensor);
 
 	const char *name_;
-	bool running_;
 
 	const Span<const PixelFormat> formats_;
 	std::set<PixelFormat> streamFormats_;
