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();