diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
index 471975a890..0195a9f3a8 100644
--- a/include/libcamera/camera.h
+++ b/include/libcamera/camera.h
@@ -124,7 +124,7 @@ public:
 
 	const std::string &id() const;
 
-	Signal<Request *, FrameBuffer *> bufferCompleted;
+	Signal<Request *, const Stream *, FrameBuffer *> bufferCompleted;
 	Signal<Request *> requestCompleted;
 	Signal<> disconnected;
 
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index be55ed72c4..1bb696566c 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -800,12 +800,14 @@ Camera::Private::acquireBuffer(const Stream *stream)
  */
 void Camera::Private::rejectBuffer(FrameBuffer *buffer)
 {
+	const Stream *stream = buffer->_d()->stream_;
+
 	ASSERT(!buffer->_d()->request());
-	ASSERT(buffer->_d()->stream_);
+	ASSERT(stream);
 
 	LOG(Camera, Debug)
 		<< "Camera:" << LIBCAMERA_O_PTR() << " rejects buffer:"
-		<< buffer << " for stream:" << buffer->_d()->stream_;
+		<< buffer << " for stream:" << stream;
 
 	/*
 	 * \todo Not `FrameError` because that requires `timestamp` and
@@ -814,8 +816,8 @@ void Camera::Private::rejectBuffer(FrameBuffer *buffer)
 	buffer->_d()->cancel();
 	buffer->_d()->stream_ = nullptr;
 
-	// \todo separate event (with stream) ?
-	LIBCAMERA_O_PTR()->bufferCompleted.emit(nullptr, buffer);
+	// \todo separate event?
+	LIBCAMERA_O_PTR()->bufferCompleted.emit(nullptr, stream, buffer);
 }
 
 /**
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 755c78b308..27ce25ad11 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -421,20 +421,20 @@ void PipelineHandler::stop(Camera *camera)
 		doQueueRequest(request);
 	}
 
-	const auto returnBuffer = [&](FrameBuffer *buffer) {
+	const auto returnBuffer = [&](const Stream *stream, FrameBuffer *buffer) {
 		ASSERT(!buffer->_d()->stream_);
 		buffer->_d()->cancel();
-		camera->bufferCompleted.emit(nullptr, buffer);
+		camera->bufferCompleted.emit(nullptr, stream, buffer);
 	};
 
 	for (auto &pf : data->pendingFences_)
-		returnBuffer(pf.buffer);
+		returnBuffer(pf.stream, pf.buffer);
 
 	data->pendingFences_.clear();
 
 	for (auto &[stream, streamData] : data->streamData_) {
 		for (FrameBuffer *buffer : streamData.buffers)
-			returnBuffer(buffer);
+			returnBuffer(stream, buffer);
 
 		streamData.buffers.clear();
 	}
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index ecdf558066..4fb8c0a659 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -108,7 +108,8 @@ bool Request::Private::completeBuffer(FrameBuffer *buffer)
 	LIBCAMERA_TRACEPOINT(request_complete_buffer, this, buffer);
 
 	Request *request = LIBCAMERA_O_PTR();
-	auto it = request->bufferMap_.find(buffer->_d()->stream_);
+	const Stream *stream = buffer->_d()->stream_;
+	auto it = request->bufferMap_.find(stream);
 	ASSERT(it != request->bufferMap_.end());
 	ASSERT(it->second == buffer || !it->second);
 
@@ -122,7 +123,7 @@ bool Request::Private::completeBuffer(FrameBuffer *buffer)
 	if (buffer->metadata().status == FrameMetadata::FrameCancelled)
 		cancelled_ = true;
 
-	camera_->bufferCompleted.emit(request, buffer);
+	camera_->bufferCompleted.emit(request, stream, buffer);
 
 	return !hasPendingBuffers();
 }
diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp
index 5e271ad3d0..c6f35a3135 100644
--- a/test/camera/buffer_import.cpp
+++ b/test/camera/buffer_import.cpp
@@ -39,6 +39,7 @@ public:
 
 protected:
 	void bufferComplete([[maybe_unused]] Request *request,
+			    [[maybe_unused]] const Stream *stream,
 			    FrameBuffer *buffer)
 	{
 		if (buffer->metadata().status != FrameMetadata::FrameSuccess)
diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
index fabe297e53..bc8cf4c59d 100644
--- a/test/camera/capture.cpp
+++ b/test/camera/capture.cpp
@@ -35,6 +35,7 @@ protected:
 	unsigned int completeRequestsCount_;
 
 	void bufferComplete([[maybe_unused]] Request *request,
+			    [[maybe_unused]] const Stream *stream,
 			    FrameBuffer *buffer)
 	{
 		if (buffer->metadata().status != FrameMetadata::FrameSuccess)
