From 73e5102ad4ce3e8984115c5e1f524f34fa645ed5 Mon Sep 17 00:00:00 2001
From: Naushir Patuck <naush@raspberrypi.com>
Date: Mon, 7 Feb 2022 15:12:12 +0000
Subject: pipeline: raspberrypi: Allow Stream::returnBuffer() to handle
 internal buffers

If Stream::returnBuffer() gets passed an internally allocated buffer, it now
simply re-queues it back to the device. With this change, the pipeline handler
code can be simplified slightly as it does not need multiple code paths for
internally allocated and non-internally allocated buffers.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 55 ++++++++++------------
 src/libcamera/pipeline/raspberrypi/rpi_stream.cpp  |  7 ++-
 2 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index 49af56ed..0826d3d9 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -1877,34 +1877,31 @@ void RPiCameraData::clearIncompleteRequests()
 
 void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, RPi::Stream *stream)
 {
-	if (stream->isExternal()) {
+	/*
+	 * It is possible to be here without a pending request, so check
+	 * that we actually have one to action, otherwise we just return
+	 * buffer back to the stream.
+	 */
+	Request *request = requestQueue_.empty() ? nullptr : requestQueue_.front();
+	if (!dropFrameCount_ && request && request->findBuffer(stream) == buffer) {
 		/*
-		 * It is possible to be here without a pending request, so check
-		 * that we actually have one to action, otherwise we just return
-		 * buffer back to the stream.
+		 * Check if this is an externally provided buffer, and if
+		 * so, we must stop tracking it in the pipeline handler.
 		 */
-		Request *request = requestQueue_.empty() ? nullptr : requestQueue_.front();
-		if (!dropFrameCount_ && request && request->findBuffer(stream) == buffer) {
-			/*
-			 * Check if this is an externally provided buffer, and if
-			 * so, we must stop tracking it in the pipeline handler.
-			 */
-			handleExternalBuffer(buffer, stream);
-			/*
-			 * Tag the buffer as completed, returning it to the
-			 * application.
-			 */
-			pipe()->completeBuffer(request, buffer);
-		} else {
-			/*
-			 * This buffer was not part of the Request, or there is no
-			 * pending request, so we can recycle it.
-			 */
-			stream->returnBuffer(buffer);
-		}
+		handleExternalBuffer(buffer, stream);
+		/*
+		 * Tag the buffer as completed, returning it to the
+		 * application.
+		 */
+		pipe()->completeBuffer(request, buffer);
 	} else {
-		/* Simply re-queue the buffer to the requested stream. */
-		stream->queueBuffer(buffer);
+		/*
+		 * This buffer was not part of the Request (which happens if an
+		 * internal buffer was used for an external stream, or
+		 * unconditionally for internal streams), or there is no pending
+		 * request, so we can recycle it.
+		 */
+		stream->returnBuffer(buffer);
 	}
 }
 
@@ -2104,7 +2101,7 @@ bool RPiCameraData::findMatchingBuffers(BayerFrame &bayerFrame, FrameBuffer *&em
 			FrameBuffer *b = embeddedQueue_.front();
 			if (!unicam_[Unicam::Embedded].isExternal() && b->metadata().timestamp < ts) {
 				embeddedQueue_.pop();
-				unicam_[Unicam::Embedded].queueBuffer(b);
+				unicam_[Unicam::Embedded].returnBuffer(b);
 				embeddedRequeueCount++;
 				LOG(RPI, Warning) << "Dropping unmatched input frame in stream "
 						  << unicam_[Unicam::Embedded].name();
@@ -2140,7 +2137,7 @@ bool RPiCameraData::findMatchingBuffers(BayerFrame &bayerFrame, FrameBuffer *&em
 				 * the front of the queue. This buffer is now orphaned, so requeue
 				 * it back to the device.
 				 */
-				unicam_[Unicam::Image].queueBuffer(bayerQueue_.front().buffer);
+				unicam_[Unicam::Image].returnBuffer(bayerQueue_.front().buffer);
 				bayerQueue_.pop();
 				bayerRequeueCount++;
 				LOG(RPI, Warning) << "Dropping unmatched input frame in stream "
@@ -2158,7 +2155,7 @@ bool RPiCameraData::findMatchingBuffers(BayerFrame &bayerFrame, FrameBuffer *&em
 
 				LOG(RPI, Warning) << "Flushing bayer stream!";
 				while (!bayerQueue_.empty()) {
-					unicam_[Unicam::Image].queueBuffer(bayerQueue_.front().buffer);
+					unicam_[Unicam::Image].returnBuffer(bayerQueue_.front().buffer);
 					bayerQueue_.pop();
 				}
 				flushedBuffers = true;
@@ -2175,7 +2172,7 @@ bool RPiCameraData::findMatchingBuffers(BayerFrame &bayerFrame, FrameBuffer *&em
 
 				LOG(RPI, Warning) << "Flushing embedded data stream!";
 				while (!embeddedQueue_.empty()) {
-					unicam_[Unicam::Embedded].queueBuffer(embeddedQueue_.front());
+					unicam_[Unicam::Embedded].returnBuffer(embeddedQueue_.front());
 					embeddedQueue_.pop();
 				}
 				flushedBuffers = true;
diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp
index a421ad09..f446e1ce 100644
--- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp
+++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp
@@ -163,8 +163,11 @@ int Stream::queueBuffer(FrameBuffer *buffer)
 
 void Stream::returnBuffer(FrameBuffer *buffer)
 {
-	/* This can only be called for external streams. */
-	ASSERT(external_);
+	if (!external_) {
+		/* For internal buffers, simply requeue back to the device. */
+		queueToDevice(buffer);
+		return;
+	}
 
 	/* Push this buffer back into the queue to be used again. */
 	availableBuffers_.push(buffer);
-- 
cgit v1.2.1