From patchwork Tue Feb 20 16:43:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 19512 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 F10F9C3257 for ; Tue, 20 Feb 2024 16:43:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6EFFE6281C; Tue, 20 Feb 2024 17:43:26 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="dLh35uea"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E6D8E61CAA for ; Tue, 20 Feb 2024 17:43:23 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 87B7C14B0; Tue, 20 Feb 2024 17:43:16 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1708447396; bh=W49fGUKG1FUnRBidXbw5IYfpuQeRo7bpjnz3RT9D1SI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dLh35ueaagZ2j4fkDgRb1Jz9Tndp1JUICunH4RFkn5LdNeyYIq99+rWnTClnShkl0 k4ppDPbmeC1LTmL6jFT0m4aI6R8i3NJNJG0gvNrpwaryhs4SybJXKI9X8bfHyAdMwj WqLm+sgavUOk10CBGJdGZ7fhccwLOgyBG5QZP2X0= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 1/7] libcamera: request: Introduce internal buffers Date: Tue, 20 Feb 2024 16:43:11 +0000 Message-Id: <20240220164317.998477-2-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240220164317.998477-1-dan.scally@ideasonboard.com> References: <20240220164317.998477-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" To simplify Pipeline Handler code designed to track whether a Request is ready to be returned to the application or not, extend Request::Private with the concept of internal buffers. These can be added to a Request::Private and associated with a role, for which a new enumeration holds descriptors. Internal buffers added to a Request in this way count towards pending buffers and so will cause hasPendingBuffers() to return false until they are also completed. This necessitates a checks before emiting the bufferCompleted signal to confirm that the buffer under consideration is associated with a Stream rather than a purely-internal buffer. Signed-off-by: Daniel Scally --- Changes in v2: - New patch, previously this was just done via the inFlightStatsBuffers map in the RkISP1 pipeline handler. include/libcamera/internal/request.h | 12 ++++ src/libcamera/pipeline_handler.cpp | 9 ++- src/libcamera/request.cpp | 93 +++++++++++++++++++++++++++- 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h index 3454cf5a..03ccc7e5 100644 --- a/include/libcamera/internal/request.h +++ b/include/libcamera/internal/request.h @@ -31,9 +31,20 @@ public: Private(Camera *camera); ~Private(); + enum InternalStream { + Parameters, + Statistics, + Mem2Mem, + }; + + using InternalBufferMap = std::map; + Camera *camera() const { return camera_; } bool hasPendingBuffers() const; + const InternalBufferMap &internalBuffers() const { return internalBufferMap_; } + int addInternalBuffer(InternalStream stream, FrameBuffer *buffer); + FrameBuffer *findInternalBuffer(InternalStream stream); bool completeBuffer(FrameBuffer *buffer); void complete(); void cancel(); @@ -59,6 +70,7 @@ private: std::unordered_set pending_; std::map> notifiers_; std::unique_ptr timer_; + InternalBufferMap internalBufferMap_; }; } /* namespace libcamera */ diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 29e0c98a..343804e9 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -499,7 +499,14 @@ void PipelineHandler::doQueueRequests() bool PipelineHandler::completeBuffer(Request *request, FrameBuffer *buffer) { Camera *camera = request->_d()->camera(); - camera->bufferCompleted.emit(request, buffer); + + for (auto pair : request->buffers()) { + if (pair.second == buffer) { + camera->bufferCompleted.emit(request, buffer); + break; + } + } + return request->_d()->completeBuffer(buffer); } diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp index 949c556f..3b852f7b 100644 --- a/src/libcamera/request.cpp +++ b/src/libcamera/request.cpp @@ -57,6 +57,22 @@ Request::Private::~Private() doCancelRequest(); } +/** + * \enum Request::Private::InternalStream + * Internal stream identifiers + * \var Request::Private::Parameters + * The stream relates to ISP parameters + * \var Request::Private::Statistics + * The stream relates to ISP statistics + * \var Request::Private::Mem2Mem + * The stream relates to memory-to-memory mode operation + */ + +/** + * \typedef Request::Private::InternalBufferMap + * \brief A map of InternalStream to FrameBuffer pointers + */ + /** * \fn Request::Private::camera() * \brief Retrieve the camera this request has been queued to @@ -75,6 +91,72 @@ bool Request::Private::hasPendingBuffers() const return !pending_.empty(); } +/** + * \fn Request::Private::internalBuffers + * \brief Retrieve the Request::Private's InternalStreams to buffers map + * + * Return a reference to the map that associates each InternalStream to the + * FrameBuffer it uses. + * + * \return The map of InternalStream to FrameBuffer + */ + +/** + * \brief Add a FrameBuffer to a Request for an InternalStream + * \param[in] stream The InternalStream the buffer is used for + * \param[in] buffer The FrameBuffer to add to the request + * + * A reference to the buffer is stored in the request. The caller is responsible + * for ensuring that the buffer will remain valid until the request complete + * callback is called. + * + * A request can only contain one buffer per InternalStream. If a buffer has + * already been added to the request for the same InternalStream, this function + * returns -EEXIST. + * + * \return 0 on success or a negative error code otherwise + * \retval -EEXIST The request already contains a buffer for the stream + */ +int Request::Private::addInternalBuffer(InternalStream stream, FrameBuffer *buffer) +{ + auto it = internalBufferMap_.find(stream); + if (it != internalBufferMap_.end()) { + LOG(Request, Error) + << "FrameBuffer already set for internal stream"; + return -EEXIST; + } + + buffer->_d()->setRequest(_o()); + pending_.insert(buffer); + internalBufferMap_[stream] = buffer; + + return 0; +} + +/** + * \var Request::Private::internalBufferMap_ + * \brief Mapping of private buffer streams to buffers for this request + * + * The internalBufferMap_ tracks the buffers associated with each internal + * buffer stream. If a stream is not utilised in this request there will be no + * buffer for that stream in the map. + */ + +/** + * \brief Return the buffer associated with a stream + * \param[in] stream The \ref InternalStream the buffer is associated to + * \return The buffer associated with the stream, or nullptr if the stream is + * not part of this request + */ +FrameBuffer *Request::Private::findInternalBuffer(InternalStream stream) +{ + auto it = internalBufferMap_.find(stream); + if (it == internalBufferMap_.end()) + return nullptr; + + return it->second; +} + /** * \brief Complete a buffer for the request * \param[in] buffer The buffer that has completed @@ -130,7 +212,14 @@ void Request::Private::doCancelRequest() for (FrameBuffer *buffer : pending_) { buffer->_d()->cancel(); - camera_->bufferCompleted.emit(request, buffer); + + for (auto pair : request->bufferMap_) { + if (pair.second == buffer) { + camera_->bufferCompleted.emit(request, buffer); + + break; + } + } } cancelled_ = true; @@ -395,6 +484,8 @@ void Request::reuse(ReuseFlag flags) bufferMap_.clear(); } + _d()->internalBufferMap_.clear(); + status_ = RequestPending; controls_->clear(); From patchwork Tue Feb 20 16:43:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 19513 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 CBA05C3261 for ; Tue, 20 Feb 2024 16:43:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0F84962820; Tue, 20 Feb 2024 17:43:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="YpeuKOCF"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6425A61CAA for ; Tue, 20 Feb 2024 17:43:24 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 01EA913AC; Tue, 20 Feb 2024 17:43:16 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1708447397; bh=R4kXQda0HMfbVXX1PAGOXI0OdPf6pPixlt799u6rYJM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YpeuKOCFXnr7EI81DYYV0TKc6ICSRGYfB1mzZvAgSGUlp6C09yZEMn/AS0LNt6mLx NWIB4kLVnW10JeDmU+/PI5J1AgbXWyZfyS4/neDrW0rF1VCKAqnyhwqxzD+5aVaHxu IogUxpoSfsmjm83dTOvbc9NOvHHEGYdnbXHB8zy0= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 2/7] libcamera: camera: Turn queuedRequests_ to a map Date: Tue, 20 Feb 2024 16:43:12 +0000 Message-Id: <20240220164317.998477-3-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240220164317.998477-1-dan.scally@ideasonboard.com> References: <20240220164317.998477-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" To facilitate fetching Requests queued to a camera using their sequence number, transform the queuedRequests_ list to a map with the sequence as the key. Signed-off-by: Daniel Scally --- Changes in v2: - New patch include/libcamera/internal/camera.h | 4 ++-- src/libcamera/camera.cpp | 4 ++-- src/libcamera/pipeline_handler.cpp | 12 ++++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/libcamera/internal/camera.h b/include/libcamera/internal/camera.h index 38dd94ff..fff70ff6 100644 --- a/include/libcamera/internal/camera.h +++ b/include/libcamera/internal/camera.h @@ -8,7 +8,7 @@ #pragma once #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ public: PipelineHandler *pipe() { return pipe_.get(); } - std::list queuedRequests_; + std::map queuedRequests_; ControlInfoMap controlInfo_; ControlList properties_; diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index a71dc933..3aa051f9 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -601,9 +601,9 @@ Camera::Private::~Private() /** * \var Camera::Private::queuedRequests_ - * \brief The list of queued and not yet completed requests + * \brief The map of queued and not yet completed requests * - * This list tracks requests queued in order to ensure completion of all + * This map tracks requests queued in order to ensure completion of all * requests when the pipeline handler is stopped. * * \sa PipelineHandler::queueRequest(), PipelineHandler::stop(), diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 343804e9..a8a67a7d 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -428,9 +428,9 @@ void PipelineHandler::doQueueRequest(Request *request) Camera *camera = request->_d()->camera(); Camera::Private *data = camera->_d(); - data->queuedRequests_.push_back(request); request->_d()->sequence_ = data->requestSequence_++; + data->queuedRequests_[request->sequence()] = request; if (request->_d()->cancelled_) { completeRequest(request); @@ -532,13 +532,17 @@ void PipelineHandler::completeRequest(Request *request) Camera::Private *data = camera->_d(); - while (!data->queuedRequests_.empty()) { - Request *req = data->queuedRequests_.front(); + for (auto it = data->queuedRequests_.begin(), it_next = it; + it != data->queuedRequests_.end(); it = it_next) { + uint32_t seq = it->first; + Request *req = it->second; + ++it_next; + if (req->status() == Request::RequestPending) break; ASSERT(!req->hasPendingBuffers()); - data->queuedRequests_.pop_front(); + data->queuedRequests_.erase(seq); camera->requestComplete(req); } } From patchwork Tue Feb 20 16:43:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 19514 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 55355C32C3 for ; Tue, 20 Feb 2024 16:43:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D54516281B; Tue, 20 Feb 2024 17:43:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="HAcgv9SR"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D453D61CAA for ; Tue, 20 Feb 2024 17:43:24 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 72A0F14B0; Tue, 20 Feb 2024 17:43:17 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1708447397; bh=aFGqaUW3ZkJPRpocov+lqEFRvBqZ4KIdRpuExSdhOXU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HAcgv9SRYfpx8e7GzRFGYwa881BTr4JVxHadMKpbpxvJaL8Mo6yl+GitmlQNyuhyh G5LPBmT8AD9XinF4uLSiHk8RTmO33fV+ieWGcQ938vT7FhobHxc26pH/btrqfLQLmb 53ZPaHObS+kZYyyP2Ou53NCqx+6SctiAazis8+fE= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 3/7] libcamera: rkisp1: Track request->sequence() instead of frame_ Date: Tue, 20 Feb 2024 16:43:13 +0000 Message-Id: <20240220164317.998477-4-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240220164317.998477-1-dan.scally@ideasonboard.com> References: <20240220164317.998477-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The rkisp1 pipeline handler currently tries to track the frame number from V4L2 to provide an index to the IPA module's FCQueue - this is not necessary, the Request's sequence does the same job perfectly well. Note that the association of controls and calculated parameters with specific frames is not affected here - the parameters are always applied based on the most recently processed statistics, and the applied controls are fetched separately using the V4L2 provided buffer->metadata().sequence, which value is also internally tracked by DelayedControls. Signed-off-by: Daniel Scally --- Changes in v2: - In statReady() I no longer used request->sequence() to fetch from delayedCtrls_ - ensuring that we only use the V4L2 reported sequence there. src/libcamera/pipeline/rkisp1/rkisp1.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 586b46d6..d926c83c 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -88,7 +88,7 @@ class RkISP1CameraData : public Camera::Private public: RkISP1CameraData(PipelineHandler *pipe, RkISP1MainPath *mainPath, RkISP1SelfPath *selfPath) - : Camera::Private(pipe), frame_(0), frameInfo_(pipe), + : Camera::Private(pipe), frameInfo_(pipe), mainPath_(mainPath), selfPath_(selfPath) { } @@ -100,7 +100,6 @@ public: Stream selfPathStream_; std::unique_ptr sensor_; std::unique_ptr delayedCtrls_; - unsigned int frame_; std::vector ipaBuffers_; RkISP1Frames frameInfo_; @@ -214,7 +213,7 @@ RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *request, bool isRaw) { - unsigned int frame = data->frame_; + unsigned int frame = request->sequence(); FrameBuffer *paramBuffer = nullptr; FrameBuffer *statBuffer = nullptr; @@ -235,6 +234,7 @@ RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *req statBuffer = pipe_->availableStatBuffers_.front(); pipe_->availableStatBuffers_.pop(); + statBuffer->_d()->setRequest(request); } FrameBuffer *mainPathBuffer = request->findBuffer(&data->mainPathStream_); @@ -935,8 +935,6 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL return ret; } - data->frame_ = 0; - if (!isRaw_) { ret = param_->streamOn(); if (ret) { @@ -1028,7 +1026,7 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) if (!info) return -ENOENT; - data->ipa_->queueRequest(data->frame_, request->controls()); + data->ipa_->queueRequest(request->sequence(), request->controls()); if (isRaw_) { if (info->mainPathBuffer) data->mainPath_->queueBuffer(info->mainPathBuffer); @@ -1036,12 +1034,10 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) if (data->selfPath_ && info->selfPathBuffer) data->selfPath_->queueBuffer(info->selfPathBuffer); } else { - data->ipa_->fillParamsBuffer(data->frame_, + data->ipa_->fillParamsBuffer(request->sequence(), info->paramBuffer->cookie()); } - data->frame_++; - return 0; } @@ -1276,7 +1272,8 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) if (isRaw_) { const ControlList &ctrls = data->delayedCtrls_->get(metadata.sequence); - data->ipa_->processStatsBuffer(info->frame, 0, ctrls); + data->ipa_->processStatsBuffer(request->sequence(), + 0, ctrls); } } else { if (isRaw_) @@ -1304,6 +1301,7 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) { ASSERT(activeCamera_); RkISP1CameraData *data = cameraData(activeCamera_); + Request *request = buffer->request(); RkISP1FrameInfo *info = data->frameInfo_.find(buffer); if (!info) @@ -1315,10 +1313,7 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) return; } - if (data->frame_ <= buffer->metadata().sequence) - data->frame_ = buffer->metadata().sequence + 1; - - data->ipa_->processStatsBuffer(info->frame, info->statBuffer->cookie(), + data->ipa_->processStatsBuffer(request->sequence(), info->statBuffer->cookie(), data->delayedCtrls_->get(buffer->metadata().sequence)); } From patchwork Tue Feb 20 16:43:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 19515 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 A3622C3257 for ; Tue, 20 Feb 2024 16:43:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5FB6061CAA; Tue, 20 Feb 2024 17:43:37 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WHnbW8Ti"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A30261CAA for ; Tue, 20 Feb 2024 17:43:25 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E18E213AC; Tue, 20 Feb 2024 17:43:17 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1708447398; bh=+D0mqjYPqvZZVsEoTqPXJlIeJLBcXF9uANQXv72rSsg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WHnbW8TiO6g8AdxYnhSJdyuOPQmMw1KQcsYj4xdP5SNuupZDo/305LEh34tXCn27C fiaUpyNJwaBgWC3K5SyoTq4iDupRc2QvqpsEEJ3W4nKRVKjAz9+1Jqb1nsm9PAPMEv ibZDNJOHOETLCWUdj2ugp6lqwMFAr2cJmyPX+SSk= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 4/7] libcamera: rkisp1: Switch tryCompleteRequest() to use Request * Date: Tue, 20 Feb 2024 16:43:14 +0000 Message-Id: <20240220164317.998477-5-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240220164317.998477-1-dan.scally@ideasonboard.com> References: <20240220164317.998477-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" tryCompleteRequest() is used to delay completeRequest() until all the image buffers have been returned to userspace and the Request's metadata has been filled with control values by the IPA. To do that the pipeline handler has a struct which holds various pieces of info that allow the tryCompleteRequest() function to decide whether it's ok to complete the request yet or not. This is quite a heavy way of doing things - ultimately what is being tracked is whether or not the buffers in question have been handled by the pipeline handler, and a Request already tracks that for the image buffers. The internal buffers can be tracked in the same way using the new concept of internal buffers for a Request. Re-factor the tryCompleteRequest() function to take a Request * and simply check hasPendingBuffers(request). Use the relatively new Request::Private::addInternalBuffer() to link the stats and parameters buffers to the request on each queueRequestDevice(). Signed-off-by: Daniel Scally --- Changes in v2: - Use the new internal buffers for Requests to track status rather than the inFlightStatsBuffers_ map. src/libcamera/pipeline/rkisp1/rkisp1.cpp | 28 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index d926c83c..43e9d98b 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -39,6 +39,7 @@ #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/request.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" @@ -48,6 +49,8 @@ namespace libcamera { LOG_DEFINE_CATEGORY(RkISP1) +using InternalStream = Request::Private::InternalStream; + class PipelineHandlerRkISP1; class RkISP1CameraData; @@ -174,7 +177,7 @@ private: int initLinks(Camera *camera, const CameraSensor *sensor, const RkISP1CameraConfiguration &config); int createCamera(MediaEntity *sensor); - void tryCompleteRequest(RkISP1FrameInfo *info); + void tryCompleteRequest(Request *request); void bufferReady(FrameBuffer *buffer); void paramReady(FrameBuffer *buffer); void statReady(FrameBuffer *buffer); @@ -231,6 +234,7 @@ RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *req paramBuffer = pipe_->availableParamBuffers_.front(); pipe_->availableParamBuffers_.pop(); + paramBuffer->_d()->setRequest(request); statBuffer = pipe_->availableStatBuffers_.front(); pipe_->availableStatBuffers_.pop(); @@ -413,7 +417,8 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta info->request->metadata().merge(metadata); info->metadataProcessed = true; - pipe()->tryCompleteRequest(info); + pipe()->completeBuffer(info->request, info->statBuffer); + pipe()->tryCompleteRequest(info->request); } /* ----------------------------------------------------------------------------- @@ -1026,6 +1031,9 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) if (!info) return -ENOENT; + request->_d()->addInternalBuffer(InternalStream::Statistics, info->statBuffer); + request->_d()->addInternalBuffer(InternalStream::Parameters, info->paramBuffer); + data->ipa_->queueRequest(request->sequence(), request->controls()); if (isRaw_) { if (info->mainPathBuffer) @@ -1228,15 +1236,15 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) * Buffer Handling */ -void PipelineHandlerRkISP1::tryCompleteRequest(RkISP1FrameInfo *info) +void PipelineHandlerRkISP1::tryCompleteRequest(Request *request) { RkISP1CameraData *data = cameraData(activeCamera_); - Request *request = info->request; - if (request->hasPendingBuffers()) + RkISP1FrameInfo *info = data->frameInfo_.find(request); + if (!info) return; - if (!info->metadataProcessed) + if (request->hasPendingBuffers()) return; if (!isRaw_ && !info->paramDequeued) @@ -1281,7 +1289,7 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) } completeBuffer(request, buffer); - tryCompleteRequest(info); + tryCompleteRequest(request); } void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) @@ -1294,7 +1302,8 @@ void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) return; info->paramDequeued = true; - tryCompleteRequest(info); + completeBuffer(info->request, buffer); + tryCompleteRequest(info->request); } void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) @@ -1309,7 +1318,8 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) if (buffer->metadata().status == FrameMetadata::FrameCancelled) { info->metadataProcessed = true; - tryCompleteRequest(info); + completeBuffer(info->request, buffer); + tryCompleteRequest(info->request); return; } From patchwork Tue Feb 20 16:43:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 19516 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 49F5CC3261 for ; Tue, 20 Feb 2024 16:43:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F130B62816; Tue, 20 Feb 2024 17:43:37 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="LcByrR4I"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 153C062805 for ; Tue, 20 Feb 2024 17:43:25 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5E19714B0; Tue, 20 Feb 2024 17:43:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1708447398; bh=SusT3ITljRDCsmlVRh/ICXW4OxPR3B3+GORNLGYAD4w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LcByrR4ItRnyy8mugEt/t/GncQogvZku/K2GrlrSqOVHhpMd/0RaGdvKOF2ZSmMsz nOGTVuxPVj814ldhbN4Ka0xZPwua/8uQRAyWBZAV21vrPG9Y/DwjB6YR/v+o8GrRHN w6yTDIkJl3fTIgHkAVOfYch423I6bx8Hi7VweJ8g= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 5/7] libcamera: rkisp1: Remove RkISP1FrameInfo Date: Tue, 20 Feb 2024 16:43:15 +0000 Message-Id: <20240220164317.998477-6-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240220164317.998477-1-dan.scally@ideasonboard.com> References: <20240220164317.998477-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The RkISP1FrameInfo class existed to hold varying bits of info to help guarantee that a Request is not completed until all of the image buffers are returned to userspace and the metadata has been filled by the IPA module. Now that we're no longer using it for that function it can be removed. Remove the class and refactor its code out to the rest of the Pipeline Handler. Signed-off-by: Daniel Scally --- Changes in v2: - None src/libcamera/pipeline/rkisp1/rkisp1.cpp | 287 +++++------------------ 1 file changed, 64 insertions(+), 223 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 43e9d98b..ec4665a9 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -54,45 +54,13 @@ using InternalStream = Request::Private::InternalStream; class PipelineHandlerRkISP1; class RkISP1CameraData; -struct RkISP1FrameInfo { - unsigned int frame; - Request *request; - - FrameBuffer *paramBuffer; - FrameBuffer *statBuffer; - FrameBuffer *mainPathBuffer; - FrameBuffer *selfPathBuffer; - - bool paramDequeued; - bool metadataProcessed; -}; - -class RkISP1Frames -{ -public: - RkISP1Frames(PipelineHandler *pipe); - - RkISP1FrameInfo *create(const RkISP1CameraData *data, Request *request, - bool isRaw); - int destroy(unsigned int frame); - void clear(); - - RkISP1FrameInfo *find(unsigned int frame); - RkISP1FrameInfo *find(FrameBuffer *buffer); - RkISP1FrameInfo *find(Request *request); - -private: - PipelineHandlerRkISP1 *pipe_; - std::map frameInfo_; -}; - class RkISP1CameraData : public Camera::Private { public: RkISP1CameraData(PipelineHandler *pipe, RkISP1MainPath *mainPath, RkISP1SelfPath *selfPath) - : Camera::Private(pipe), frameInfo_(pipe), - mainPath_(mainPath), selfPath_(selfPath) + : Camera::Private(pipe), mainPath_(mainPath), + selfPath_(selfPath) { } @@ -104,7 +72,6 @@ public: std::unique_ptr sensor_; std::unique_ptr delayedCtrls_; std::vector ipaBuffers_; - RkISP1Frames frameInfo_; RkISP1MainPath *mainPath_; RkISP1SelfPath *selfPath_; @@ -172,7 +139,6 @@ private: } friend RkISP1CameraData; - friend RkISP1Frames; int initLinks(Camera *camera, const CameraSensor *sensor, const RkISP1CameraConfiguration &config); @@ -208,131 +174,6 @@ private: const MediaPad *ispSink_; }; -RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) - : pipe_(static_cast(pipe)) -{ -} - -RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *request, - bool isRaw) -{ - unsigned int frame = request->sequence(); - - FrameBuffer *paramBuffer = nullptr; - FrameBuffer *statBuffer = nullptr; - - if (!isRaw) { - if (pipe_->availableParamBuffers_.empty()) { - LOG(RkISP1, Error) << "Parameters buffer underrun"; - return nullptr; - } - - if (pipe_->availableStatBuffers_.empty()) { - LOG(RkISP1, Error) << "Statistic buffer underrun"; - return nullptr; - } - - paramBuffer = pipe_->availableParamBuffers_.front(); - pipe_->availableParamBuffers_.pop(); - paramBuffer->_d()->setRequest(request); - - statBuffer = pipe_->availableStatBuffers_.front(); - pipe_->availableStatBuffers_.pop(); - statBuffer->_d()->setRequest(request); - } - - FrameBuffer *mainPathBuffer = request->findBuffer(&data->mainPathStream_); - FrameBuffer *selfPathBuffer = request->findBuffer(&data->selfPathStream_); - - RkISP1FrameInfo *info = new RkISP1FrameInfo; - - info->frame = frame; - info->request = request; - info->paramBuffer = paramBuffer; - info->mainPathBuffer = mainPathBuffer; - info->selfPathBuffer = selfPathBuffer; - info->statBuffer = statBuffer; - info->paramDequeued = false; - info->metadataProcessed = false; - - frameInfo_[frame] = info; - - return info; -} - -int RkISP1Frames::destroy(unsigned int frame) -{ - RkISP1FrameInfo *info = find(frame); - if (!info) - return -ENOENT; - - pipe_->availableParamBuffers_.push(info->paramBuffer); - pipe_->availableStatBuffers_.push(info->statBuffer); - - frameInfo_.erase(info->frame); - - delete info; - - return 0; -} - -void RkISP1Frames::clear() -{ - for (const auto &entry : frameInfo_) { - RkISP1FrameInfo *info = entry.second; - - pipe_->availableParamBuffers_.push(info->paramBuffer); - pipe_->availableStatBuffers_.push(info->statBuffer); - - delete info; - } - - frameInfo_.clear(); -} - -RkISP1FrameInfo *RkISP1Frames::find(unsigned int frame) -{ - auto itInfo = frameInfo_.find(frame); - - if (itInfo != frameInfo_.end()) - return itInfo->second; - - LOG(RkISP1, Fatal) << "Can't locate info from frame"; - - return nullptr; -} - -RkISP1FrameInfo *RkISP1Frames::find(FrameBuffer *buffer) -{ - for (auto &itInfo : frameInfo_) { - RkISP1FrameInfo *info = itInfo.second; - - if (info->paramBuffer == buffer || - info->statBuffer == buffer || - info->mainPathBuffer == buffer || - info->selfPathBuffer == buffer) - return info; - } - - LOG(RkISP1, Fatal) << "Can't locate info from buffer"; - - return nullptr; -} - -RkISP1FrameInfo *RkISP1Frames::find(Request *request) -{ - for (auto &itInfo : frameInfo_) { - RkISP1FrameInfo *info = itInfo.second; - - if (info->request == request) - return info; - } - - LOG(RkISP1, Fatal) << "Can't locate info from request"; - - return nullptr; -} - PipelineHandlerRkISP1 *RkISP1CameraData::pipe() { return static_cast(Camera::Private::pipe()); @@ -386,20 +227,37 @@ int RkISP1CameraData::loadIPA(unsigned int hwRevision) void RkISP1CameraData::paramFilled(unsigned int frame) { PipelineHandlerRkISP1 *pipe = RkISP1CameraData::pipe(); - RkISP1FrameInfo *info = frameInfo_.find(frame); - if (!info) + + Request *request = queuedRequests_[frame]; + ASSERT(request); + + FrameBuffer *paramBuffer = request->_d()->findInternalBuffer(InternalStream::Parameters); + ASSERT(paramBuffer); + + FrameBuffer *mainPathBuffer = request->findBuffer(&mainPathStream_); + FrameBuffer *selfPathBuffer = request->findBuffer(&selfPathStream_); + + if (pipe->availableStatBuffers_.empty()) { + LOG(RkISP1, Fatal) << "Statistics buffer underrun"; return; + } + + FrameBuffer *statBuffer = pipe->availableStatBuffers_.front(); + pipe->availableStatBuffers_.pop(); + request->_d()->addInternalBuffer(InternalStream::Statistics, statBuffer); - info->paramBuffer->_d()->metadata().planes()[0].bytesused = + paramBuffer->_d()->metadata().planes()[0].bytesused = sizeof(struct rkisp1_params_cfg); - pipe->param_->queueBuffer(info->paramBuffer); - pipe->stat_->queueBuffer(info->statBuffer); + pipe->param_->queueBuffer(paramBuffer); + pipe->stat_->queueBuffer(statBuffer); + + if (mainPathBuffer) + mainPath_->queueBuffer(mainPathBuffer); + + if (selfPath_ && selfPathBuffer) + selfPath_->queueBuffer(selfPathBuffer); - if (info->mainPathBuffer) - mainPath_->queueBuffer(info->mainPathBuffer); - if (selfPath_ && info->selfPathBuffer) - selfPath_->queueBuffer(info->selfPathBuffer); } void RkISP1CameraData::setSensorControls([[maybe_unused]] unsigned int frame, @@ -410,15 +268,16 @@ void RkISP1CameraData::setSensorControls([[maybe_unused]] unsigned int frame, void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &metadata) { - RkISP1FrameInfo *info = frameInfo_.find(frame); - if (!info) - return; + Request *request = queuedRequests_[frame]; + ASSERT(request); - info->request->metadata().merge(metadata); - info->metadataProcessed = true; + FrameBuffer *statBuffer = request->_d()->findInternalBuffer(InternalStream::Statistics); + ASSERT(statBuffer); - pipe()->completeBuffer(info->request, info->statBuffer); - pipe()->tryCompleteRequest(info->request); + request->metadata().merge(metadata); + pipe()->availableStatBuffers_.push(statBuffer); + pipe()->completeBuffer(request, statBuffer); + pipe()->tryCompleteRequest(request); } /* ----------------------------------------------------------------------------- @@ -1016,7 +875,6 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera) } ASSERT(data->queuedRequests_.empty()); - data->frameInfo_.clear(); freeBuffers(camera); @@ -1026,24 +884,34 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera) int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) { RkISP1CameraData *data = cameraData(camera); + FrameBuffer *paramBuffer = nullptr; - RkISP1FrameInfo *info = data->frameInfo_.create(data, request, isRaw_); - if (!info) - return -ENOENT; + if (!isRaw_) { + if (availableParamBuffers_.empty()) { + LOG(RkISP1, Error) << "Parameters buffer underrun"; + return -ENOENT; + } + + paramBuffer = availableParamBuffers_.front(); + availableParamBuffers_.pop(); + paramBuffer->_d()->setRequest(request); + } - request->_d()->addInternalBuffer(InternalStream::Statistics, info->statBuffer); - request->_d()->addInternalBuffer(InternalStream::Parameters, info->paramBuffer); + request->_d()->addInternalBuffer(InternalStream::Parameters, paramBuffer); data->ipa_->queueRequest(request->sequence(), request->controls()); if (isRaw_) { - if (info->mainPathBuffer) - data->mainPath_->queueBuffer(info->mainPathBuffer); + FrameBuffer *mainPathBuffer = request->findBuffer(&data->mainPathStream_); + FrameBuffer *selfPathBuffer = request->findBuffer(&data->selfPathStream_); + + if (mainPathBuffer) + data->mainPath_->queueBuffer(mainPathBuffer); - if (data->selfPath_ && info->selfPathBuffer) - data->selfPath_->queueBuffer(info->selfPathBuffer); + if (data->selfPath_ && selfPathBuffer) + data->selfPath_->queueBuffer(selfPathBuffer); } else { data->ipa_->fillParamsBuffer(request->sequence(), - info->paramBuffer->cookie()); + paramBuffer->cookie()); } return 0; @@ -1238,20 +1106,9 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) void PipelineHandlerRkISP1::tryCompleteRequest(Request *request) { - RkISP1CameraData *data = cameraData(activeCamera_); - - RkISP1FrameInfo *info = data->frameInfo_.find(request); - if (!info) - return; - if (request->hasPendingBuffers()) return; - if (!isRaw_ && !info->paramDequeued) - return; - - data->frameInfo_.destroy(info->frame); - completeRequest(request); } @@ -1259,11 +1116,6 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) { ASSERT(activeCamera_); RkISP1CameraData *data = cameraData(activeCamera_); - - RkISP1FrameInfo *info = data->frameInfo_.find(buffer); - if (!info) - return; - const FrameMetadata &metadata = buffer->metadata(); Request *request = buffer->request(); @@ -1283,9 +1135,6 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) data->ipa_->processStatsBuffer(request->sequence(), 0, ctrls); } - } else { - if (isRaw_) - info->metadataProcessed = true; } completeBuffer(request, buffer); @@ -1295,15 +1144,11 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) { ASSERT(activeCamera_); - RkISP1CameraData *data = cameraData(activeCamera_); - - RkISP1FrameInfo *info = data->frameInfo_.find(buffer); - if (!info) - return; + Request *request = buffer->request(); - info->paramDequeued = true; - completeBuffer(info->request, buffer); - tryCompleteRequest(info->request); + completeBuffer(buffer->request(), buffer); + tryCompleteRequest(request); + availableParamBuffers_.push(buffer); } void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) @@ -1312,18 +1157,14 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) RkISP1CameraData *data = cameraData(activeCamera_); Request *request = buffer->request(); - RkISP1FrameInfo *info = data->frameInfo_.find(buffer); - if (!info) - return; - if (buffer->metadata().status == FrameMetadata::FrameCancelled) { - info->metadataProcessed = true; - completeBuffer(info->request, buffer); - tryCompleteRequest(info->request); + completeBuffer(request, buffer); + tryCompleteRequest(request); + availableStatBuffers_.push(buffer); return; } - data->ipa_->processStatsBuffer(request->sequence(), info->statBuffer->cookie(), + data->ipa_->processStatsBuffer(request->sequence(), buffer->cookie(), data->delayedCtrls_->get(buffer->metadata().sequence)); } From patchwork Tue Feb 20 16:43:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 19517 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 0C151C3257 for ; Tue, 20 Feb 2024 16:43:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B78A96281C; Tue, 20 Feb 2024 17:43:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kCy57dN5"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4BD3C62816 for ; Tue, 20 Feb 2024 17:43:26 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CDF8513AC; Tue, 20 Feb 2024 17:43:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1708447399; bh=oVp2NAeK8iFDudcHJP+wK5DZNhWAkH7FY3TPU52qTsM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kCy57dN5UqPrcDVdO60eBHgFUfMWcSDForB8g4Z86YWN6qNucjhg1ESJor8B1/f8s cj182+g9dqtkRggrl3pNOExg7soIDPf+PKlMq/ZgSl/yjKtt2JvwpW+Hxd2Vogf/as CIQYGcHgv4rmRw+CbxQt0i6A+3uwH7lebwnYcsuM= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 6/7] libcamera: rkisp1: Remove tryCompleteRequest function Date: Tue, 20 Feb 2024 16:43:16 +0000 Message-Id: <20240220164317.998477-7-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240220164317.998477-1-dan.scally@ideasonboard.com> References: <20240220164317.998477-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now that tryCompleteRequest() does nothing beyond checking for the Request's pending buffers, we can just remove the function and rely on the return value of completeBuffer() to know if it's time to call completeRequest() or not. Signed-off-by: Daniel Scally --- Changes in v2: - New patch src/libcamera/pipeline/rkisp1/rkisp1.cpp | 27 +++++++++--------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index ec4665a9..8331da11 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -143,7 +143,6 @@ private: int initLinks(Camera *camera, const CameraSensor *sensor, const RkISP1CameraConfiguration &config); int createCamera(MediaEntity *sensor); - void tryCompleteRequest(Request *request); void bufferReady(FrameBuffer *buffer); void paramReady(FrameBuffer *buffer); void statReady(FrameBuffer *buffer); @@ -276,8 +275,8 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta request->metadata().merge(metadata); pipe()->availableStatBuffers_.push(statBuffer); - pipe()->completeBuffer(request, statBuffer); - pipe()->tryCompleteRequest(request); + if (pipe()->completeBuffer(request, statBuffer)) + pipe()->completeRequest(request); } /* ----------------------------------------------------------------------------- @@ -1104,14 +1103,6 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) * Buffer Handling */ -void PipelineHandlerRkISP1::tryCompleteRequest(Request *request) -{ - if (request->hasPendingBuffers()) - return; - - completeRequest(request); -} - void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) { ASSERT(activeCamera_); @@ -1137,8 +1128,8 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) } } - completeBuffer(request, buffer); - tryCompleteRequest(request); + if (completeBuffer(request, buffer)) + completeRequest(request); } void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) @@ -1146,8 +1137,9 @@ void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) ASSERT(activeCamera_); Request *request = buffer->request(); - completeBuffer(buffer->request(), buffer); - tryCompleteRequest(request); + if (completeBuffer(buffer->request(), buffer)) + completeRequest(request); + availableParamBuffers_.push(buffer); } @@ -1158,8 +1150,9 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) Request *request = buffer->request(); if (buffer->metadata().status == FrameMetadata::FrameCancelled) { - completeBuffer(request, buffer); - tryCompleteRequest(request); + if (completeBuffer(request, buffer)) + completeRequest(request); + availableStatBuffers_.push(buffer); return; } From patchwork Tue Feb 20 16:43:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 19518 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 A1C68C32C3 for ; Tue, 20 Feb 2024 16:43:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 52C906281A; Tue, 20 Feb 2024 17:43:39 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="r+AdyMdM"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A140F6281E for ; Tue, 20 Feb 2024 17:43:26 +0100 (CET) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3416E230E; Tue, 20 Feb 2024 17:43:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1708447399; bh=ULueQp8rIcDhjqodhbddJkkr9uqRqkkH+A1iuuLNJk0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r+AdyMdMHcbag+g/7zlFWZV8lH+CWozCDaSyXeICZnBcPgJLWcy+p4okfXbtu1NXN NZGEPgvFu0/O5KobRu48UWvQaG6w6lGL6n+Sxg9it01yClg8h6KBzspkfsyR76NvbR ewtbNfjhGAZvJwO9M7yyZQA7i2d62FAthi7FxPIo= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 7/7] libcamera: ipu3: Remove IPU3Frames Date: Tue, 20 Feb 2024 16:43:17 +0000 Message-Id: <20240220164317.998477-8-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240220164317.998477-1-dan.scally@ideasonboard.com> References: <20240220164317.998477-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The IPU3Frames class existed to track whether or not a request is ok to complete yet or not - that can now be done through internal buffer tracking within a Request::Private, so switch to that method and drop the dedicated class. Signed-off-by: Daniel Scally --- Changes in v2: - New patch src/libcamera/pipeline/ipu3/cio2.cpp | 3 +- src/libcamera/pipeline/ipu3/cio2.h | 2 +- src/libcamera/pipeline/ipu3/frames.cpp | 143 ----------------- src/libcamera/pipeline/ipu3/frames.h | 67 -------- src/libcamera/pipeline/ipu3/ipu3.cpp | 203 ++++++++++++++---------- src/libcamera/pipeline/ipu3/meson.build | 1 - 6 files changed, 122 insertions(+), 297 deletions(-) delete mode 100644 src/libcamera/pipeline/ipu3/frames.cpp delete mode 100644 src/libcamera/pipeline/ipu3/frames.h diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp index 7400cb0b..e0b0d3d1 100644 --- a/src/libcamera/pipeline/ipu3/cio2.cpp +++ b/src/libcamera/pipeline/ipu3/cio2.cpp @@ -379,7 +379,7 @@ int CIO2Device::stop() return ret; } -FrameBuffer *CIO2Device::queueBuffer(Request *request, FrameBuffer *rawBuffer) +FrameBuffer *CIO2Device::queueBuffer(FrameBuffer *rawBuffer) { FrameBuffer *buffer = rawBuffer; @@ -392,7 +392,6 @@ FrameBuffer *CIO2Device::queueBuffer(Request *request, FrameBuffer *rawBuffer) buffer = availableBuffers_.front(); availableBuffers_.pop(); - buffer->_d()->setRequest(request); } int ret = output_->queueBuffer(buffer); diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h index bbd87eb8..42bb28b7 100644 --- a/src/libcamera/pipeline/ipu3/cio2.h +++ b/src/libcamera/pipeline/ipu3/cio2.h @@ -56,7 +56,7 @@ public: CameraSensor *sensor() { return sensor_.get(); } const CameraSensor *sensor() const { return sensor_.get(); } - FrameBuffer *queueBuffer(Request *request, FrameBuffer *rawBuffer); + FrameBuffer *queueBuffer(FrameBuffer *rawBuffer); void tryReturnBuffer(FrameBuffer *buffer); Signal &bufferReady() { return output_->bufferReady; } Signal &frameStart() { return csi2_->frameStart; } diff --git a/src/libcamera/pipeline/ipu3/frames.cpp b/src/libcamera/pipeline/ipu3/frames.cpp deleted file mode 100644 index a4c3477c..00000000 --- a/src/libcamera/pipeline/ipu3/frames.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020, Google Inc. - * - * frames.cpp - Intel IPU3 Frames helper - */ - -#include "frames.h" - -#include -#include - -#include "libcamera/internal/framebuffer.h" -#include "libcamera/internal/pipeline_handler.h" -#include "libcamera/internal/v4l2_videodevice.h" - -namespace libcamera { - -LOG_DECLARE_CATEGORY(IPU3) - -IPU3Frames::IPU3Frames() -{ -} - -void IPU3Frames::init(const std::vector> ¶mBuffers, - const std::vector> &statBuffers) -{ - for (const std::unique_ptr &buffer : paramBuffers) - availableParamBuffers_.push(buffer.get()); - - for (const std::unique_ptr &buffer : statBuffers) - availableStatBuffers_.push(buffer.get()); - - frameInfo_.clear(); -} - -void IPU3Frames::clear() -{ - availableParamBuffers_ = {}; - availableStatBuffers_ = {}; -} - -IPU3Frames::Info *IPU3Frames::create(Request *request) -{ - unsigned int id = request->sequence(); - - if (availableParamBuffers_.empty()) { - LOG(IPU3, Debug) << "Parameters buffer underrun"; - return nullptr; - } - - if (availableStatBuffers_.empty()) { - LOG(IPU3, Debug) << "Statistics buffer underrun"; - return nullptr; - } - - FrameBuffer *paramBuffer = availableParamBuffers_.front(); - FrameBuffer *statBuffer = availableStatBuffers_.front(); - - paramBuffer->_d()->setRequest(request); - statBuffer->_d()->setRequest(request); - - availableParamBuffers_.pop(); - availableStatBuffers_.pop(); - - /* \todo Remove the dynamic allocation of Info */ - std::unique_ptr info = std::make_unique(); - - info->id = id; - info->request = request; - info->rawBuffer = nullptr; - info->paramBuffer = paramBuffer; - info->statBuffer = statBuffer; - info->paramDequeued = false; - info->metadataProcessed = false; - - frameInfo_[id] = std::move(info); - - return frameInfo_[id].get(); -} - -void IPU3Frames::remove(IPU3Frames::Info *info) -{ - /* Return params and stat buffer for reuse. */ - availableParamBuffers_.push(info->paramBuffer); - availableStatBuffers_.push(info->statBuffer); - - /* Delete the extended frame information. */ - frameInfo_.erase(info->id); -} - -bool IPU3Frames::tryComplete(IPU3Frames::Info *info) -{ - Request *request = info->request; - - if (request->hasPendingBuffers()) - return false; - - if (!info->metadataProcessed) - return false; - - if (!info->paramDequeued) - return false; - - remove(info); - - bufferAvailable.emit(); - - return true; -} - -IPU3Frames::Info *IPU3Frames::find(unsigned int id) -{ - const auto &itInfo = frameInfo_.find(id); - - if (itInfo != frameInfo_.end()) - return itInfo->second.get(); - - LOG(IPU3, Fatal) << "Can't find tracking information for frame " << id; - - return nullptr; -} - -IPU3Frames::Info *IPU3Frames::find(FrameBuffer *buffer) -{ - for (auto const &itInfo : frameInfo_) { - Info *info = itInfo.second.get(); - - for (auto const itBuffers : info->request->buffers()) - if (itBuffers.second == buffer) - return info; - - if (info->rawBuffer == buffer || info->paramBuffer == buffer || - info->statBuffer == buffer) - return info; - } - - LOG(IPU3, Fatal) << "Can't find tracking information from buffer"; - - return nullptr; -} - -} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/ipu3/frames.h b/src/libcamera/pipeline/ipu3/frames.h deleted file mode 100644 index 6e3cb915..00000000 --- a/src/libcamera/pipeline/ipu3/frames.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020, Google Inc. - * - * frames.h - Intel IPU3 Frames helper - */ - -#pragma once - -#include -#include -#include -#include - -#include - -#include - -namespace libcamera { - -class FrameBuffer; -class IPAProxy; -class PipelineHandler; -class Request; -class V4L2VideoDevice; -struct IPABuffer; - -class IPU3Frames -{ -public: - struct Info { - unsigned int id; - Request *request; - - FrameBuffer *rawBuffer; - FrameBuffer *paramBuffer; - FrameBuffer *statBuffer; - - ControlList effectiveSensorControls; - - bool paramDequeued; - bool metadataProcessed; - }; - - IPU3Frames(); - - void init(const std::vector> ¶mBuffers, - const std::vector> &statBuffers); - void clear(); - - Info *create(Request *request); - void remove(Info *info); - bool tryComplete(Info *info); - - Info *find(unsigned int id); - Info *find(FrameBuffer *buffer); - - Signal<> bufferAvailable; - -private: - std::queue availableParamBuffers_; - std::queue availableStatBuffers_; - - std::map> frameInfo_; -}; - -} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index fa4bd0bb..a8e59dea 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -34,15 +34,17 @@ #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/request.h" #include "cio2.h" -#include "frames.h" #include "imgu.h" namespace libcamera { LOG_DEFINE_CATEGORY(IPU3) +using InternalStream = Request::Private::InternalStream; + static const ControlInfoMap::Map IPU3Controls = { { &controls::draft::PipelineDepth, ControlInfo(2, 3) }, }; @@ -58,6 +60,7 @@ public: int loadIPA(); void imguOutputBufferReady(FrameBuffer *buffer); + void imguInputBufferReady(FrameBuffer *buffer); void cio2BufferReady(FrameBuffer *buffer); void paramBufferReady(FrameBuffer *buffer); void statBufferReady(FrameBuffer *buffer); @@ -75,7 +78,6 @@ public: Rectangle cropRegion_; std::unique_ptr delayedCtrls_; - IPU3Frames frameInfos_; std::unique_ptr ipa_; @@ -86,11 +88,14 @@ public: ControlInfoMap ipaControls_; + std::queue availableParamBuffers_; + std::queue availableStatBuffers_; private: void metadataReady(unsigned int id, const ControlList &metadata); void paramsBufferReady(unsigned int id); void setSensorControls(unsigned int id, const ControlList &sensorControls, const ControlList &lensControls); + void tryCompleteRequest(Request *request); }; class IPU3CameraConfiguration : public CameraConfiguration @@ -680,19 +685,17 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera) for (const std::unique_ptr &buffer : imgu->paramBuffers_) { buffer->setCookie(ipaBufferId++); ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes()); + data->availableParamBuffers_.push(buffer.get()); } for (const std::unique_ptr &buffer : imgu->statBuffers_) { buffer->setCookie(ipaBufferId++); ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes()); + data->availableStatBuffers_.push(buffer.get()); } data->ipa_->mapBuffers(ipaBuffers_); - data->frameInfos_.init(imgu->paramBuffers_, imgu->statBuffers_); - data->frameInfos_.bufferAvailable.connect( - data, &IPU3CameraData::queuePendingRequests); - return 0; } @@ -700,7 +703,11 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera) { IPU3CameraData *data = cameraData(camera); - data->frameInfos_.clear(); + while (!data->availableStatBuffers_.empty()) + data->availableStatBuffers_.pop(); + + while (!data->availableParamBuffers_.empty()) + data->availableParamBuffers_.pop(); std::vector ids; for (IPABuffer &ipabuf : ipaBuffers_) @@ -792,6 +799,12 @@ void IPU3CameraData::cancelPendingRequests() pipe()->completeBuffer(request, buffer); } + for (auto it : request->_d()->internalBuffers()) { + FrameBuffer *b = it.second; + b->_d()->cancel(); + pipe()->completeBuffer(request, b); + } + pipe()->completeRequest(request); pendingRequests_.pop(); } @@ -802,31 +815,23 @@ void IPU3CameraData::queuePendingRequests() while (!pendingRequests_.empty()) { Request *request = pendingRequests_.front(); - IPU3Frames::Info *info = 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(&rawStream_); - FrameBuffer *rawBuffer = cio2_.queueBuffer(request, reqRawBuffer); + FrameBuffer *rawBuffer = cio2_.queueBuffer(reqRawBuffer); /* * \todo If queueBuffer fails in queuing a buffer to the device, * report the request as error by cancelling the request and * calling PipelineHandler::completeRequest(). */ - if (!rawBuffer) { - frameInfos_.remove(info); + if (!rawBuffer) break; - } - - info->rawBuffer = rawBuffer; - - ipa_->queueRequest(info->id, request->controls()); + request->_d()->addInternalBuffer(InternalStream::Mem2Mem, rawBuffer); + ipa_->queueRequest(request->sequence(), request->controls()); pendingRequests_.pop(); processingRequests_.push(request); } @@ -1120,8 +1125,8 @@ int PipelineHandlerIPU3::registerCameras() &IPU3CameraData::cio2BufferReady); data->cio2_.bufferAvailable.connect( data.get(), &IPU3CameraData::queuePendingRequests); - data->imgu_->input_->bufferReady.connect(&data->cio2_, - &CIO2Device::tryReturnBuffer); + data->imgu_->input_->bufferReady.connect(data.get(), + &IPU3CameraData::imguInputBufferReady); data->imgu_->output_->bufferReady.connect(data.get(), &IPU3CameraData::imguOutputBufferReady); data->imgu_->viewfinder_->bufferReady.connect(data.get(), @@ -1200,6 +1205,17 @@ int IPU3CameraData::loadIPA() return 0; } +void IPU3CameraData::tryCompleteRequest(Request *request) +{ + if (request->hasPendingBuffers()) + return; + + pipe()->completeRequest(request); + + /* Try queue another request now that this one has completed. */ + queuePendingRequests(); +} + void IPU3CameraData::setSensorControls([[maybe_unused]] unsigned int id, const ControlList &sensorControls, const ControlList &lensControls) @@ -1220,12 +1236,11 @@ void IPU3CameraData::setSensorControls([[maybe_unused]] unsigned int id, void IPU3CameraData::paramsBufferReady(unsigned int id) { - IPU3Frames::Info *info = frameInfos_.find(id); - if (!info) - return; + Request *request = queuedRequests_[id]; + ASSERT(request); /* Queue all buffers from the request aimed for the ImgU. */ - for (auto it : info->request->buffers()) { + for (auto it : request->buffers()) { const Stream *stream = it.first; FrameBuffer *outbuffer = it.second; @@ -1235,25 +1250,41 @@ void IPU3CameraData::paramsBufferReady(unsigned int id) imgu_->viewfinder_->queueBuffer(outbuffer); } - info->paramBuffer->_d()->metadata().planes()[0].bytesused = + FrameBuffer *paramBuffer = request->_d()->findInternalBuffer(InternalStream::Parameters); + paramBuffer->_d()->metadata().planes()[0].bytesused = sizeof(struct ipu3_uapi_params); - imgu_->param_->queueBuffer(info->paramBuffer); - imgu_->stat_->queueBuffer(info->statBuffer); - imgu_->input_->queueBuffer(info->rawBuffer); + + if (availableStatBuffers_.empty()) { + LOG(IPU3, Error) << "Statistics buffer underrun"; + return; + } + + FrameBuffer *statBuffer = availableStatBuffers_.front(); + availableStatBuffers_.pop(); + request->_d()->addInternalBuffer(InternalStream::Statistics, statBuffer); + + imgu_->param_->queueBuffer(paramBuffer); + imgu_->stat_->queueBuffer(statBuffer); + + FrameBuffer *rawBuffer = request->_d()->findInternalBuffer(InternalStream::Mem2Mem); + ASSERT(rawBuffer); + + imgu_->input_->queueBuffer(rawBuffer); } void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata) { - IPU3Frames::Info *info = frameInfos_.find(id); - if (!info) - return; + Request *request = queuedRequests_[id]; + ASSERT(request); + + FrameBuffer *statBuffer = request->_d()->findInternalBuffer(InternalStream::Statistics); + ASSERT(statBuffer); - Request *request = info->request; request->metadata().merge(metadata); + availableStatBuffers_.push(statBuffer); - info->metadataProcessed = true; - if (frameInfos_.tryComplete(info)) - pipe()->completeRequest(request); + pipe()->completeBuffer(request, statBuffer); + tryCompleteRequest(request); } /* ----------------------------------------------------------------------------- @@ -1268,13 +1299,7 @@ void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata) */ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer) { - IPU3Frames::Info *info = frameInfos_.find(buffer); - if (!info) - return; - - Request *request = info->request; - - pipe()->completeBuffer(request, buffer); + Request *request = buffer->request(); request->metadata().set(controls::draft::PipelineDepth, 3); /* \todo Actually apply the scaler crop region to the ImgU. */ @@ -1283,8 +1308,25 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer) cropRegion_ = *scalerCrop; request->metadata().set(controls::ScalerCrop, cropRegion_); - if (frameInfos_.tryComplete(info)) - pipe()->completeRequest(request); + pipe()->completeBuffer(request, buffer); + tryCompleteRequest(request); +} + +void IPU3CameraData::imguInputBufferReady(FrameBuffer *buffer) +{ + Request *request = buffer->request(); + + /* + * If the Request has a Mem2Mem buffer and it's **this** buffer, then + * give it back to the CIO2Device to return it to its internal queue and + * flag it as completed for the purposes of the Request + */ + FrameBuffer *reqBuffer = request->_d()->findInternalBuffer(InternalStream::Mem2Mem); + if (reqBuffer && reqBuffer == buffer) { + pipe()->completeBuffer(request, buffer); + tryCompleteRequest(request); + cio2_.tryReturnBuffer(buffer); + } } /** @@ -1296,11 +1338,7 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer) */ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer) { - IPU3Frames::Info *info = frameInfos_.find(buffer); - if (!info) - return; - - Request *request = info->request; + Request *request = buffer->request(); /* If the buffer is cancelled force a complete of the whole request. */ if (buffer->metadata().status == FrameMetadata::FrameCancelled) { @@ -1310,7 +1348,12 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer) pipe()->completeBuffer(request, b); } - frameInfos_.remove(info); + for (auto it : request->_d()->internalBuffers()) { + FrameBuffer *b = it.second; + b->_d()->cancel(); + pipe()->completeBuffer(request, b); + } + pipe()->completeRequest(request); return; } @@ -1324,57 +1367,51 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer) request->metadata().set(controls::SensorTimestamp, buffer->metadata().timestamp); - info->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence); - if (request->findBuffer(&rawStream_)) pipe()->completeBuffer(request, buffer); - ipa_->fillParamsBuffer(info->id, info->paramBuffer->cookie()); + if (availableParamBuffers_.empty()) { + LOG(IPU3, Error) << "Parameters buffer underrun"; + return; + } + + FrameBuffer *paramBuffer = availableParamBuffers_.front(); + availableParamBuffers_.pop(); + request->_d()->addInternalBuffer(InternalStream::Parameters, paramBuffer); + + ipa_->fillParamsBuffer(request->sequence(), paramBuffer->cookie()); } void IPU3CameraData::paramBufferReady(FrameBuffer *buffer) { - IPU3Frames::Info *info = frameInfos_.find(buffer); - if (!info) - return; - - info->paramDequeued = true; + Request *request = buffer->request(); - /* - * tryComplete() will delete info if it completes the IPU3Frame. - * In that event, we must have obtained the Request before hand. - * - * \todo Improve the FrameInfo API to avoid this type of issue - */ - Request *request = info->request; + pipe()->completeBuffer(request, buffer); + tryCompleteRequest(request); - if (frameInfos_.tryComplete(info)) - pipe()->completeRequest(request); + availableParamBuffers_.push(buffer); } void IPU3CameraData::statBufferReady(FrameBuffer *buffer) { - IPU3Frames::Info *info = frameInfos_.find(buffer); - if (!info) - return; - - Request *request = info->request; + Request *request = buffer->request(); if (buffer->metadata().status == FrameMetadata::FrameCancelled) { - info->metadataProcessed = true; - - /* - * tryComplete() will delete info if it completes the IPU3Frame. - * In that event, we must have obtained the Request before hand. - */ - if (frameInfos_.tryComplete(info)) - pipe()->completeRequest(request); + pipe()->completeBuffer(request, buffer); + tryCompleteRequest(request); return; } - ipa_->processStatsBuffer(info->id, request->metadata().get(controls::SensorTimestamp).value_or(0), - info->statBuffer->cookie(), info->effectiveSensorControls); + /* + * We **must** use the sequence reported by the CIO2 when fetching the + * applied sensor controls. + */ + FrameBuffer *rawBuffer = request->_d()->findInternalBuffer(InternalStream::Mem2Mem); + ASSERT(rawBuffer); + + ipa_->processStatsBuffer(request->sequence(), request->metadata().get(controls::SensorTimestamp).value_or(0), + buffer->cookie(), delayedCtrls_->get(rawBuffer->metadata().sequence)); } /* diff --git a/src/libcamera/pipeline/ipu3/meson.build b/src/libcamera/pipeline/ipu3/meson.build index a1b0b31a..d60e07ae 100644 --- a/src/libcamera/pipeline/ipu3/meson.build +++ b/src/libcamera/pipeline/ipu3/meson.build @@ -2,7 +2,6 @@ libcamera_sources += files([ 'cio2.cpp', - 'frames.cpp', 'imgu.cpp', 'ipu3.cpp', ])