[{"id":21761,"web_url":"https://patchwork.libcamera.org/comment/21761/","msgid":"<YbPGRAe8IgUYxfRu@pendragon.ideasonboard.com>","date":"2021-12-10T21:27:32","subject":"Re: [libcamera-devel] [PATCH v5 08/11] libcamera: request: Add\n\tRequest::Private::prepare()","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Fri, Dec 10, 2021 at 09:52:36PM +0100, Jacopo Mondi wrote:\n> Add a prepare() function to the Private Request representation.\n> \n> The prepare() function is used by the PipelineHandler class to\n> prepare a Request to be queued to the hardware.\n> \n> The current implementation of prepare() handles the fences associated\n> with the Framebuffers part of a Request. The function starts an event\n> notifier for each of those and emits the Request::prepared signal when\n> all fences have been signalled or an optional timeout has expired.\n> \n> The optional timeout allows to interrupt blocked waits and notify the\n> Request as failed so that it can be cancelled.\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  include/libcamera/internal/request.h |  16 ++++\n>  src/libcamera/request.cpp            | 133 +++++++++++++++++++++++++++\n>  2 files changed, 149 insertions(+)\n> \n> diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h\n> index 1340ffa2a683..1f2499896e23 100644\n> --- a/include/libcamera/internal/request.h\n> +++ b/include/libcamera/internal/request.h\n> @@ -7,10 +7,17 @@\n>  #ifndef __LIBCAMERA_INTERNAL_REQUEST_H__\n>  #define __LIBCAMERA_INTERNAL_REQUEST_H__\n>  \n> +#include <chrono>\n> +#include <map>\n>  #include <memory>\n>  \n> +#include <libcamera/base/event_notifier.h>\n> +#include <libcamera/base/timer.h>\n> +\n>  #include <libcamera/request.h>\n>  \n> +using namespace std::chrono_literals;\n> +\n>  namespace libcamera {\n>  \n>  class Camera;\n> @@ -32,16 +39,25 @@ public:\n>  \tvoid cancel();\n>  \tvoid reuse();\n>  \n> +\tvoid prepare(std::chrono::milliseconds timeout = 0ms);\n> +\tSignal<> prepared;\n> +\n>  private:\n>  \tfriend class PipelineHandler;\n>  \n>  \tvoid doCancelRequest();\n> +\tvoid emitPrepareCompleted();\n> +\tvoid notifierActivated(FrameBuffer *buffer);\n> +\tvoid timeout();\n>  \n>  \tCamera *camera_;\n>  \tbool cancelled_;\n>  \tuint32_t sequence_ = 0;\n> +\tbool prepared_ = false;\n>  \n>  \tstd::unordered_set<FrameBuffer *> pending_;\n> +\tstd::map<FrameBuffer *, std::unique_ptr<EventNotifier>> notifiers_;\n> +\tstd::unique_ptr<Timer> timer_;\n>  };\n>  \n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\n> index 016db9d62340..7e9238dc1eb4 100644\n> --- a/src/libcamera/request.cpp\n> +++ b/src/libcamera/request.cpp\n> @@ -135,6 +135,8 @@ void Request::Private::doCancelRequest()\n>  \n>  \tcancelled_ = true;\n>  \tpending_.clear();\n> +\tnotifiers_.clear();\n> +\ttimer_.reset();\n>  }\n>  \n>  /**\n> @@ -162,7 +164,138 @@ void Request::Private::reuse()\n>  {\n>  \tsequence_ = 0;\n>  \tcancelled_ = false;\n> +\tprepared_ = false;\n>  \tpending_.clear();\n> +\tnotifiers_.clear();\n> +\ttimer_.reset();\n> +}\n> +\n> +/*\n> + * Helper function to save some lines of code and make sure prepared_ is set\n> + * to true before emitting the signal.\n> + */\n> +void Request::Private::emitPrepareCompleted()\n> +{\n> +\tprepared_ = true;\n> +\tprepared.emit();\n> +}\n> +\n> +/**\n> + * \\brief Prepare the Request to be queued to the device\n> + * \\param[in] timeout Optional expiration timeout\n> + *\n> + * Prepare a Request to be queued to the hardware device by ensuring it is\n> + * ready for the incoming memory transfers.\n> + *\n> + * This currently means waiting on each frame buffer acquire fence to be\n> + * signalled. An optional expiration timeout can be specified. If not all the\n> + * fences have been signalled correctly before the timeout expires the Request\n> + * is cancelled.\n> + *\n> + * The function immediately emits the prepared signal if all the prepare\n> + * operations have been completed synchronously. If instead the prepare\n> + * operations require to wait the completion of asynchronous events, such as\n> + * fences notifications or timer expiration, the prepared signal is emitted upon\n> + * the asynchronous event completion.\n> + *\n> + * As we currently only handle fences, the function emits the prepared signal\n> + * immediately if there are no fences to wait on. Otherwise the prepared signal\n> + * is emitted when all fences have been signalled or the optional timeout has\n> + * expired.\n> + *\n> + * If not all the fences have been correctly signalled or the optional timeout\n> + * has expired the Request will be cancelled and the Request::prepared signal\n> + * emitted.\n> + *\n> + * The intended user of this function is the PipelineHandler base class, which\n> + * 'prepares' a Request before queuing it to the hardware device.\n> + */\n> +void Request::Private::prepare(std::chrono::milliseconds timeout)\n> +{\n> +\t/* Create and connect one notifier for each synchronization fence. */\n> +\tfor (FrameBuffer *buffer : pending_) {\n> +\t\tconst Fence *fence = buffer->_d()->fence();\n> +\t\tif (!fence)\n> +\t\t\tcontinue;\n> +\n> +\t\tstd::unique_ptr<EventNotifier> notifier =\n> +\t\t\tstd::make_unique<EventNotifier>(fence->fd().get(),\n> +\t\t\t\t\t\t\tEventNotifier::Read);\n> +\n> +\t\tnotifier->activated.connect(this, [this, buffer] {\n> +\t\t\t\t\t\t\tnotifierActivated(buffer);\n> +\t\t\t\t\t    });\n> +\n> +\t\tnotifiers_[buffer] = std::move(notifier);\n> +\t}\n> +\n> +\tif (notifiers_.empty()) {\n> +\t\temitPrepareCompleted();\n> +\t\treturn;\n> +\t}\n> +\n> +\t/*\n> +\t * In case a timeout is specified, create a timer and set it up.\n> +\t *\n> +\t * The timer must be created here instead of in the Request constructor,\n> +\t * in order to be bound to the pipeline handler thread.\n> +\t */\n> +\tif (timeout == 0ms) {\n\nThis was\n\n\tif (timeout != 0ms) {\n\nin the previous version.\n\n\tif (timeout) {\n\nwould work too, but \n\n\tif (timeout == 0ms) {\n\nis probably not what you want.\n\nBy the way, a timer with a 0ms timeout is a simple way to get a function\ncalled as soon as control goes back to the event loop, if you ever find\nyourself in the need of that.\n\n> +\t\ttimer_ = std::make_unique<Timer>();\n> +\t\ttimer_->timeout.connect(this, &Request::Private::timeout);\n> +\t\ttimer_->start(timeout);\n> +\t}\n> +}\n> +\n> +/**\n> + * \\var Request::Private::prepared\n> + * \\brief Request preparation completed Signal\n> + *\n> + * The signal is emitted once the request preparation has completed and is ready\n> + * to be queued. The Request might complete with errors in which case it is\n> + * cancelled.\n> + *\n> + * The intended slot for this signal is the PipelineHandler::doQueueRequests()\n> + * function which queues Request after they have been prepared or cancel them\n> + * if they have failed preparing.\n> + */\n> +\n> +void Request::Private::notifierActivated(FrameBuffer *buffer)\n> +{\n> +\t/* Close the fence if successfully signalled. */\n> +\tASSERT(buffer);\n> +\tbuffer->releaseFence();\n> +\n> +\t/* Remove the entry from the map and check if other fences are pending. */\n> +\tauto it = notifiers_.find(buffer);\n> +\tASSERT(it != notifiers_.end());\n> +\tnotifiers_.erase(it);\n> +\n> +\tRequest *request = _o<Request>();\n> +\tLOG(Request, Debug)\n> +\t\t<< \"Request \" << request->cookie() << \" buffer \" << buffer\n> +\t\t<< \" fence signalled\";\n> +\n> +\tif (!notifiers_.empty())\n> +\t\treturn;\n> +\n> +\t/* All fences completed, delete the timer and move to state Ready. */\n> +\ttimer_.reset();\n> +\temitPrepareCompleted();\n> +}\n> +\n> +void Request::Private::timeout()\n> +{\n> +\t/* A timeout can only happen if there are fences not yet signalled. */\n> +\tASSERT(!notifiers_.empty());\n> +\tnotifiers_.clear();\n> +\n> +\tRequest *request = _o<Request>();\n> +\tLOG(Request, Debug) << \"Request prepare timeout: \" << request->cookie();\n> +\n> +\tcancel();\n> +\n> +\temitPrepareCompleted();\n>  }\n>  \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 999AFBF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 10 Dec 2021 21:28:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C3ED060897;\n\tFri, 10 Dec 2021 22:28:03 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 31E0560868\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 10 Dec 2021 22:28:02 +0100 (CET)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8E1DAF84;\n\tFri, 10 Dec 2021 22:28:01 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"dUDG81Q+\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1639171681;\n\tbh=RVxDlTmFMWU7bEddvBpj11M0V24r2Guq3JUO26dc/x0=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=dUDG81Q+Kj4voMdDkY9v9N1UgmMnGLpN8iI4tzf1qFu/pvfPkQxDzlAvfwxAQSlSc\n\tvB9hcRWCA8fMDWONtRb1i7yPfgMbCMgFXRMCYtpJV1qKPcIZ/0E5hYqEupJ4Tv4emT\n\tJGZ4TKuLPglbEhCrKLmljbusSHaXyrc41HD2Iqlc=","Date":"Fri, 10 Dec 2021 23:27:32 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<YbPGRAe8IgUYxfRu@pendragon.ideasonboard.com>","References":"<20211210205239.354901-1-jacopo@jmondi.org>\n\t<20211210205239.354901-9-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20211210205239.354901-9-jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH v5 08/11] libcamera: request: Add\n\tRequest::Private::prepare()","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":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":21767,"web_url":"https://patchwork.libcamera.org/comment/21767/","msgid":"<20211211150139.io37kmd5devpoluo@uno.localdomain>","date":"2021-12-11T15:01:39","subject":"Re: [libcamera-devel] [PATCH v5 08/11] libcamera: request: Add\n\tRequest::Private::prepare()","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent\n\nOn Fri, Dec 10, 2021 at 11:27:32PM +0200, Laurent Pinchart wrote:\n> Hi Jacopo,\n>\n> Thank you for the patch.\n>\n> On Fri, Dec 10, 2021 at 09:52:36PM +0100, Jacopo Mondi wrote:\n> > Add a prepare() function to the Private Request representation.\n> >\n> > The prepare() function is used by the PipelineHandler class to\n> > prepare a Request to be queued to the hardware.\n> >\n> > The current implementation of prepare() handles the fences associated\n> > with the Framebuffers part of a Request. The function starts an event\n> > notifier for each of those and emits the Request::prepared signal when\n> > all fences have been signalled or an optional timeout has expired.\n> >\n> > The optional timeout allows to interrupt blocked waits and notify the\n> > Request as failed so that it can be cancelled.\n> >\n> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  include/libcamera/internal/request.h |  16 ++++\n> >  src/libcamera/request.cpp            | 133 +++++++++++++++++++++++++++\n> >  2 files changed, 149 insertions(+)\n> >\n> > diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h\n> > index 1340ffa2a683..1f2499896e23 100644\n> > --- a/include/libcamera/internal/request.h\n> > +++ b/include/libcamera/internal/request.h\n> > @@ -7,10 +7,17 @@\n> >  #ifndef __LIBCAMERA_INTERNAL_REQUEST_H__\n> >  #define __LIBCAMERA_INTERNAL_REQUEST_H__\n> >\n> > +#include <chrono>\n> > +#include <map>\n> >  #include <memory>\n> >\n> > +#include <libcamera/base/event_notifier.h>\n> > +#include <libcamera/base/timer.h>\n> > +\n> >  #include <libcamera/request.h>\n> >\n> > +using namespace std::chrono_literals;\n> > +\n> >  namespace libcamera {\n> >\n> >  class Camera;\n> > @@ -32,16 +39,25 @@ public:\n> >  \tvoid cancel();\n> >  \tvoid reuse();\n> >\n> > +\tvoid prepare(std::chrono::milliseconds timeout = 0ms);\n> > +\tSignal<> prepared;\n> > +\n> >  private:\n> >  \tfriend class PipelineHandler;\n> >\n> >  \tvoid doCancelRequest();\n> > +\tvoid emitPrepareCompleted();\n> > +\tvoid notifierActivated(FrameBuffer *buffer);\n> > +\tvoid timeout();\n> >\n> >  \tCamera *camera_;\n> >  \tbool cancelled_;\n> >  \tuint32_t sequence_ = 0;\n> > +\tbool prepared_ = false;\n> >\n> >  \tstd::unordered_set<FrameBuffer *> pending_;\n> > +\tstd::map<FrameBuffer *, std::unique_ptr<EventNotifier>> notifiers_;\n> > +\tstd::unique_ptr<Timer> timer_;\n> >  };\n> >\n> >  } /* namespace libcamera */\n> > diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\n> > index 016db9d62340..7e9238dc1eb4 100644\n> > --- a/src/libcamera/request.cpp\n> > +++ b/src/libcamera/request.cpp\n> > @@ -135,6 +135,8 @@ void Request::Private::doCancelRequest()\n> >\n> >  \tcancelled_ = true;\n> >  \tpending_.clear();\n> > +\tnotifiers_.clear();\n> > +\ttimer_.reset();\n> >  }\n> >\n> >  /**\n> > @@ -162,7 +164,138 @@ void Request::Private::reuse()\n> >  {\n> >  \tsequence_ = 0;\n> >  \tcancelled_ = false;\n> > +\tprepared_ = false;\n> >  \tpending_.clear();\n> > +\tnotifiers_.clear();\n> > +\ttimer_.reset();\n> > +}\n> > +\n> > +/*\n> > + * Helper function to save some lines of code and make sure prepared_ is set\n> > + * to true before emitting the signal.\n> > + */\n> > +void Request::Private::emitPrepareCompleted()\n> > +{\n> > +\tprepared_ = true;\n> > +\tprepared.emit();\n> > +}\n> > +\n> > +/**\n> > + * \\brief Prepare the Request to be queued to the device\n> > + * \\param[in] timeout Optional expiration timeout\n> > + *\n> > + * Prepare a Request to be queued to the hardware device by ensuring it is\n> > + * ready for the incoming memory transfers.\n> > + *\n> > + * This currently means waiting on each frame buffer acquire fence to be\n> > + * signalled. An optional expiration timeout can be specified. If not all the\n> > + * fences have been signalled correctly before the timeout expires the Request\n> > + * is cancelled.\n> > + *\n> > + * The function immediately emits the prepared signal if all the prepare\n> > + * operations have been completed synchronously. If instead the prepare\n> > + * operations require to wait the completion of asynchronous events, such as\n> > + * fences notifications or timer expiration, the prepared signal is emitted upon\n> > + * the asynchronous event completion.\n> > + *\n> > + * As we currently only handle fences, the function emits the prepared signal\n> > + * immediately if there are no fences to wait on. Otherwise the prepared signal\n> > + * is emitted when all fences have been signalled or the optional timeout has\n> > + * expired.\n> > + *\n> > + * If not all the fences have been correctly signalled or the optional timeout\n> > + * has expired the Request will be cancelled and the Request::prepared signal\n> > + * emitted.\n> > + *\n> > + * The intended user of this function is the PipelineHandler base class, which\n> > + * 'prepares' a Request before queuing it to the hardware device.\n> > + */\n> > +void Request::Private::prepare(std::chrono::milliseconds timeout)\n> > +{\n> > +\t/* Create and connect one notifier for each synchronization fence. */\n> > +\tfor (FrameBuffer *buffer : pending_) {\n> > +\t\tconst Fence *fence = buffer->_d()->fence();\n> > +\t\tif (!fence)\n> > +\t\t\tcontinue;\n> > +\n> > +\t\tstd::unique_ptr<EventNotifier> notifier =\n> > +\t\t\tstd::make_unique<EventNotifier>(fence->fd().get(),\n> > +\t\t\t\t\t\t\tEventNotifier::Read);\n> > +\n> > +\t\tnotifier->activated.connect(this, [this, buffer] {\n> > +\t\t\t\t\t\t\tnotifierActivated(buffer);\n> > +\t\t\t\t\t    });\n> > +\n> > +\t\tnotifiers_[buffer] = std::move(notifier);\n> > +\t}\n> > +\n> > +\tif (notifiers_.empty()) {\n> > +\t\temitPrepareCompleted();\n> > +\t\treturn;\n> > +\t}\n> > +\n> > +\t/*\n> > +\t * In case a timeout is specified, create a timer and set it up.\n> > +\t *\n> > +\t * The timer must be created here instead of in the Request constructor,\n> > +\t * in order to be bound to the pipeline handler thread.\n> > +\t */\n> > +\tif (timeout == 0ms) {\n>\n> This was\n>\n> \tif (timeout != 0ms) {\n>\n> in the previous version.\n>\n> \tif (timeout) {\n>\n> would work too, but\n>\n> \tif (timeout == 0ms) {\n>\n> is probably not what you want.\n>\n> By the way, a timer with a 0ms timeout is a simple way to get a function\n> called as soon as control goes back to the event loop, if you ever find\n> yourself in the need of that.\n\nOuch, again weird that it doesn't fail.\nAnyway, no, if (timeout) doesn't work\n\n../src/libcamera/request.cpp:243:13: error: could not convert ‘timeout’ from ‘std::chrono::milliseconds’ {aka ‘std::chrono::duration<long int, std::ratio<1, 1000> >’} to ‘bool\n\n>\n> > +\t\ttimer_ = std::make_unique<Timer>();\n> > +\t\ttimer_->timeout.connect(this, &Request::Private::timeout);\n> > +\t\ttimer_->start(timeout);\n> > +\t}\n> > +}\n> > +\n> > +/**\n> > + * \\var Request::Private::prepared\n> > + * \\brief Request preparation completed Signal\n> > + *\n> > + * The signal is emitted once the request preparation has completed and is ready\n> > + * to be queued. The Request might complete with errors in which case it is\n> > + * cancelled.\n> > + *\n> > + * The intended slot for this signal is the PipelineHandler::doQueueRequests()\n> > + * function which queues Request after they have been prepared or cancel them\n> > + * if they have failed preparing.\n> > + */\n> > +\n> > +void Request::Private::notifierActivated(FrameBuffer *buffer)\n> > +{\n> > +\t/* Close the fence if successfully signalled. */\n> > +\tASSERT(buffer);\n> > +\tbuffer->releaseFence();\n> > +\n> > +\t/* Remove the entry from the map and check if other fences are pending. */\n> > +\tauto it = notifiers_.find(buffer);\n> > +\tASSERT(it != notifiers_.end());\n> > +\tnotifiers_.erase(it);\n> > +\n> > +\tRequest *request = _o<Request>();\n> > +\tLOG(Request, Debug)\n> > +\t\t<< \"Request \" << request->cookie() << \" buffer \" << buffer\n> > +\t\t<< \" fence signalled\";\n> > +\n> > +\tif (!notifiers_.empty())\n> > +\t\treturn;\n> > +\n> > +\t/* All fences completed, delete the timer and move to state Ready. */\n> > +\ttimer_.reset();\n> > +\temitPrepareCompleted();\n> > +}\n> > +\n> > +void Request::Private::timeout()\n> > +{\n> > +\t/* A timeout can only happen if there are fences not yet signalled. */\n> > +\tASSERT(!notifiers_.empty());\n> > +\tnotifiers_.clear();\n> > +\n> > +\tRequest *request = _o<Request>();\n> > +\tLOG(Request, Debug) << \"Request prepare timeout: \" << request->cookie();\n> > +\n> > +\tcancel();\n> > +\n> > +\temitPrepareCompleted();\n> >  }\n> >\n> >  /**\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","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 A07A5BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 11 Dec 2021 15:00:49 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EBF576088C;\n\tSat, 11 Dec 2021 16:00:48 +0100 (CET)","from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net\n\t[217.70.183.194])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 02A5960113\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 11 Dec 2021 16:00:46 +0100 (CET)","(Authenticated sender: jacopo@jmondi.org)\n\tby relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 7AE7340002;\n\tSat, 11 Dec 2021 15:00:46 +0000 (UTC)"],"Date":"Sat, 11 Dec 2021 16:01:39 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20211211150139.io37kmd5devpoluo@uno.localdomain>","References":"<20211210205239.354901-1-jacopo@jmondi.org>\n\t<20211210205239.354901-9-jacopo@jmondi.org>\n\t<YbPGRAe8IgUYxfRu@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<YbPGRAe8IgUYxfRu@pendragon.ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v5 08/11] libcamera: request: Add\n\tRequest::Private::prepare()","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":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]