[libcamera-devel] [PATCH] libcamera: pipeline: rkisp1: Add internal request queue

Nícolas F. R. A. Prado nfraprado at collabora.com
Thu Jul 8 23:31:05 CEST 2021


Add an internal queue that stores requests until there are internal
buffers and V4L2 buffer slots available. This avoids the need to cancel
requests when there is a shortage of said buffers.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado at collabora.com>
---

This is very similar to what 5a9d19210fad ("libcamera: pipeline: ipu3: Try
queuing pending requests if a buffer is available") and 89dae5844964
("libcamera: pipeline: ipu3: Store requests in the case a buffer shortage") did
for IPU3. And also to the patch I sent for the uvcvideo pipeline [1].

I tested this with a new lc-compliance test from the series in [2]. The test
fails without this patch, and passes with it applied.

[1] https://lists.libcamera.org/pipermail/libcamera-devel/2021-July/022029.html
[2] https://lists.libcamera.org/pipermail/libcamera-devel/2021-July/022098.html

 src/libcamera/pipeline/rkisp1/rkisp1.cpp | 72 +++++++++++++++++++-----
 1 file changed, 58 insertions(+), 14 deletions(-)

diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 00df4f0b3e6b..84abb4c2a462 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -87,6 +87,8 @@ public:
 	}
 
 	int loadIPA(unsigned int hwRevision);
+	void queuePendingRequests();
+	void cancelPendingRequests();
 
 	Stream mainPathStream_;
 	Stream selfPathStream_;
@@ -101,6 +103,8 @@ public:
 
 	std::unique_ptr<ipa::rkisp1::IPAProxyRkISP1> ipa_;
 
+	std::queue<Request *> pendingRequests_;
+
 private:
 	void queueFrameAction(unsigned int frame,
 			      const ipa::rkisp1::RkISP1Action &action);
@@ -198,13 +202,13 @@ RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *req
 	unsigned int frame = data->frame_;
 
 	if (pipe_->availableParamBuffers_.empty()) {
-		LOG(RkISP1, Error) << "Parameters buffer underrun";
+		LOG(RkISP1, Debug) << "Parameters buffer underrun";
 		return nullptr;
 	}
 	FrameBuffer *paramBuffer = pipe_->availableParamBuffers_.front();
 
 	if (pipe_->availableStatBuffers_.empty()) {
-		LOG(RkISP1, Error) << "Statisitc buffer underrun";
+		LOG(RkISP1, Debug) << "Statistic buffer underrun";
 		return nullptr;
 	}
 	FrameBuffer *statBuffer = pipe_->availableStatBuffers_.front();
@@ -831,6 +835,8 @@ void PipelineHandlerRkISP1::stop(Camera *camera)
 
 	isp_->setFrameStartEnabled(false);
 
+	data->cancelPendingRequests();
+
 	data->ipa_->stop();
 
 	selfPath_.stop();
@@ -854,22 +860,58 @@ void PipelineHandlerRkISP1::stop(Camera *camera)
 	activeCamera_ = nullptr;
 }
 
-int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request)
+void RkISP1CameraData::cancelPendingRequests()
 {
-	RkISP1CameraData *data = cameraData(camera);
+	while (!pendingRequests_.empty()) {
+		Request *request = pendingRequests_.front();
 
-	RkISP1FrameInfo *info = data->frameInfo_.create(data, request);
-	if (!info)
-		return -ENOENT;
+		for (auto it : request->buffers()) {
+			FrameBuffer *buffer = it.second;
+			buffer->cancel();
+			pipe_->completeBuffer(request, buffer);
+		}
 
-	ipa::rkisp1::RkISP1Event ev;
-	ev.op = ipa::rkisp1::EventQueueRequest;
-	ev.frame = data->frame_;
-	ev.bufferId = info->paramBuffer->cookie();
-	ev.controls = request->controls();
-	data->ipa_->processEvent(ev);
+		pipe_->completeRequest(request);
+
+		pendingRequests_.pop();
+	}
+}
+
+void RkISP1CameraData::queuePendingRequests()
+{
+	while (!pendingRequests_.empty()) {
+		Request *request = pendingRequests_.front();
+
+		/*
+		 * If there aren't internal buffers available, we break and try
+		 * again later. If there are, we're guaranteed to also have V4L2
+		 * buffer slots available to queue the request, since we should
+		 * always have more (or equal) buffer slots than internal
+		 * buffers.
+		 */
+		RkISP1FrameInfo *info = frameInfo_.create(this, request);
+		if (!info)
+			break;
+
+		ipa::rkisp1::RkISP1Event ev;
+		ev.op = ipa::rkisp1::EventQueueRequest;
+		ev.frame = frame_;
+		ev.bufferId = info->paramBuffer->cookie();
+		ev.controls = request->controls();
+		ipa_->processEvent(ev);
 
-	data->frame_++;
+		frame_++;
+
+		pendingRequests_.pop();
+	}
+}
+
+int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request)
+{
+	RkISP1CameraData *data = cameraData(camera);
+
+	data->pendingRequests_.push(request);
+	data->queuePendingRequests();
 
 	return 0;
 }
@@ -1065,6 +1107,8 @@ void PipelineHandlerRkISP1::tryCompleteRequest(Request *request)
 	data->frameInfo_.destroy(info->frame);
 
 	completeRequest(request);
+
+	data->queuePendingRequests();
 }
 
 void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer)
-- 
2.32.0



More information about the libcamera-devel mailing list