[libcamera-devel] [PATCH] pipeline: ipu3: Store requests in the case a buffer shortage

Hirokazu Honda hiroh at chromium.org
Wed Mar 31 10:45:39 CEST 2021


PipelineHandlerIPU3 returns -ENOBUFS and -ENOMEM on queueing a
request when there are not sufficient buffers for the request.
Since the request will be successful if it is queued later when
enough buffers are available. The requests failed due to a buffer
shortage should be stored and retried later in the FIFO order.
This introduces the queue in PipelineHandlerIPU3 to do that.

Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
---
 src/libcamera/pipeline/ipu3/ipu3.cpp | 62 ++++++++++++++++++----------
 1 file changed, 41 insertions(+), 21 deletions(-)

diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 519cad4f..71dd311f 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -153,12 +153,16 @@ private:
 	int allocateBuffers(Camera *camera);
 	int freeBuffers(Camera *camera);
 
+	int queuePendingRequests();
+
 	ImgUDevice imgu0_;
 	ImgUDevice imgu1_;
 	MediaDevice *cio2MediaDev_;
 	MediaDevice *imguMediaDev_;
 
 	std::vector<IPABuffer> ipaBuffers_;
+
+	std::queue<std::pair<IPU3CameraData *, Request *>> pendingRequests_;
 };
 
 IPU3CameraConfiguration::IPU3CameraConfiguration(IPU3CameraData *data)
@@ -764,6 +768,8 @@ void PipelineHandlerIPU3::stop(Camera *camera)
 	IPU3CameraData *data = cameraData(camera);
 	int ret = 0;
 
+	pendingRequests_ = {};
+
 	data->ipa_->stop();
 
 	ret |= data->imgu_->stop();
@@ -774,36 +780,50 @@ void PipelineHandlerIPU3::stop(Camera *camera)
 	freeBuffers(camera);
 }
 
-int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
+int PipelineHandlerIPU3::queuePendingRequests()
 {
-	IPU3CameraData *data = cameraData(camera);
+	while (!pendingRequests_.empty()) {
+		IPU3CameraData *data = pendingRequests_.front().first;
+		Request *request = pendingRequests_.front().second;
 
-	IPU3Frames::Info *info = data->frameInfos_.create(request);
-	if (!info)
-		return -ENOBUFS;
+		IPU3Frames::Info *info = data->frameInfos_.create(request);
+		if (!info)
+			break;
 
-	/*
-	 * Queue a buffer on the CIO2, using the raw stream buffer provided in
-	 * the request, if any, or a CIO2 internal buffer otherwise.
-	 */
-	FrameBuffer *reqRawBuffer = request->findBuffer(&data->rawStream_);
-	FrameBuffer *rawBuffer = data->cio2_.queueBuffer(request, reqRawBuffer);
-	if (!rawBuffer) {
-		data->frameInfos_.remove(info);
-		return -ENOMEM;
-	}
+		/*
+		 * Queue a buffer on the CIO2, using the raw stream buffer
+		 * provided in the request, if any, or a CIO2 internal buffer
+		 * otherwise.
+		 */
+		FrameBuffer *reqRawBuffer = request->findBuffer(&data->rawStream_);
+		FrameBuffer *rawBuffer = data->cio2_.queueBuffer(request, reqRawBuffer);
+		if (!rawBuffer) {
+			data->frameInfos_.remove(info);
+			break;
+		}
 
-	info->rawBuffer = rawBuffer;
+		info->rawBuffer = rawBuffer;
 
-	ipa::ipu3::IPU3Event ev;
-	ev.op = ipa::ipu3::EventProcessControls;
-	ev.frame = info->id;
-	ev.controls = request->controls();
-	data->ipa_->processEvent(ev);
+		ipa::ipu3::IPU3Event ev;
+		ev.op = ipa::ipu3::EventProcessControls;
+		ev.frame = info->id;
+		ev.controls = request->controls();
+		data->ipa_->processEvent(ev);
+
+		pendingRequests_.pop();
+	}
 
 	return 0;
 }
 
+int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
+{
+	IPU3CameraData *data = cameraData(camera);
+
+	pendingRequests_.emplace(data, request);
+	return queuePendingRequests();
+}
+
 bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
 {
 	int ret;
-- 
2.31.0.291.g576ba9dcdaf-goog



More information about the libcamera-devel mailing list