From patchwork Thu Jul 8 21:31:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= X-Patchwork-Id: 12871 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A8B04C3224 for ; Thu, 8 Jul 2021 21:31:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 17ECE68513; Thu, 8 Jul 2021 23:31:25 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB60168506 for ; Thu, 8 Jul 2021 23:31:23 +0200 (CEST) Received: from localhost.localdomain (unknown [IPv6:2804:14c:1a9:2434:6553:ad0c:9d2a:24db]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: nfraprado) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 111B91F44064; Thu, 8 Jul 2021 22:31:21 +0100 (BST) From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Thu, 8 Jul 2021 18:31:05 -0300 Message-Id: <20210708213105.1485393-1-nfraprado@collabora.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH] libcamera: pipeline: rkisp1: Add internal request queue X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kernel@collabora.com, =?utf-8?q?Andr=C3=A9_Almeida?= Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- 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_; + std::queue 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)