diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.cpp b/src/libcamera/pipeline/rpi/common/rpi_stream.cpp
index ee827a86b06a..20864aeed2d1 100644
--- a/src/libcamera/pipeline/rpi/common/rpi_stream.cpp
+++ b/src/libcamera/pipeline/rpi/common/rpi_stream.cpp
@@ -155,7 +155,7 @@ int Stream::queueBuffer(FrameBuffer *buffer)
 
 void Stream::returnBuffer(FrameBuffer *buffer)
 {
-	if (!(flags_ & StreamFlag::External)) {
+	if (!(flags_ & StreamFlag::External) && !(flags_ & StreamFlag::Recurrent)) {
 		/* For internal buffers, simply requeue back to the device. */
 		queueToDevice(buffer);
 		return;
@@ -217,7 +217,7 @@ int Stream::queueAllBuffers()
 {
 	int ret;
 
-	if (flags_ & StreamFlag::External)
+	if ((flags_ & StreamFlag::External) || (flags_ & StreamFlag::Recurrent))
 		return 0;
 
 	while (!availableBuffers_.empty()) {
diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.h b/src/libcamera/pipeline/rpi/common/rpi_stream.h
index 861e9c8e7dab..c5e35d134926 100644
--- a/src/libcamera/pipeline/rpi/common/rpi_stream.h
+++ b/src/libcamera/pipeline/rpi/common/rpi_stream.h
@@ -70,6 +70,17 @@ public:
 		 * to the pipeline handler when requested.
 		 */
 		RequiresMmap	= (1 << 2),
+		/*
+		 * Indicates a stream that needs buffers recycled every frame internally
+		 * in the pipeline handler, e.g. stitch, TDN, config. All buffer
+		 * management will be handled by the pipeline handler.
+		 */
+		Recurrent	= (1 << 3),
+		/*
+		 * Indicates that the output stream needs a software format conversion
+		 * to be applied after ISP processing.
+		 */
+		Needs32bitConv	= (1 << 4),
 	};
 
 	using StreamFlags = Flags<StreamFlag>;
