From patchwork Mon Jul 19 19:14:36 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: 13045 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 2D914C322B for ; Mon, 19 Jul 2021 19:14:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ECE5068539; Mon, 19 Jul 2021 21:14:58 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 239A368539 for ; Mon, 19 Jul 2021 21:14:57 +0200 (CEST) Received: from localhost.localdomain (unknown [IPv6:2804:14c:1a9:2434:2e2f:cb19:fca8:1dff]) (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 949251F42E0E; Mon, 19 Jul 2021 20:14:55 +0100 (BST) From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Mon, 19 Jul 2021 16:14:36 -0300 Message-Id: <20210719191438.189046-2-nfraprado@collabora.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210719191438.189046-1-nfraprado@collabora.com> References: <20210719191438.189046-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/3] libcamera: pipeline: vimc: 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 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 --- src/libcamera/pipeline/vimc/vimc.cpp | 65 +++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index a698427c4361..c9092bec9a74 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,9 @@ public: int init(); void bufferReady(FrameBuffer *buffer); + void queuePendingRequests(); + void cancelPendingRequests(); + MediaDevice *media_; std::unique_ptr sensor_; std::unique_ptr debayer_; @@ -62,6 +66,8 @@ public: Stream stream_; std::unique_ptr ipa_; + + std::queue pendingRequests_; }; class VimcCameraConfiguration : public CameraConfiguration @@ -94,9 +100,9 @@ public: bool match(DeviceEnumerator *enumerator) override; -private: int processControls(VimcCameraData *data, Request *request); +private: VimcCameraData *cameraData(const Camera *camera) { return static_cast( @@ -335,6 +341,7 @@ int PipelineHandlerVimc::start(Camera *camera, [[maybe_unused]] const ControlLis void PipelineHandlerVimc::stop(Camera *camera) { VimcCameraData *data = cameraData(camera); + data->cancelPendingRequests(); data->video_->streamOff(); data->ipa_->stop(); data->video_->releaseBuffers(); @@ -383,21 +390,16 @@ int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request) int PipelineHandlerVimc::queueRequestDevice(Camera *camera, Request *request) { VimcCameraData *data = cameraData(camera); - FrameBuffer *buffer = request->findBuffer(&data->stream_); - if (!buffer) { + + if (!request->findBuffer(&data->stream_)) { LOG(VIMC, Error) << "Attempt to queue request with invalid stream"; return -ENOENT; } - int ret = processControls(data, request); - if (ret < 0) - return ret; - - ret = data->video_->queueBuffer(buffer); - if (ret < 0) - return ret; + data->pendingRequests_.push(request); + data->queuePendingRequests(); return 0; } @@ -531,6 +533,49 @@ void VimcCameraData::bufferReady(FrameBuffer *buffer) pipe_->completeBuffer(request, buffer); pipe_->completeRequest(request); + + queuePendingRequests(); +} + +void VimcCameraData::queuePendingRequests() +{ + PipelineHandlerVimc *pipe = static_cast(pipe_); + + while (!pendingRequests_.empty()) { + Request *request = pendingRequests_.front(); + FrameBuffer *buffer = request->findBuffer(&stream_); + + int ret = pipe->processControls(this, request); + if (ret < 0) { + buffer->cancel(); + pipe_->completeBuffer(request, buffer); + pipe_->completeRequest(request); + pendingRequests_.pop(); + + continue; + } + + /* If we're missing V4L2 buffer slots, try again later */ + ret = video_->queueBuffer(buffer); + if (ret < 0) + break; + + pendingRequests_.pop(); + } +} + +void VimcCameraData::cancelPendingRequests() +{ + while (!pendingRequests_.empty()) { + Request *request = pendingRequests_.front(); + FrameBuffer *buffer = request->findBuffer(&stream_); + + buffer->cancel(); + pipe_->completeBuffer(request, buffer); + pipe_->completeRequest(request); + + pendingRequests_.pop(); + } } REGISTER_PIPELINE_HANDLER(PipelineHandlerVimc) From patchwork Mon Jul 19 19:14:37 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: 13046 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 857D4C322B for ; Mon, 19 Jul 2021 19:15:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4315D6853F; Mon, 19 Jul 2021 21:15:01 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5AB6868538 for ; Mon, 19 Jul 2021 21:14:59 +0200 (CEST) Received: from localhost.localdomain (unknown [IPv6:2804:14c:1a9:2434:2e2f:cb19:fca8:1dff]) (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 993381F42E0E; Mon, 19 Jul 2021 20:14:57 +0100 (BST) From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Mon, 19 Jul 2021 16:14:37 -0300 Message-Id: <20210719191438.189046-3-nfraprado@collabora.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210719191438.189046-1-nfraprado@collabora.com> References: <20210719191438.189046-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/3] libcamera: pipeline: uvcvideo: 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 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 --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 66 +++++++++++++++++--- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 32482300f09a..a5b593473cb3 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -45,8 +46,13 @@ public: ControlInfoMap::Map *ctrls); void bufferReady(FrameBuffer *buffer); + void queuePendingRequests(); + void cancelPendingRequests(); + std::unique_ptr video_; Stream stream_; + + std::queue pendingRequests_; }; class UVCCameraConfiguration : public CameraConfiguration @@ -79,12 +85,13 @@ public: bool match(DeviceEnumerator *enumerator) override; + int processControls(UVCCameraData *data, Request *request); + private: std::string generateId(const UVCCameraData *data); int processControl(ControlList *controls, unsigned int id, const ControlValue &value); - int processControls(UVCCameraData *data, Request *request); UVCCameraData *cameraData(const Camera *camera) { @@ -252,6 +259,7 @@ int PipelineHandlerUVC::start(Camera *camera, [[maybe_unused]] const ControlList void PipelineHandlerUVC::stop(Camera *camera) { UVCCameraData *data = cameraData(camera); + data->cancelPendingRequests(); data->video_->streamOff(); data->video_->releaseBuffers(); } @@ -365,21 +373,16 @@ int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request) int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request) { UVCCameraData *data = cameraData(camera); - FrameBuffer *buffer = request->findBuffer(&data->stream_); - if (!buffer) { + + if (!request->findBuffer(&data->stream_)) { LOG(UVC, Error) << "Attempt to queue request with invalid stream"; return -ENOENT; } - int ret = processControls(data, request); - if (ret < 0) - return ret; - - ret = data->video_->queueBuffer(buffer); - if (ret < 0) - return ret; + data->pendingRequests_.push(request); + data->queuePendingRequests(); return 0; } @@ -669,6 +672,49 @@ void UVCCameraData::bufferReady(FrameBuffer *buffer) pipe_->completeBuffer(request, buffer); pipe_->completeRequest(request); + + queuePendingRequests(); +} + +void UVCCameraData::queuePendingRequests() +{ + PipelineHandlerUVC *pipe = static_cast(pipe_); + + while (!pendingRequests_.empty()) { + Request *request = pendingRequests_.front(); + FrameBuffer *buffer = request->findBuffer(&stream_); + + int ret = pipe->processControls(this, request); + if (ret < 0) { + buffer->cancel(); + pipe_->completeBuffer(request, buffer); + pipe_->completeRequest(request); + pendingRequests_.pop(); + + continue; + } + + /* If we're missing V4L2 buffer slots, try again later */ + ret = video_->queueBuffer(buffer); + if (ret < 0) + break; + + pendingRequests_.pop(); + } +} + +void UVCCameraData::cancelPendingRequests() +{ + while (!pendingRequests_.empty()) { + Request *request = pendingRequests_.front(); + FrameBuffer *buffer = request->findBuffer(&stream_); + + buffer->cancel(); + pipe_->completeBuffer(request, buffer); + pipe_->completeRequest(request); + + pendingRequests_.pop(); + } } REGISTER_PIPELINE_HANDLER(PipelineHandlerUVC) From patchwork Mon Jul 19 19:14:38 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: 13047 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 AF1B0C322C for ; Mon, 19 Jul 2021 19:15:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7787B6853D; Mon, 19 Jul 2021 21:15:02 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 59B2668542 for ; Mon, 19 Jul 2021 21:15:01 +0200 (CEST) Received: from localhost.localdomain (unknown [IPv6:2804:14c:1a9:2434:2e2f:cb19:fca8:1dff]) (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 B03291F42E0E; Mon, 19 Jul 2021 20:14:59 +0100 (BST) From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Mon, 19 Jul 2021 16:14:38 -0300 Message-Id: <20210719191438.189046-4-nfraprado@collabora.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210719191438.189046-1-nfraprado@collabora.com> References: <20210719191438.189046-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/3] 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 Reviewed-by: Laurent Pinchart --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 73 +++++++++++++++++++----- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index f4ea2fd4d4d0..f1c75b7d37c5 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -89,6 +89,9 @@ public: int loadIPA(unsigned int hwRevision); + void queuePendingRequests(); + void cancelPendingRequests(); + Stream mainPathStream_; Stream selfPathStream_; std::unique_ptr sensor_; @@ -102,6 +105,8 @@ public: std::unique_ptr ipa_; + std::queue pendingRequests_; + private: void queueFrameAction(unsigned int frame, const ipa::rkisp1::RkISP1Action &action); @@ -199,13 +204,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(); @@ -373,6 +378,52 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta pipe->tryCompleteRequest(info->request); } +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); + + frame_++; + + pendingRequests_.pop(); + } +} + +void RkISP1CameraData::cancelPendingRequests() +{ + while (!pendingRequests_.empty()) { + Request *request = pendingRequests_.front(); + + for (auto it : request->buffers()) { + FrameBuffer *buffer = it.second; + buffer->cancel(); + pipe_->completeBuffer(request, buffer); + } + + pipe_->completeRequest(request); + + pendingRequests_.pop(); + } +} + RkISP1CameraConfiguration::RkISP1CameraConfiguration(Camera *camera, RkISP1CameraData *data) : CameraConfiguration() @@ -827,6 +878,8 @@ void PipelineHandlerRkISP1::stop(Camera *camera) isp_->setFrameStartEnabled(false); + data->cancelPendingRequests(); + data->ipa_->stop(); selfPath_.stop(); @@ -854,18 +907,8 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) { RkISP1CameraData *data = cameraData(camera); - RkISP1FrameInfo *info = data->frameInfo_.create(data, request); - if (!info) - return -ENOENT; - - 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); - - data->frame_++; + data->pendingRequests_.push(request); + data->queuePendingRequests(); return 0; } @@ -1062,6 +1105,8 @@ void PipelineHandlerRkISP1::tryCompleteRequest(Request *request) data->frameInfo_.destroy(info->frame); completeRequest(request); + + data->queuePendingRequests(); } void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer)