[{"id":38757,"web_url":"https://patchwork.libcamera.org/comment/38757/","msgid":"<afxCsboXuRWkj63j@zed>","date":"2026-05-07T07:58:39","subject":"Re: [PATCH v3 1/3] pipeline: rpi: Simplify delayed controls","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi David\n\nOn Tue, Apr 28, 2026 at 02:26:37PM +0100, David Plowman wrote:\n> The queueCount_ value is redundant and can be removed.\n>\n> The pipeline handler calls the push and applyControls functions in a\n> an interleaved manner, so queueCount_ was merely tracking writeCount_,\n> and is therefore unnecessary.\n\nIf you're confident that's always going to be the case\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\npush and applyControls are actually triggered by two quite distinct\nevents: frames coming from the sensor produced at regular intervals\nand completion of IPA processing of statistics.\n\nAs long as the pipeline is kept fed with buffers to sustain the\nsensor's frame rate I think that's ok.\n\nWe often discussed the case where system with limited resources\nlike the pi zero only seldom captures frames. Do you keep the IPA\nrunning by feeding it with stats from the FE even if jobs on the BE\nare only scheduled when an output frame is requested ?\n\nIn other words: if the application doesn't keep up with queueing\nrequests fast enough to sustain the sensor's frame rate, will\npush() and applyControls() stay in sync ?\n\n\n>\n> Signed-off-by: David Plowman <david.plowman@raspberrypi.com>\n> ---\n>  .../pipeline/rpi/common/delayed_controls.cpp  | 62 +++++++++++--------\n>  .../pipeline/rpi/common/delayed_controls.h    |  1 -\n>  2 files changed, 36 insertions(+), 27 deletions(-)\n>\n> diff --git a/src/libcamera/pipeline/rpi/common/delayed_controls.cpp b/src/libcamera/pipeline/rpi/common/delayed_controls.cpp\n> index 19c71946..b647174f 100644\n> --- a/src/libcamera/pipeline/rpi/common/delayed_controls.cpp\n> +++ b/src/libcamera/pipeline/rpi/common/delayed_controls.cpp\n> @@ -32,14 +32,15 @@ namespace RPi {\n>   *\n>   * Some sensor controls take effect with a delay as the sensor needs time to\n>   * adjust, for example exposure and analog gain. This is a helper class to deal\n> - * with such controls and the intended users are pipeline handlers.\n> + * with such controls.\n>   *\n> - * The idea is to extend the concept of the buffer depth of a pipeline the\n> - * application needs to maintain to also cover controls. Just as with buffer\n> - * depth if the application keeps the number of requests queued above the\n> - * control depth the controls are guaranteed to take effect for the correct\n> - * request. The control depth is determined by the control with the greatest\n> - * delay.\n> + * The idea is to maintain a queue of controls that have been submitted.\n> + * Whenever a new frame starts, we can \"peak back\" into this queue to send\n> + * controls at the correct number of frames in advance to account for each\n> + * control's delay.\n> + *\n> + * The overall delay for controls becomes the maximum delay of any of the\n> + * controls.\n>   */\n>\n>  /**\n> @@ -119,7 +120,6 @@ DelayedControls::DelayedControls(V4L2Device *device,\n>   */\n>  void DelayedControls::reset(unsigned int cookie)\n>  {\n> -\tqueueCount_ = 1;\n>  \twriteCount_ = 0;\n>  \tcookies_[0] = cookie;\n>\n> @@ -146,18 +146,25 @@ void DelayedControls::reset(unsigned int cookie)\n>   * \\brief Push a set of controls on the queue\n>   * \\param[in] controls List of controls to add to the device queue\n>   *\n> - * Push a set of controls to the control queue. This increases the control queue\n> - * depth by one.\n> + * Push a set of controls to the control queue. The next call to applyControls\n> + * will advance the slot in the queue where the next call to push will write\n> + * controls.\n>   *\n>   * \\returns true if \\a controls are accepted, or false otherwise\n>   */\n>  bool DelayedControls::push(const ControlList &controls, const unsigned int cookie)\n>  {\n>  \t/* Copy state from previous frame. */\n> -\tfor (auto &ctrl : values_) {\n> -\t\tInfo &info = ctrl.second[queueCount_];\n> -\t\tinfo = values_[ctrl.first][queueCount_ - 1];\n> -\t\tinfo.updated = false;\n> +\tif (writeCount_ > 0) {\n> +\t\tfor (auto &ctrl : values_) {\n> +\t\t\tInfo &info = ctrl.second[writeCount_];\n> +\t\t\tinfo = values_[ctrl.first][writeCount_ - 1];\n> +\t\t\tinfo.updated = false;\n> +\t\t}\n> +\t} else {\n> +\t\t/* Although it works, we don't expect this. */\n> +\t\tLOG(RPiDelayedControls, Warning)\n> +\t\t\t<< \"push called before applyControls\";\n>  \t}\n>\n>  \t/* Update with new controls. */\n> @@ -175,18 +182,17 @@ bool DelayedControls::push(const ControlList &controls, const unsigned int cooki\n>  \t\tif (controlParams_.find(id) == controlParams_.end())\n>  \t\t\treturn false;\n>\n> -\t\tInfo &info = values_[id][queueCount_];\n> +\t\tInfo &info = values_[id][writeCount_];\n>\n>  \t\tinfo = Info(control.second);\n>\n>  \t\tLOG(RPiDelayedControls, Debug)\n>  \t\t\t<< \"Queuing \" << id->name()\n>  \t\t\t<< \" to \" << info.toString()\n> -\t\t\t<< \" at index \" << queueCount_;\n> +\t\t\t<< \" at index \" << writeCount_;\n>  \t}\n>\n> -\tcookies_[queueCount_] = cookie;\n> -\tqueueCount_++;\n> +\tcookies_[writeCount_] = cookie;\n>\n>  \treturn true;\n>  }\n> @@ -200,9 +206,9 @@ bool DelayedControls::push(const ControlList &controls, const unsigned int cooki\n>   * the callers responsibility to not read too old sequence numbers that have been\n>   * pushed out of the history.\n>   *\n> - * Historic values are evicted by pushing new values onto the queue using\n> - * push(). The max history from the current sequence number that yields valid\n> - * values are thus 16 minus number of controls pushed.\n> + * Historic values are evicted by new frames arriving and applyControls\n> + * advancing the head of the queue in the ring buffer. The valid history in\n> + * the queue consists of 16 entries from this head of the queue.\n>   *\n>   * \\return The controls at \\a sequence number\n>   */\n> @@ -234,6 +240,10 @@ std::pair<ControlList, unsigned int> DelayedControls::get(uint32_t sequence)\n>   * number. Any user of these helpers is responsible to inform the helper about\n>   * the start of any frame. This can be connected with ease to the start of a\n>   * exposure (SOE) V4L2 event.\n> + *\n> + * Controls will be sent to the device, each staggered by the appropriate\n> + * number of frames for that control, so that they are applied at the same\n> + * time.\n>   */\n>  void DelayedControls::applyControls(uint32_t sequence)\n>  {\n> @@ -277,12 +287,12 @@ void DelayedControls::applyControls(uint32_t sequence)\n>  \t\t}\n>  \t}\n>\n> -\twriteCount_ = sequence + 1;\n> -\n> -\twhile (writeCount_ > queueCount_) {\n> +\twhile (writeCount_ < sequence + 1) {\n> +\t\twriteCount_++;\n>  \t\tLOG(RPiDelayedControls, Debug)\n> -\t\t\t<< \"Queue is empty, auto queue no-op.\";\n> -\t\tpush({}, cookies_[queueCount_ - 1]);\n> +\t\t\t<< \"Pushing noop with for index \" << writeCount_\n> +\t\t\t<< \" with cookie \" << cookies_[writeCount_ - 1];\n> +\t\tpush({}, cookies_[writeCount_ - 1]);\n>  \t}\n>\n>  \tdevice_->setControls(&out);\n> diff --git a/src/libcamera/pipeline/rpi/common/delayed_controls.h b/src/libcamera/pipeline/rpi/common/delayed_controls.h\n> index 487b0057..48ad5a0f 100644\n> --- a/src/libcamera/pipeline/rpi/common/delayed_controls.h\n> +++ b/src/libcamera/pipeline/rpi/common/delayed_controls.h\n> @@ -76,7 +76,6 @@ private:\n>  \tstd::unordered_map<const ControlId *, ControlParams> controlParams_;\n>  \tunsigned int maxDelay_;\n>\n> -\tuint32_t queueCount_;\n>  \tuint32_t writeCount_;\n>  \tstd::unordered_map<const ControlId *, RingBuffer<Info>> values_;\n>  \tRingBuffer<unsigned int> cookies_;\n> --\n> 2.47.3\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 CE532BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  7 May 2026 07:58:44 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 89DBE63020;\n\tThu,  7 May 2026 09:58:43 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2467762FB1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  7 May 2026 09:58:42 +0200 (CEST)","from ideasonboard.com (net-93-65-100-155.cust.vodafonedsl.it\n\t[93.65.100.155])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 2633C5B2;\n\tThu,  7 May 2026 09:58:38 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"nQ3r2nJX\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1778140718;\n\tbh=HX+TvHrH/EP38t2GPP3j8Jlb8y4k2Nn1E+YWlWgq2c0=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=nQ3r2nJXLUKBt3RKnRrwsYzLC2NqJLwGH+voO5yH1f7mEm+Ww3Zv6qtpY1OKMgcsb\n\tJyvYlT7CVhK7cQYj1LAgJ1knCdzJy9/oVn5TYK25S58BnXzIXUc5MHBG6UPG8Fdkpk\n\tIa6hl4qBPBBORN7PY5Z0uXPVnwLSzc51J8pGSgXE=","Date":"Thu, 7 May 2026 09:58:39 +0200","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v3 1/3] pipeline: rpi: Simplify delayed controls","Message-ID":"<afxCsboXuRWkj63j@zed>","References":"<20260428133952.6582-1-david.plowman@raspberrypi.com>\n\t<20260428133952.6582-2-david.plowman@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20260428133952.6582-2-david.plowman@raspberrypi.com>","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>"}},{"id":38761,"web_url":"https://patchwork.libcamera.org/comment/38761/","msgid":"<CAEmqJPqi5GMYN_qQ4ji0SrAE7MmdfvuvtT3oN5Zg-sL1XkU19A@mail.gmail.com>","date":"2026-05-07T08:29:57","subject":"Re: [PATCH v3 1/3] pipeline: rpi: Simplify delayed controls","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Jacopo,\n\nOn Thu, 7 May 2026 at 08:58, Jacopo Mondi <jacopo.mondi@ideasonboard.com>\nwrote:\n\n> Hi David\n>\n> On Tue, Apr 28, 2026 at 02:26:37PM +0100, David Plowman wrote:\n> > The queueCount_ value is redundant and can be removed.\n> >\n> > The pipeline handler calls the push and applyControls functions in a\n> > an interleaved manner, so queueCount_ was merely tracking writeCount_,\n> > and is therefore unnecessary.\n>\n> If you're confident that's always going to be the case\n> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>\n> push and applyControls are actually triggered by two quite distinct\n> events: frames coming from the sensor produced at regular intervals\n> and completion of IPA processing of statistics.\n>\n> As long as the pipeline is kept fed with buffers to sustain the\n> sensor's frame rate I think that's ok.\n>\n\nWhen we underrun the CSI-2 Rx, glitches will inevitably occur, but that's\nunavoidable. So having a glitch in the control/metadata is not the end of\nthe world IMO. It should eventually reach a steady state when we exit the\nunderrun state.\n\n\n>\n> We often discussed the case where system with limited resources\n> like the pi zero only seldom captures frames. Do you keep the IPA\n> running by feeding it with stats from the FE even if jobs on the BE\n> are only scheduled when an output frame is requested ?\n>\n\n> In other words: if the application doesn't keep up with queueing\n> requests fast enough to sustain the sensor's frame rate, will\n> push() and applyControls() stay in sync ?\n>\n\nThe IPA will only run when there are requests to fulfil, and frames\navailable to fulfil them.  In such cases, the push() and applyControls()\nwill stay in sync because we have the concept of a no-op push.\n\nRegards,\nNaush\n\n\n>\n>\n> >\n> > Signed-off-by: David Plowman <david.plowman@raspberrypi.com>\n> > ---\n> >  .../pipeline/rpi/common/delayed_controls.cpp  | 62 +++++++++++--------\n> >  .../pipeline/rpi/common/delayed_controls.h    |  1 -\n> >  2 files changed, 36 insertions(+), 27 deletions(-)\n> >\n> > diff --git a/src/libcamera/pipeline/rpi/common/delayed_controls.cpp\n> b/src/libcamera/pipeline/rpi/common/delayed_controls.cpp\n> > index 19c71946..b647174f 100644\n> > --- a/src/libcamera/pipeline/rpi/common/delayed_controls.cpp\n> > +++ b/src/libcamera/pipeline/rpi/common/delayed_controls.cpp\n> > @@ -32,14 +32,15 @@ namespace RPi {\n> >   *\n> >   * Some sensor controls take effect with a delay as the sensor needs\n> time to\n> >   * adjust, for example exposure and analog gain. This is a helper class\n> to deal\n> > - * with such controls and the intended users are pipeline handlers.\n> > + * with such controls.\n> >   *\n> > - * The idea is to extend the concept of the buffer depth of a pipeline\n> the\n> > - * application needs to maintain to also cover controls. Just as with\n> buffer\n> > - * depth if the application keeps the number of requests queued above\n> the\n> > - * control depth the controls are guaranteed to take effect for the\n> correct\n> > - * request. The control depth is determined by the control with the\n> greatest\n> > - * delay.\n> > + * The idea is to maintain a queue of controls that have been submitted.\n> > + * Whenever a new frame starts, we can \"peak back\" into this queue to\n> send\n> > + * controls at the correct number of frames in advance to account for\n> each\n> > + * control's delay.\n> > + *\n> > + * The overall delay for controls becomes the maximum delay of any of\n> the\n> > + * controls.\n> >   */\n> >\n> >  /**\n> > @@ -119,7 +120,6 @@ DelayedControls::DelayedControls(V4L2Device *device,\n> >   */\n> >  void DelayedControls::reset(unsigned int cookie)\n> >  {\n> > -     queueCount_ = 1;\n> >       writeCount_ = 0;\n> >       cookies_[0] = cookie;\n> >\n> > @@ -146,18 +146,25 @@ void DelayedControls::reset(unsigned int cookie)\n> >   * \\brief Push a set of controls on the queue\n> >   * \\param[in] controls List of controls to add to the device queue\n> >   *\n> > - * Push a set of controls to the control queue. This increases the\n> control queue\n> > - * depth by one.\n> > + * Push a set of controls to the control queue. The next call to\n> applyControls\n> > + * will advance the slot in the queue where the next call to push will\n> write\n> > + * controls.\n> >   *\n> >   * \\returns true if \\a controls are accepted, or false otherwise\n> >   */\n> >  bool DelayedControls::push(const ControlList &controls, const unsigned\n> int cookie)\n> >  {\n> >       /* Copy state from previous frame. */\n> > -     for (auto &ctrl : values_) {\n> > -             Info &info = ctrl.second[queueCount_];\n> > -             info = values_[ctrl.first][queueCount_ - 1];\n> > -             info.updated = false;\n> > +     if (writeCount_ > 0) {\n> > +             for (auto &ctrl : values_) {\n> > +                     Info &info = ctrl.second[writeCount_];\n> > +                     info = values_[ctrl.first][writeCount_ - 1];\n> > +                     info.updated = false;\n> > +             }\n> > +     } else {\n> > +             /* Although it works, we don't expect this. */\n> > +             LOG(RPiDelayedControls, Warning)\n> > +                     << \"push called before applyControls\";\n> >       }\n> >\n> >       /* Update with new controls. */\n> > @@ -175,18 +182,17 @@ bool DelayedControls::push(const ControlList\n> &controls, const unsigned int cooki\n> >               if (controlParams_.find(id) == controlParams_.end())\n> >                       return false;\n> >\n> > -             Info &info = values_[id][queueCount_];\n> > +             Info &info = values_[id][writeCount_];\n> >\n> >               info = Info(control.second);\n> >\n> >               LOG(RPiDelayedControls, Debug)\n> >                       << \"Queuing \" << id->name()\n> >                       << \" to \" << info.toString()\n> > -                     << \" at index \" << queueCount_;\n> > +                     << \" at index \" << writeCount_;\n> >       }\n> >\n> > -     cookies_[queueCount_] = cookie;\n> > -     queueCount_++;\n> > +     cookies_[writeCount_] = cookie;\n> >\n> >       return true;\n> >  }\n> > @@ -200,9 +206,9 @@ bool DelayedControls::push(const ControlList\n> &controls, const unsigned int cooki\n> >   * the callers responsibility to not read too old sequence numbers that\n> have been\n> >   * pushed out of the history.\n> >   *\n> > - * Historic values are evicted by pushing new values onto the queue\n> using\n> > - * push(). The max history from the current sequence number that yields\n> valid\n> > - * values are thus 16 minus number of controls pushed.\n> > + * Historic values are evicted by new frames arriving and applyControls\n> > + * advancing the head of the queue in the ring buffer. The valid\n> history in\n> > + * the queue consists of 16 entries from this head of the queue.\n> >   *\n> >   * \\return The controls at \\a sequence number\n> >   */\n> > @@ -234,6 +240,10 @@ std::pair<ControlList, unsigned int>\n> DelayedControls::get(uint32_t sequence)\n> >   * number. Any user of these helpers is responsible to inform the\n> helper about\n> >   * the start of any frame. This can be connected with ease to the start\n> of a\n> >   * exposure (SOE) V4L2 event.\n> > + *\n> > + * Controls will be sent to the device, each staggered by the\n> appropriate\n> > + * number of frames for that control, so that they are applied at the\n> same\n> > + * time.\n> >   */\n> >  void DelayedControls::applyControls(uint32_t sequence)\n> >  {\n> > @@ -277,12 +287,12 @@ void DelayedControls::applyControls(uint32_t\n> sequence)\n> >               }\n> >       }\n> >\n> > -     writeCount_ = sequence + 1;\n> > -\n> > -     while (writeCount_ > queueCount_) {\n> > +     while (writeCount_ < sequence + 1) {\n> > +             writeCount_++;\n> >               LOG(RPiDelayedControls, Debug)\n> > -                     << \"Queue is empty, auto queue no-op.\";\n> > -             push({}, cookies_[queueCount_ - 1]);\n> > +                     << \"Pushing noop with for index \" << writeCount_\n> > +                     << \" with cookie \" << cookies_[writeCount_ - 1];\n> > +             push({}, cookies_[writeCount_ - 1]);\n> >       }\n> >\n> >       device_->setControls(&out);\n> > diff --git a/src/libcamera/pipeline/rpi/common/delayed_controls.h\n> b/src/libcamera/pipeline/rpi/common/delayed_controls.h\n> > index 487b0057..48ad5a0f 100644\n> > --- a/src/libcamera/pipeline/rpi/common/delayed_controls.h\n> > +++ b/src/libcamera/pipeline/rpi/common/delayed_controls.h\n> > @@ -76,7 +76,6 @@ private:\n> >       std::unordered_map<const ControlId *, ControlParams>\n> controlParams_;\n> >       unsigned int maxDelay_;\n> >\n> > -     uint32_t queueCount_;\n> >       uint32_t writeCount_;\n> >       std::unordered_map<const ControlId *, RingBuffer<Info>> values_;\n> >       RingBuffer<unsigned int> cookies_;\n> > --\n> > 2.47.3\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 61574BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  7 May 2026 08:30:39 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0E6986301E;\n\tThu,  7 May 2026 10:30:38 +0200 (CEST)","from mail-vk1-xa31.google.com (mail-vk1-xa31.google.com\n\t[IPv6:2607:f8b0:4864:20::a31])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4400C62FB1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  7 May 2026 10:30:36 +0200 (CEST)","by mail-vk1-xa31.google.com with SMTP id\n\t71dfb90a1353d-57550c18d5eso28754e0c.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 07 May 2026 01:30:36 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"gESGU9dk\"; dkim-atps=neutral","ARC-Seal":"i=1; a=rsa-sha256; t=1778142635; cv=none;\n\td=google.com; s=arc-20240605;\n\tb=aQYp+nX1VAjSKGtXmcnXD+vaWcqcJIL0TUp2fmfkECTPxA75Eb5R3E1RA8uZe/Q6VK\n\t8A6yAgymXAT2W4KkksnLTkUmwLgrklUG3SPv3mXjYU4+X4ND6SiFxvDASiJfyYdJBVih\n\tlqZqNdAQxJ+eh8zEtVAYC1DiYtntXvN0/hVhRzF/x8ijr7M567lkL7B21OjnxY7myInf\n\trcpduBgXw8XZ5L6WQbCu2nr0De0dAnfxF3S/IbwmK1sB4j0CGSaDt9xvu1fcHmdXZaqQ\n\tD9Zvz1qn2VU1qYhzig5dL4h2H2w7J3INxkcHRmVkJZVaOHnPOshxkHXHgMj4OmokvUSP\n\tl72g==","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;\n\ts=arc-20240605; \n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:dkim-signature;\n\tbh=HdgaqOvZlQfSQivgU11FVPsKQ4uaRtpbPEqCvrLnqQk=;\n\tfh=ysCvZYSDUxIDiiqgI0zHEc5xQ97GM0cIfV8+T8ZXuUU=;\n\tb=K53jKn4sxiC9lo8CO3etpQc7yWTDlTXtHaAkUJcPXzsQAt/BqDbbUyCYqRLEUhCKUJ\n\t/Qv9cGS2IRIjFH8WUocBO7v//uEjiws2rB1SsknxlnAhFM64wrR4Q8hP5+QmJJoWaCGm\n\tsyXQh86GcDpq8Pri+l92sDYQOXKqYFA8uvP15EE4ENLL1phoL8TvvB2ifyUbg+QyZ1u8\n\teruxUR5phwA8HBIEBQSryldJNtCjhamP7iIG4BIkxLhn30kegf5onoG2Zosl/4mribcV\n\t/LRaPVKrpj0jNqY3CY91536EGRYJ+1Rqf9Ay0OYWDzjezjhg8nc1xlwfe3K9Ynfp6b/m\n\t+HgA==; darn=lists.libcamera.org","ARC-Authentication-Results":"i=1; mx.google.com; arc=none","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1778142635; x=1778747435;\n\tdarn=lists.libcamera.org; \n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=HdgaqOvZlQfSQivgU11FVPsKQ4uaRtpbPEqCvrLnqQk=;\n\tb=gESGU9dk1V5SxBXIgtJlA9m1KhQ7XjDRortZvXK51AjkAL7+8V+X0/nAXZnuUc2UDv\n\ty6dCF+NYNotB/rxxrle0bsjmYk15qlgbH5li7Bgc5XKTIXRjfKWh4u2dxfOrUcB1Pgwz\n\tq2xM0uMk0osnndLe+u2e4taCJ4k9/QOMBIGHJe1wEFMB19kzidPVny1rB8+MyhZe7+ga\n\tYYiuaMD895ZrAAM5O1pUlWeIL/yaEVHRLze3fW/F/IwpPbKryXXBctImzFPMt7vzrnE9\n\tj/X4JtR9+9kgHROPZ5znBg2PHTgpVhCPnVg2rCE/KU3XSu4m8nY8rbSW8lR5XIlw7F0P\n\tiS1g==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1778142635; x=1778747435;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=HdgaqOvZlQfSQivgU11FVPsKQ4uaRtpbPEqCvrLnqQk=;\n\tb=TSF+SyJYqubR4aeJHwGMFwG1GNlYAUKtcSIeUvrDk0nD8gQHHE/W0DEnbtSqpe8YPR\n\tztHkx0/ZP7XsfFxlcyYPPDMEN2pvjeSCKw39BGaLF053fyfCjDHmVi9var1mdljlRyRk\n\ts87B3ULaHntD1BCSzJAzKf83FDT8TGksH9Zw18HN2s7ErVDrMYBxjcaIiUFUHi/okbSi\n\tVLvRIyvjyJA9pS7zOT4Z63IZcbthVrm9VFI/C2kCPI0JGLvrxK/BWP031OKYfqabN977\n\tSI0Ighec+z8I7+oGDk3n8JkK0EDOrqUY06zditLWIRSDsZEDD+DA9J3p9t1ZGTbL7maI\n\tXXjg==","X-Forwarded-Encrypted":"i=1;\n\tAFNElJ+XUSF8lW+d+RkBIyZj3w1RoGLhMi5/qbv0HdY/tUby2QB4u7suB9TC30uK47CeiG1Ply9MuzE/jgE5OmM+HPw=@lists.libcamera.org","X-Gm-Message-State":"AOJu0Ywn5/Z0cy6sLnoF+IcDttgjHL1rW85EnTDSd+Q9BgjSj88/8Inu\n\t8iIiPxvwUQDqh5HfLDbYw/8asN66b8/Q1yq9mvdPDL8binf0Zy0+G/KkvmPa+opW/OrMhvWaVPv\n\td2QMzntHPY6sR3yCOAHm70Ii8gpzOyTjwQmrJw2xG0MiMC/US/pzpWR6k0kJt","X-Gm-Gg":"AeBDiesZsENRtDJs3YdLxWKxcXnsN5z/x/xCy4kANmPFnlwgmLq+tqU02Wha304IB7h\n\t5USUWgtfRfkf+WVMTrQEUrTkPcJefB+aD74wIgxyeUJIflLm4qA/tt8pdHl+HeFCEv1fbV0addY\n\tAlbxuRDLtFmwuk7VxSNDx+L1LGxhckIc0oYZVb1Y6beWPGA9o0zM9p+n3Lanp+u99xx2GUMQMEA\n\tRffdHdCIU6/OoHMr6bUh3GaUFJ41eizgC6fBD/qAyX/76waNYBnrm5ABrInY/99VH7tmZ96ZycT\n\tZOV3jxeJADrVbraaPUo2n8JUM2N/EEyvVee+1XGMzma1Qm6Wv52GFeL9fHYp1KdlbJD1qlkpipe\n\tJoPfoba0WQQplMMm3QPvThRmnqaH3GU/RvhNdi4FEYXXcjlxUgklIEgz92GuNr3MsjMnVYRvwiz\n\tN1+3bFyLTPBDLNzGubWvgzbITlKQ114YUoCA==","X-Received":"by 2002:a05:6122:5017:b0:575:24c1:f668 with SMTP id\n\t71dfb90a1353d-5755b2b0d03mr1192141e0c.1.1778142634832;\n\tThu, 07 May 2026 01:30:34 -0700 (PDT)","MIME-Version":"1.0","References":"<20260428133952.6582-1-david.plowman@raspberrypi.com>\n\t<20260428133952.6582-2-david.plowman@raspberrypi.com>\n\t<afxCsboXuRWkj63j@zed>","In-Reply-To":"<afxCsboXuRWkj63j@zed>","From":"Naushir Patuck <naush@raspberrypi.com>","Date":"Thu, 7 May 2026 09:29:57 +0100","X-Gm-Features":"AVHnY4LuZUmsUSFPcuME9_S9YYne74aKnV29NzAI_vbpOKlJBg6MQIoQKJ2JboM","Message-ID":"<CAEmqJPqi5GMYN_qQ4ji0SrAE7MmdfvuvtT3oN5Zg-sL1XkU19A@mail.gmail.com>","Subject":"Re: [PATCH v3 1/3] pipeline: rpi: Simplify delayed controls","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"David Plowman <david.plowman@raspberrypi.com>,\n\tlibcamera-devel@lists.libcamera.org","Content-Type":"multipart/alternative; boundary=\"0000000000001c06dd065136184d\"","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>"}}]