[{"id":28868,"web_url":"https://patchwork.libcamera.org/comment/28868/","msgid":"<11a12d59-4fe8-469e-9162-45d803afc82c@ideasonboard.com>","date":"2024-03-05T13:31:19","subject":"Re: [PATCH 4/5] libcamera: ipu3: Replace IPU3FrameInfo","submitter":{"id":156,"url":"https://patchwork.libcamera.org/api/people/156/","name":"Dan Scally","email":"dan.scally@ideasonboard.com"},"content":"Hi Jacopo\n\nOn 21/02/2024 17:40, Jacopo Mondi wrote:\n> Now that the pipeline handler can create a private derived class of\n> Request::Private, use it to store the pipeline specific data.\n>\n> In the case of IPU3 we associate statistics and paramters buffer with a\n> Request and a raw buffer which gets dequeued from the CIO2 and input\n> to the ImgU input.\n>\n> This replaces the functionalities of IPU3FrameInfo which can now be\n> removed.\n>\n> Signed-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\n>\n> diff --git a/src/libcamera/pipeline/ipu3/frames.cpp b/src/libcamera/pipeline/ipu3/frames.cpp\n> deleted file mode 100644\n> index 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 */\n> diff --git a/src/libcamera/pipeline/ipu3/frames.h b/src/libcamera/pipeline/ipu3/frames.h\n> deleted file mode 100644\n> index 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 */\n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index 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\nIs this one used? I think all the instances below are IPU3CameraData::cameraRequest()\n\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 */\nI think the comment's probably unnecessary to someone reading the code as opposed to this series, so \nI'd probably drop it.\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.\ns/paramters/parameters\n> +\t\t */\n> +\t\tipu3Request->rawBuffer = rawBuffer;\n> +\n> +\t\t/*\n> +\t\t * Prepare the stats and parameters buffer and associate it\ns/associate it/associate them\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}\nShould these be warnings, perhaps? If something went wrong and those queues became totally empty \nyou'd just get a silent hang whilst queuePendingRequests() waited for these to be filled otherwise.\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>   /*\n> diff --git a/src/libcamera/pipeline/ipu3/meson.build b/src/libcamera/pipeline/ipu3/meson.build\n> index 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>   ])","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 A5C93BD160\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  5 Mar 2024 13:31:24 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C34C86286F;\n\tTue,  5 Mar 2024 14:31:23 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5B47161C8D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  5 Mar 2024 14:31:22 +0100 (CET)","from [192.168.0.43]\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 31C9463F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  5 Mar 2024 14:31:05 +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=\"MWHNJ3d5\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1709645465;\n\tbh=aezSnv2BfUZgv8naEcXb4nWm8gZc7y8hxc7Ix1L48Vg=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=MWHNJ3d59SWu9Yixs+wFcX9+A9woqeZ78RbQJ3mjli2syGuSTYkN4dWbmRlKQm8kE\n\tOfzfcenvhtYWFtbFVcEoNNMFuJO/2Gcj13RASY+Fm6rXcLx4xp1C5+cfMrxECYtRfZ\n\tvcHrU4+LpzI/EKby+ggC/S/I0vlb4/Zz1x8wOBg0=","Message-ID":"<11a12d59-4fe8-469e-9162-45d803afc82c@ideasonboard.com>","Date":"Tue, 5 Mar 2024 13:31:19 +0000","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 4/5] libcamera: ipu3: Replace IPU3FrameInfo","Content-Language":"en-US","To":"libcamera-devel@lists.libcamera.org","References":"<20240221174015.52958-1-jacopo.mondi@ideasonboard.com>\n\t<20240221174015.52958-5-jacopo.mondi@ideasonboard.com>","From":"Dan Scally <dan.scally@ideasonboard.com>","Autocrypt":"addr=dan.scally@ideasonboard.com; keydata=\n\t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","In-Reply-To":"<20240221174015.52958-5-jacopo.mondi@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]