From patchwork Fri Dec 6 16:07:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 22229 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 88546BE173 for ; Fri, 6 Dec 2024 16:08:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4BC6967E2D; Fri, 6 Dec 2024 17:07:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="mjsCbx0N"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EC06E618B3 for ; Fri, 6 Dec 2024 17:07:55 +0100 (CET) Received: from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it [93.61.96.190]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 475B2641; Fri, 6 Dec 2024 17:07:26 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1733501246; bh=UtKmjupIEL60xV2zJbciiaJq0pJuJPdySw2ZplSqTxI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mjsCbx0NsX2cevRuXiEnyiVYEeQHPHre18Wf35Sn8oRzvBSgYjpoZkEXg1J4oV8lb trq85eHXQJCliHu/HEHbC8xEeCUv6aW1XnHh1YGluLuLUktFelRZ3IkRMDELIX/t8D JSSadDQfxYTqWh2OU6gwGetPwQX00NX6O9xupInM= From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Harvey Yang , Han-Lin Chen Subject: [PATCH 3/8] libcamera: pipeline_handler: Add metadataAvailable() function Date: Fri, 6 Dec 2024 17:07:41 +0100 Message-ID: <20241206160747.97176-4-jacopo.mondi@ideasonboard.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241206160747.97176-1-jacopo.mondi@ideasonboard.com> References: <20241206160747.97176-1-jacopo.mondi@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" Currently the way pipeline handlers have to store metadata results for a Request is to access the Request::metadata_ list directly and either merge a ControlList or set a single control value there. Direct access to Request::metadata_ is however problematic as even if metadata would be available earlier, pipeline handlers can only accumulate the results in Request::metadata_ and they're only available for applications at Request complete time. Instead of letting pipeline handlers access Request::metadata_ directly provide two helper functions, similar in spirit to PipelineHandler::completeBuffer() and PipelineHandler::completeRequest(), to allow pipeline handlers to notify early availability of metadata. Provide two overloads, one that accepts a ControlList and merges it into Request::metadata_ and one that allows to set a single metadata result there without going through an intermediate copy. The newly provided helpers trigger the Camera::availableMetadata signal from where applications can retrieve the list of ControlIds that have just been made available by the pipeline handler. Signed-off-by: Jacopo Mondi --- include/libcamera/internal/pipeline_handler.h | 41 ++++++++++ src/libcamera/pipeline_handler.cpp | 74 +++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h index fb28a18d0f46..3ca6a0290b2b 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -11,13 +11,17 @@ #include #include #include +#include #include #include +#include #include #include +#include "libcamera/internal/request.h" + namespace libcamera { class Camera; @@ -58,6 +62,43 @@ public: void registerRequest(Request *request); void queueRequest(Request *request); + void metadataAvailable(Request *request, const ControlList &metadata); + + template + void metadataAvailable(Request *request, const Control &ctrl, + const T &value) + { + if (request->metadata().contains(ctrl.id())) + return; + + std::unordered_set ids; + ids.insert(&ctrl); + + request->metadata().set(ctrl, value); + + Camera *camera = request->_d()->camera(); + camera->metadataAvailable.emit(request, ids); + } + +#ifndef __DOXYGEN__ + template + void metadataAvailable(Request *request, + const Control> &ctrl, + const Span &value) + { + if (request->metadata().contains(ctrl.id())) + return; + + std::unordered_set ids; + ids.insert(&ctrl); + + request->metadata().set(ctrl, value); + + Camera *camera = request->_d()->camera(); + camera->metadataAvailable.emit(request, ids); + } +#endif + bool completeBuffer(Request *request, FrameBuffer *buffer); void completeRequest(Request *request); void cancelRequest(Request *request); diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index caa5c20e7483..a69d789116ad 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -507,6 +507,80 @@ void PipelineHandler::doQueueRequests() * \return 0 on success or a negative error code otherwise */ +/** + * \brief Notify the availability of a list of metadata for \a request + * \param[in] request The request the metadata belongs to + * \param[in] metadata The metadata list + * + * This function should be called multiple times by pipeline handlers to signal + * the availability of a list of metadata results. It notifies applications + * by triggering the Camera::availableMetadata signal and accumulates the + * metadata results in Request::metadata(). + * + * Early metadata completion allows pipeline handlers to fast track delivery of + * metadata results as soon as they are available before the completion of \a + * request. The full list of metadata results of a Request is available at + * Request completion time in Request::metadata(). + * + * A metadata key is expected to be notified at most once. Metadata keys + * notified multiple times are ignored. + * + * This overload allows to signal the availability of a list of metadata and + * merges them in the Request::metadata() list. This operations is expensive + * as controls are copied from \a metadata to Request::metadata(). + * + * \context This function shall be called from the CameraManager thread. + */ +void PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata) +{ + std::unordered_set ids; + const ControlIdMap *idmap = request->metadata().idMap(); + + for (const auto &ctrl : metadata) { + if (request->metadata().contains(ctrl.first)) + continue; + + ASSERT(idmap->count(ctrl.first)); + + ids.insert(idmap->at(ctrl.first)); + } + + if (ids.empty()) + return; + + request->metadata().merge(metadata); + + Camera *camera = request->_d()->camera(); + camera->metadataAvailable.emit(request, ids); +} + +/** + * \fn void PipelineHandler::metadataAvailable(Request *request, const Control &ctrl, const T &value) + * \brief Notify the availability of a metadata result for \a request + * \param[in] request The request the metadata belongs to + * \param[in] ctrl The control id to notify + * \param[in] value the control value + * + * This function should be called multiple times by pipeline handlers to signal + * the availability of a metadata result. It notifies applications + * by triggering the Camera::availableMetadata signal and accumulates the + * metadata result in Request::metadata(). + * + * Early metadata completion allows pipeline handlers to fast track delivery of + * metadata results as soon as they are available before the completion of \a + * request. The full list of metadata results of a Request is available at + * Request completion time in Request::metadata(). + * + * A metadata key is expected to be notified at most once. Metadata keys + * notified multiple times are ignored. + * + * This overload allows to signal the availability of a single metadata and + * merge \a value in the Request::metadata() list. This operations copies \a + * value in the Request::metadata() list without creating intermediate copies. + * + * \context This function shall be called from the CameraManager thread. + */ + /** * \brief Complete a buffer for a request * \param[in] request The request the buffer belongs to