{"id":19526,"url":"https://patchwork.libcamera.org/api/patches/19526/?format=json","web_url":"https://patchwork.libcamera.org/patch/19526/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20240221174015.52958-5-jacopo.mondi@ideasonboard.com>","date":"2024-02-21T17:40:12","name":"[4/5] libcamera: ipu3: Replace IPU3FrameInfo","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"1cdbbd61693a1f4f380753bd7d6c5e4d6312538b","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/?format=json","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/19526/mbox/","series":[{"id":4176,"url":"https://patchwork.libcamera.org/api/series/4176/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=4176","date":"2024-02-21T17:40:08","name":"libcamera: Replace IPU3/RkISP1FrameInfo","version":1,"mbox":"https://patchwork.libcamera.org/series/4176/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/19526/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/19526/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 718A5C32C3\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Feb 2024 17:40:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 402CE62822;\n\tWed, 21 Feb 2024 18:40:33 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C766C6281D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Feb 2024 18:40:28 +0100 (CET)","from localhost.localdomain (unknown\n\t[IPv6:2001:b07:5d2e:52c9:cc1e:e404:491f:e6ea])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A9FCA2B3;\n\tWed, 21 Feb 2024 18:40:20 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"QW+pHLgR\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1708537220;\n\tbh=Y9w5i6JRZWaf6u+qYrUbj4vtvLWg+cZKde67FOjM1K4=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=QW+pHLgRnoA7XxPwSasyX5hPH9GFC7Esy63GWnTAKcrK3jXritXU+OORFbkArN0xu\n\tK9CL4UgTT0H7zcB6o+1AvDi+v03D6KnBQMkZQIrKoisEKSPkGgOwXqanBoMe8k10GO\n\tnMobBFEvvtGmWSseEE2816GXfs7dRIEryrJSDVtc=","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Subject":"[PATCH 4/5] libcamera: ipu3: Replace IPU3FrameInfo","Date":"Wed, 21 Feb 2024 18:40:12 +0100","Message-ID":"<20240221174015.52958-5-jacopo.mondi@ideasonboard.com>","X-Mailer":"git-send-email 2.43.0","In-Reply-To":"<20240221174015.52958-1-jacopo.mondi@ideasonboard.com>","References":"<20240221174015.52958-1-jacopo.mondi@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Now that the pipeline handler can create a private derived class of\nRequest::Private, use it to store the pipeline specific data.\n\nIn the case of IPU3 we associate statistics and paramters buffer with a\nRequest and a raw buffer which gets dequeued from the CIO2 and input\nto the ImgU input.\n\nThis replaces the functionalities of IPU3FrameInfo which can now be\nremoved.\n\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\n src/libcamera/pipeline/ipu3/frames.cpp  | 143 ---------------\n src/libcamera/pipeline/ipu3/frames.h    |  67 -------\n src/libcamera/pipeline/ipu3/ipu3.cpp    | 221 ++++++++++++++++--------\n src/libcamera/pipeline/ipu3/meson.build |   1 -\n 4 files changed, 146 insertions(+), 286 deletions(-)\n delete mode 100644 src/libcamera/pipeline/ipu3/frames.cpp\n delete mode 100644 src/libcamera/pipeline/ipu3/frames.h","diff":"diff --git a/src/libcamera/pipeline/ipu3/frames.cpp b/src/libcamera/pipeline/ipu3/frames.cpp\ndeleted file mode 100644\nindex a4c3477cd9ef..000000000000\n--- a/src/libcamera/pipeline/ipu3/frames.cpp\n+++ /dev/null\n@@ -1,143 +0,0 @@\n-/* SPDX-License-Identifier: LGPL-2.1-or-later */\n-/*\n- * Copyright (C) 2020, Google Inc.\n- *\n- * frames.cpp - Intel IPU3 Frames helper\n- */\n-\n-#include \"frames.h\"\n-\n-#include <libcamera/framebuffer.h>\n-#include <libcamera/request.h>\n-\n-#include \"libcamera/internal/framebuffer.h\"\n-#include \"libcamera/internal/pipeline_handler.h\"\n-#include \"libcamera/internal/v4l2_videodevice.h\"\n-\n-namespace libcamera {\n-\n-LOG_DECLARE_CATEGORY(IPU3)\n-\n-IPU3Frames::IPU3Frames()\n-{\n-}\n-\n-void IPU3Frames::init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuffers,\n-\t\t      const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers)\n-{\n-\tfor (const std::unique_ptr<FrameBuffer> &buffer : paramBuffers)\n-\t\tavailableParamBuffers_.push(buffer.get());\n-\n-\tfor (const std::unique_ptr<FrameBuffer> &buffer : statBuffers)\n-\t\tavailableStatBuffers_.push(buffer.get());\n-\n-\tframeInfo_.clear();\n-}\n-\n-void IPU3Frames::clear()\n-{\n-\tavailableParamBuffers_ = {};\n-\tavailableStatBuffers_ = {};\n-}\n-\n-IPU3Frames::Info *IPU3Frames::create(Request *request)\n-{\n-\tunsigned int id = request->sequence();\n-\n-\tif (availableParamBuffers_.empty()) {\n-\t\tLOG(IPU3, Debug) << \"Parameters buffer underrun\";\n-\t\treturn nullptr;\n-\t}\n-\n-\tif (availableStatBuffers_.empty()) {\n-\t\tLOG(IPU3, Debug) << \"Statistics buffer underrun\";\n-\t\treturn nullptr;\n-\t}\n-\n-\tFrameBuffer *paramBuffer = availableParamBuffers_.front();\n-\tFrameBuffer *statBuffer = availableStatBuffers_.front();\n-\n-\tparamBuffer->_d()->setRequest(request);\n-\tstatBuffer->_d()->setRequest(request);\n-\n-\tavailableParamBuffers_.pop();\n-\tavailableStatBuffers_.pop();\n-\n-\t/* \\todo Remove the dynamic allocation of Info */\n-\tstd::unique_ptr<Info> info = std::make_unique<Info>();\n-\n-\tinfo->id = id;\n-\tinfo->request = request;\n-\tinfo->rawBuffer = nullptr;\n-\tinfo->paramBuffer = paramBuffer;\n-\tinfo->statBuffer = statBuffer;\n-\tinfo->paramDequeued = false;\n-\tinfo->metadataProcessed = false;\n-\n-\tframeInfo_[id] = std::move(info);\n-\n-\treturn frameInfo_[id].get();\n-}\n-\n-void IPU3Frames::remove(IPU3Frames::Info *info)\n-{\n-\t/* Return params and stat buffer for reuse. */\n-\tavailableParamBuffers_.push(info->paramBuffer);\n-\tavailableStatBuffers_.push(info->statBuffer);\n-\n-\t/* Delete the extended frame information. */\n-\tframeInfo_.erase(info->id);\n-}\n-\n-bool IPU3Frames::tryComplete(IPU3Frames::Info *info)\n-{\n-\tRequest *request = info->request;\n-\n-\tif (request->hasPendingBuffers())\n-\t\treturn false;\n-\n-\tif (!info->metadataProcessed)\n-\t\treturn false;\n-\n-\tif (!info->paramDequeued)\n-\t\treturn false;\n-\n-\tremove(info);\n-\n-\tbufferAvailable.emit();\n-\n-\treturn true;\n-}\n-\n-IPU3Frames::Info *IPU3Frames::find(unsigned int id)\n-{\n-\tconst auto &itInfo = frameInfo_.find(id);\n-\n-\tif (itInfo != frameInfo_.end())\n-\t\treturn itInfo->second.get();\n-\n-\tLOG(IPU3, Fatal) << \"Can't find tracking information for frame \" << id;\n-\n-\treturn nullptr;\n-}\n-\n-IPU3Frames::Info *IPU3Frames::find(FrameBuffer *buffer)\n-{\n-\tfor (auto const &itInfo : frameInfo_) {\n-\t\tInfo *info = itInfo.second.get();\n-\n-\t\tfor (auto const itBuffers : info->request->buffers())\n-\t\t\tif (itBuffers.second == buffer)\n-\t\t\t\treturn info;\n-\n-\t\tif (info->rawBuffer == buffer || info->paramBuffer == buffer ||\n-\t\t    info->statBuffer == buffer)\n-\t\t\treturn info;\n-\t}\n-\n-\tLOG(IPU3, Fatal) << \"Can't find tracking information from buffer\";\n-\n-\treturn nullptr;\n-}\n-\n-} /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/ipu3/frames.h b/src/libcamera/pipeline/ipu3/frames.h\ndeleted file mode 100644\nindex 6e3cb915c7b8..000000000000\n--- a/src/libcamera/pipeline/ipu3/frames.h\n+++ /dev/null\n@@ -1,67 +0,0 @@\n-/* SPDX-License-Identifier: LGPL-2.1-or-later */\n-/*\n- * Copyright (C) 2020, Google Inc.\n- *\n- * frames.h - Intel IPU3 Frames helper\n- */\n-\n-#pragma once\n-\n-#include <map>\n-#include <memory>\n-#include <queue>\n-#include <vector>\n-\n-#include <libcamera/base/signal.h>\n-\n-#include <libcamera/controls.h>\n-\n-namespace libcamera {\n-\n-class FrameBuffer;\n-class IPAProxy;\n-class PipelineHandler;\n-class Request;\n-class V4L2VideoDevice;\n-struct IPABuffer;\n-\n-class IPU3Frames\n-{\n-public:\n-\tstruct Info {\n-\t\tunsigned int id;\n-\t\tRequest *request;\n-\n-\t\tFrameBuffer *rawBuffer;\n-\t\tFrameBuffer *paramBuffer;\n-\t\tFrameBuffer *statBuffer;\n-\n-\t\tControlList effectiveSensorControls;\n-\n-\t\tbool paramDequeued;\n-\t\tbool metadataProcessed;\n-\t};\n-\n-\tIPU3Frames();\n-\n-\tvoid init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuffers,\n-\t\t  const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers);\n-\tvoid clear();\n-\n-\tInfo *create(Request *request);\n-\tvoid remove(Info *info);\n-\tbool tryComplete(Info *info);\n-\n-\tInfo *find(unsigned int id);\n-\tInfo *find(FrameBuffer *buffer);\n-\n-\tSignal<> bufferAvailable;\n-\n-private:\n-\tstd::queue<FrameBuffer *> availableParamBuffers_;\n-\tstd::queue<FrameBuffer *> availableStatBuffers_;\n-\n-\tstd::map<unsigned int, std::unique_ptr<Info>> frameInfo_;\n-};\n-\n-} /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex fa4bd0bb73e2..f61e4a10892e 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -34,9 +34,9 @@\n #include \"libcamera/internal/ipa_manager.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n \n #include \"cio2.h\"\n-#include \"frames.h\"\n #include \"imgu.h\"\n \n namespace libcamera {\n@@ -47,6 +47,24 @@ static const ControlInfoMap::Map IPU3Controls = {\n \t{ &controls::draft::PipelineDepth, ControlInfo(2, 3) },\n };\n \n+class IPU3Request : public Request::Private\n+{\n+public:\n+\tIPU3Request(Camera *camera)\n+\t\t: Request::Private(camera)\n+\t{\n+\t}\n+\n+\tFrameBuffer *rawBuffer;\n+\tFrameBuffer *paramBuffer;\n+\tFrameBuffer *statBuffer;\n+\n+\tControlList effectiveSensorControls;\n+\n+\tbool paramDequeued;\n+\tbool metadataProcessed;\n+};\n+\n class IPU3CameraData : public Camera::Private\n {\n public:\n@@ -57,6 +75,7 @@ public:\n \n \tint loadIPA();\n \n+\tvoid tryCompleteRequest(IPU3Request *request);\n \tvoid imguOutputBufferReady(FrameBuffer *buffer);\n \tvoid cio2BufferReady(FrameBuffer *buffer);\n \tvoid paramBufferReady(FrameBuffer *buffer);\n@@ -75,7 +94,6 @@ public:\n \tRectangle cropRegion_;\n \n \tstd::unique_ptr<DelayedControls> delayedCtrls_;\n-\tIPU3Frames frameInfos_;\n \n \tstd::unique_ptr<ipa::ipu3::IPAProxyIPU3> ipa_;\n \n@@ -86,7 +104,17 @@ public:\n \n \tControlInfoMap ipaControls_;\n \n+\tstd::map<unsigned int, IPU3Request *> requestMap_;\n+\n+\tstd::queue<FrameBuffer *> availableParamBuffers_;\n+\tstd::queue<FrameBuffer *> availableStatBuffers_;\n+\n private:\n+\tIPU3Request *cameraRequest(Request *request)\n+\t{\n+\t\treturn static_cast<IPU3Request *>(request->_d());\n+\t}\n+\n \tvoid metadataReady(unsigned int id, const ControlList &metadata);\n \tvoid paramsBufferReady(unsigned int id);\n \tvoid setSensorControls(unsigned int id, const ControlList &sensorControls,\n@@ -144,6 +172,8 @@ public:\n \tint start(Camera *camera, const ControlList *controls) override;\n \tvoid stopDevice(Camera *camera) override;\n \n+\tstd::unique_ptr<Request> createRequestDevice(Camera *camera,\n+\t\t\t\t\t\t     uint64_t cookie) override;\n \tint queueRequestDevice(Camera *camera, Request *request) override;\n \n \tbool match(DeviceEnumerator *enumerator) override;\n@@ -154,6 +184,11 @@ private:\n \t\treturn static_cast<IPU3CameraData *>(camera->_d());\n \t}\n \n+\tIPU3Request *cameraRequest(Request *request)\n+\t{\n+\t\treturn static_cast<IPU3Request *>(request->_d());\n+\t}\n+\n \tint initControls(IPU3CameraData *data);\n \tint updateControls(IPU3CameraData *data);\n \tint registerCameras();\n@@ -680,19 +715,17 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera)\n \tfor (const std::unique_ptr<FrameBuffer> &buffer : imgu->paramBuffers_) {\n \t\tbuffer->setCookie(ipaBufferId++);\n \t\tipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());\n+\t\tdata->availableParamBuffers_.push(buffer.get());\n \t}\n \n \tfor (const std::unique_ptr<FrameBuffer> &buffer : imgu->statBuffers_) {\n \t\tbuffer->setCookie(ipaBufferId++);\n \t\tipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());\n+\t\tdata->availableStatBuffers_.push(buffer.get());\n \t}\n \n \tdata->ipa_->mapBuffers(ipaBuffers_);\n \n-\tdata->frameInfos_.init(imgu->paramBuffers_, imgu->statBuffers_);\n-\tdata->frameInfos_.bufferAvailable.connect(\n-\t\tdata, &IPU3CameraData::queuePendingRequests);\n-\n \treturn 0;\n }\n \n@@ -700,8 +733,6 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera)\n {\n \tIPU3CameraData *data = cameraData(camera);\n \n-\tdata->frameInfos_.clear();\n-\n \tstd::vector<unsigned int> ids;\n \tfor (IPABuffer &ipabuf : ipaBuffers_)\n \t\tids.push_back(ipabuf.id);\n@@ -777,6 +808,7 @@ void PipelineHandlerIPU3::stopDevice(Camera *camera)\n \t\tLOG(IPU3, Warning) << \"Failed to stop camera \" << camera->id();\n \n \tfreeBuffers(camera);\n+\tdata->requestMap_.clear();\n }\n \n void IPU3CameraData::cancelPendingRequests()\n@@ -801,37 +833,80 @@ void IPU3CameraData::queuePendingRequests()\n {\n \twhile (!pendingRequests_.empty()) {\n \t\tRequest *request = pendingRequests_.front();\n+\t\tIPU3Request *ipu3Request = cameraRequest(request);\n \n-\t\tIPU3Frames::Info *info = frameInfos_.create(request);\n-\t\tif (!info)\n-\t\t\tbreak;\n+\t\t/*\n+\t\t * The IPU3 pipeline associates buffers with the request\n+\t\t * sequence.\n+\t\t */\n+\t\trequestMap_[request->sequence()] = ipu3Request;\n \n \t\t/*\n \t\t * Queue a buffer on the CIO2, using the raw stream buffer\n \t\t * provided in the request, if any, or a CIO2 internal buffer\n \t\t * otherwise.\n+\t\t *\n+\t\t * No need to set a buffer->setRequest() as\n+\t\t * a) If the buffer is provided by the application that's\n+\t\t *    already been done\n+\t\t * b) If the buffer comes from the CIO2 internal pool,\n+\t\t *    CIO2Device::queueBuffer() does that for us\n \t\t */\n \t\tFrameBuffer *reqRawBuffer = request->findBuffer(&rawStream_);\n \t\tFrameBuffer *rawBuffer = cio2_.queueBuffer(request, reqRawBuffer);\n+\n \t\t/*\n \t\t * \\todo If queueBuffer fails in queuing a buffer to the device,\n \t\t * report the request as error by cancelling the request and\n \t\t * calling PipelineHandler::completeRequest().\n \t\t */\n-\t\tif (!rawBuffer) {\n-\t\t\tframeInfos_.remove(info);\n+\t\tif (!rawBuffer)\n+\t\t\tbreak;\n+\n+\t\t/*\n+\t\t * Store the raw buffer queued to the CIO2 to queue it to the\n+\t\t * Imgu input when the IPA has prepared the paramters buffer.\n+\t\t */\n+\t\tipu3Request->rawBuffer = rawBuffer;\n+\n+\t\t/*\n+\t\t * Prepare the stats and parameters buffer and associate it\n+\t\t * with the currently queued request.\n+\t\t */\n+\t\tif (availableParamBuffers_.empty()) {\n+\t\t\tLOG(IPU3, Debug) << \"Parameters buffer underrun\";\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (availableStatBuffers_.empty()) {\n+\t\t\tLOG(IPU3, Debug) << \"Statistics buffer underrun\";\n \t\t\tbreak;\n \t\t}\n \n-\t\tinfo->rawBuffer = rawBuffer;\n+\t\tipu3Request->paramBuffer = availableParamBuffers_.front();\n+\t\tipu3Request->paramDequeued = false;\n+\t\tipu3Request->paramBuffer->_d()->setRequest(request);\n+\t\tavailableParamBuffers_.pop();\n \n-\t\tipa_->queueRequest(info->id, request->controls());\n+\t\tipu3Request->statBuffer = availableStatBuffers_.front();\n+\t\tipu3Request->metadataProcessed = false;\n+\t\tipu3Request->statBuffer->_d()->setRequest(request);\n+\t\tavailableStatBuffers_.pop();\n+\n+\t\tipa_->queueRequest(request->sequence(), request->controls());\n \n \t\tpendingRequests_.pop();\n \t\tprocessingRequests_.push(request);\n \t}\n }\n \n+std::unique_ptr<Request> PipelineHandlerIPU3::createRequestDevice(Camera *camera,\n+\t\t\t\t\t\t\t\t  uint64_t cookie)\n+{\n+\tauto request = std::make_unique<IPU3Request>(camera);\n+\treturn Request::create(std::move(request), cookie);\n+}\n+\n int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)\n {\n \tIPU3CameraData *data = cameraData(camera);\n@@ -1200,6 +1275,26 @@ int IPU3CameraData::loadIPA()\n \treturn 0;\n }\n \n+void IPU3CameraData::tryCompleteRequest(IPU3Request *request)\n+{\n+\tif (request->hasPendingBuffers())\n+\t\treturn;\n+\n+\tif (!request->metadataProcessed)\n+\t\treturn;\n+\n+\tif (!request->paramDequeued)\n+\t\treturn;\n+\n+\tavailableParamBuffers_.push(request->paramBuffer);\n+\tavailableStatBuffers_.push(request->statBuffer);\n+\n+\tpipe()->completeRequest(request->_o<Request>());\n+\n+\t/* Try queue another request now that this one has completed. */\n+\tqueuePendingRequests();\n+}\n+\n void IPU3CameraData::setSensorControls([[maybe_unused]] unsigned int id,\n \t\t\t\t       const ControlList &sensorControls,\n \t\t\t\t       const ControlList &lensControls)\n@@ -1220,12 +1315,10 @@ void IPU3CameraData::setSensorControls([[maybe_unused]] unsigned int id,\n \n void IPU3CameraData::paramsBufferReady(unsigned int id)\n {\n-\tIPU3Frames::Info *info = frameInfos_.find(id);\n-\tif (!info)\n-\t\treturn;\n+\tIPU3Request *request = requestMap_[id];\n \n \t/* Queue all buffers from the request aimed for the ImgU. */\n-\tfor (auto it : info->request->buffers()) {\n+\tfor (auto it : request->_o<Request>()->buffers()) {\n \t\tconst Stream *stream = it.first;\n \t\tFrameBuffer *outbuffer = it.second;\n \n@@ -1235,25 +1328,21 @@ void IPU3CameraData::paramsBufferReady(unsigned int id)\n \t\t\timgu_->viewfinder_->queueBuffer(outbuffer);\n \t}\n \n-\tinfo->paramBuffer->_d()->metadata().planes()[0].bytesused =\n+\trequest->paramBuffer->_d()->metadata().planes()[0].bytesused =\n \t\tsizeof(struct ipu3_uapi_params);\n-\timgu_->param_->queueBuffer(info->paramBuffer);\n-\timgu_->stat_->queueBuffer(info->statBuffer);\n-\timgu_->input_->queueBuffer(info->rawBuffer);\n+\timgu_->param_->queueBuffer(request->paramBuffer);\n+\timgu_->stat_->queueBuffer(request->statBuffer);\n+\timgu_->input_->queueBuffer(request->rawBuffer);\n }\n \n void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)\n {\n-\tIPU3Frames::Info *info = frameInfos_.find(id);\n-\tif (!info)\n-\t\treturn;\n+\tIPU3Request *request = requestMap_[id];\n \n-\tRequest *request = info->request;\n-\trequest->metadata().merge(metadata);\n+\trequest->_o<Request>()->metadata().merge(metadata);\n \n-\tinfo->metadataProcessed = true;\n-\tif (frameInfos_.tryComplete(info))\n-\t\tpipe()->completeRequest(request);\n+\trequest->metadataProcessed = true;\n+\ttryCompleteRequest(request);\n }\n \n /* -----------------------------------------------------------------------------\n@@ -1268,11 +1357,7 @@ void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)\n  */\n void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)\n {\n-\tIPU3Frames::Info *info = frameInfos_.find(buffer);\n-\tif (!info)\n-\t\treturn;\n-\n-\tRequest *request = info->request;\n+\tRequest *request = buffer->request();\n \n \tpipe()->completeBuffer(request, buffer);\n \n@@ -1283,8 +1368,7 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)\n \t\tcropRegion_ = *scalerCrop;\n \trequest->metadata().set(controls::ScalerCrop, cropRegion_);\n \n-\tif (frameInfos_.tryComplete(info))\n-\t\tpipe()->completeRequest(request);\n+\ttryCompleteRequest(cameraRequest(request));\n }\n \n /**\n@@ -1296,22 +1380,20 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)\n  */\n void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)\n {\n-\tIPU3Frames::Info *info = frameInfos_.find(buffer);\n-\tif (!info)\n-\t\treturn;\n-\n-\tRequest *request = info->request;\n+\tIPU3Request *request = cameraRequest(buffer->request());\n \n \t/* If the buffer is cancelled force a complete of the whole request. */\n \tif (buffer->metadata().status == FrameMetadata::FrameCancelled) {\n-\t\tfor (auto it : request->buffers()) {\n+\t\tfor (auto it : request->_o<Request>()->buffers()) {\n \t\t\tFrameBuffer *b = it.second;\n \t\t\tb->_d()->cancel();\n-\t\t\tpipe()->completeBuffer(request, b);\n+\t\t\tpipe()->completeBuffer(request->_o<Request>(), b);\n \t\t}\n \n-\t\tframeInfos_.remove(info);\n-\t\tpipe()->completeRequest(request);\n+\t\tavailableParamBuffers_.push(request->paramBuffer);\n+\t\tavailableStatBuffers_.push(request->statBuffer);\n+\n+\t\tpipe()->completeRequest(request->_o<Request>());\n \t\treturn;\n \t}\n \n@@ -1321,24 +1403,23 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)\n \t * \\todo The sensor timestamp should be better estimated by connecting\n \t * to the V4L2Device::frameStart signal.\n \t */\n-\trequest->metadata().set(controls::SensorTimestamp,\n-\t\t\t\tbuffer->metadata().timestamp);\n+\trequest->_o<Request>()->metadata().set(controls::SensorTimestamp,\n+\t\t\t\t\t       buffer->metadata().timestamp);\n \n-\tinfo->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence);\n+\trequest->effectiveSensorControls =\n+\t\tdelayedCtrls_->get(buffer->metadata().sequence);\n \n-\tif (request->findBuffer(&rawStream_))\n-\t\tpipe()->completeBuffer(request, buffer);\n+\tif (request->_o<Request>()->findBuffer(&rawStream_))\n+\t\tpipe()->completeBuffer(request->_o<Request>(), buffer);\n \n-\tipa_->fillParamsBuffer(info->id, info->paramBuffer->cookie());\n+\tipa_->fillParamsBuffer(request->_o<Request>()->sequence(),\n+\t\t\t       request->paramBuffer->cookie());\n }\n \n void IPU3CameraData::paramBufferReady(FrameBuffer *buffer)\n {\n-\tIPU3Frames::Info *info = frameInfos_.find(buffer);\n-\tif (!info)\n-\t\treturn;\n-\n-\tinfo->paramDequeued = true;\n+\tIPU3Request *request = cameraRequest(buffer->request());\n+\trequest->paramDequeued = true;\n \n \t/*\n \t * tryComplete() will delete info if it completes the IPU3Frame.\n@@ -1346,35 +1427,25 @@ void IPU3CameraData::paramBufferReady(FrameBuffer *buffer)\n \t *\n \t * \\todo Improve the FrameInfo API to avoid this type of issue\n \t */\n-\tRequest *request = info->request;\n \n-\tif (frameInfos_.tryComplete(info))\n-\t\tpipe()->completeRequest(request);\n+\ttryCompleteRequest(request);\n }\n \n void IPU3CameraData::statBufferReady(FrameBuffer *buffer)\n {\n-\tIPU3Frames::Info *info = frameInfos_.find(buffer);\n-\tif (!info)\n-\t\treturn;\n-\n-\tRequest *request = info->request;\n+\tIPU3Request *request = cameraRequest(buffer->request());\n \n \tif (buffer->metadata().status == FrameMetadata::FrameCancelled) {\n-\t\tinfo->metadataProcessed = true;\n+\t\trequest->metadataProcessed = true;\n \n-\t\t/*\n-\t\t * tryComplete() will delete info if it completes the IPU3Frame.\n-\t\t * In that event, we must have obtained the Request before hand.\n-\t\t */\n-\t\tif (frameInfos_.tryComplete(info))\n-\t\t\tpipe()->completeRequest(request);\n+\t\ttryCompleteRequest(request);\n \n \t\treturn;\n \t}\n \n-\tipa_->processStatsBuffer(info->id, request->metadata().get(controls::SensorTimestamp).value_or(0),\n-\t\t\t\t info->statBuffer->cookie(), info->effectiveSensorControls);\n+\tipa_->processStatsBuffer(request->_o<Request>()->sequence(),\n+\t\t\t\t request->_o<Request>()->metadata().get(controls::SensorTimestamp).value_or(0),\n+\t\t\t\t request->statBuffer->cookie(), request->effectiveSensorControls);\n }\n \n /*\ndiff --git a/src/libcamera/pipeline/ipu3/meson.build b/src/libcamera/pipeline/ipu3/meson.build\nindex a1b0b31ac5bc..d60e07ae6cca 100644\n--- a/src/libcamera/pipeline/ipu3/meson.build\n+++ b/src/libcamera/pipeline/ipu3/meson.build\n@@ -2,7 +2,6 @@\n \n libcamera_sources += files([\n     'cio2.cpp',\n-    'frames.cpp',\n     'imgu.cpp',\n     'ipu3.cpp',\n ])\n","prefixes":["4/5"]}