[{"id":16123,"web_url":"https://patchwork.libcamera.org/comment/16123/","msgid":"<20210406124734.sqyzfnzu2okpkotp@uno.localdomain>","date":"2021-04-06T12:47:34","subject":"Re: [libcamera-devel] [PATCH 1/2] android: CameraBuffer: Add option\n\tof not mapping a buffer","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Hiro,\n\nOn Mon, Apr 05, 2021 at 01:04:23PM +0900, Hirokazu Honda wrote:\n> CameraBuffer always maps a buffer in constructor. This adds an\n> option to not map a buffer within CameraBuffer. The option is\n> useful for a caller to only validate a buffer and not have to\n> map the buffer.\n>\n\nAlthough this requires CameraDevice to create a CameraBuffer in\nprocessCaptureRequest() only to validate. Would a static method work\nbetter ? After all if the validation shall happen before mapping, it\nmeans it is based on static attribute of buffer_handle_t\n\nAlso, I don't really like the 'map' flag, as it seems to me if only\nconstruction is required, but not mapping, we should rather split the\ntwo operations in two methods (ie adding an explicit\nCameraBuffer::map() method)\n\nThanks\n  j\n\n\n> Signed-off-by: Hirokazu Honda <hiroh@chromium.org>\n> ---\n>  src/android/camera_buffer.h              |  7 ++++---\n>  src/android/mm/cros_camera_buffer.cpp    | 17 +++++++++++++----\n>  src/android/mm/generic_camera_buffer.cpp | 20 ++++++++++++--------\n>  3 files changed, 29 insertions(+), 15 deletions(-)\n>\n> diff --git a/src/android/camera_buffer.h b/src/android/camera_buffer.h\n> index 7e8970b4..1fdb76a6 100644\n> --- a/src/android/camera_buffer.h\n> +++ b/src/android/camera_buffer.h\n> @@ -17,7 +17,7 @@ class CameraBuffer final : public libcamera::Extensible\n>  \tLIBCAMERA_DECLARE_PRIVATE(CameraBuffer)\n>\n>  public:\n> -\tCameraBuffer(buffer_handle_t camera3Buffer, int flags);\n> +\tCameraBuffer(buffer_handle_t camera3Buffer, int flags, bool map = true);\n>  \t~CameraBuffer();\n>\n>  \tbool isValid() const;\n> @@ -31,8 +31,9 @@ public:\n>  };\n>\n>  #define PUBLIC_CAMERA_BUFFER_IMPLEMENTATION\t\t\t\t\\\n> -CameraBuffer::CameraBuffer(buffer_handle_t camera3Buffer, int flags)\t\\\n> -\t: Extensible(new Private(this, camera3Buffer, flags))\t\t\\\n> +\tCameraBuffer::CameraBuffer(buffer_handle_t camera3Buffer, int flags, \\\n> +\t\t\t\t   bool map)\t\t\t\t\\\n> +\t\t: Extensible(new Private(this, camera3Buffer, flags, map))\\\n>  {\t\t\t\t\t\t\t\t\t\\\n>  }\t\t\t\t\t\t\t\t\t\\\n>  CameraBuffer::~CameraBuffer()\t\t\t\t\t\t\\\n> diff --git a/src/android/mm/cros_camera_buffer.cpp b/src/android/mm/cros_camera_buffer.cpp\n> index 1a4fd5d1..71e03766 100644\n> --- a/src/android/mm/cros_camera_buffer.cpp\n> +++ b/src/android/mm/cros_camera_buffer.cpp\n> @@ -21,7 +21,7 @@ class CameraBuffer::Private : public Extensible::Private\n>\n>  public:\n>  \tPrivate(CameraBuffer *cameraBuffer,\n> -\t\tbuffer_handle_t camera3Buffer, int flags);\n> +\t\tbuffer_handle_t camera3Buffer, int flags, bool map);\n>  \t~Private();\n>\n>  \tbool isValid() const { return valid_; }\n> @@ -38,6 +38,7 @@ private:\n>  \tunsigned int numPlanes_;\n>  \tbool valid_;\n>  \tbool registered_;\n> +\tbool map_;\n>  \tunion {\n>  \t\tvoid *addr;\n>  \t\tandroid_ycbcr ycbcr;\n> @@ -48,9 +49,10 @@ private:\n>  };\n>\n>  CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n> -\t\t\t       buffer_handle_t camera3Buffer, int flags)\n> +\t\t\t       buffer_handle_t camera3Buffer, int flags,\n> +\t\t\t       bool map)\n>  \t: Extensible::Private(cameraBuffer), handle_(camera3Buffer),\n> -\t  numPlanes_(0), valid_(false), registered_(false)\n> +\t  numPlanes_(0), valid_(false), registered_(false), map_(map)\n>  {\n>  \tbufferManager_ = cros::CameraBufferManager::GetInstance();\n>\n> @@ -62,6 +64,13 @@ CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n>\n>  \tregistered_ = true;\n>  \tnumPlanes_ = bufferManager_->GetNumPlanes(camera3Buffer);\n> +\n> +\tmemset(&mem, 0, sizeof(mem));\n> +\tif (!map_) {\n> +\t\tvalid_ = true;\n> +\t\treturn;\n> +\t}\n> +\n>  \tswitch (numPlanes_) {\n>  \tcase 1: {\n>  \t\tret = bufferManager_->Lock(handle_, 0, 0, 0, 0, 0, &mem.addr);\n> @@ -91,7 +100,7 @@ CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n>\n>  CameraBuffer::Private::~Private()\n>  {\n> -\tif (valid_)\n> +\tif (map_ && valid_)\n>  \t\tbufferManager_->Unlock(handle_);\n>  \tif (registered_)\n>  \t\tbufferManager_->Deregister(handle_);\n> diff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp\n> index 929e078a..8fa79889 100644\n> --- a/src/android/mm/generic_camera_buffer.cpp\n> +++ b/src/android/mm/generic_camera_buffer.cpp\n> @@ -21,7 +21,7 @@ class CameraBuffer::Private : public Extensible::Private,\n>\n>  public:\n>  \tPrivate(CameraBuffer *cameraBuffer,\n> -\t\tbuffer_handle_t camera3Buffer, int flags);\n> +\t\tbuffer_handle_t camera3Buffer, int flags, bool map);\n>  \t~Private();\n>\n>  \tunsigned int numPlanes() const;\n> @@ -32,7 +32,8 @@ public:\n>  };\n>\n>  CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n> -\t\t\t       buffer_handle_t camera3Buffer, int flags)\n> +\t\t\t       buffer_handle_t camera3Buffer,\n> +\t\t\t       int flags, bool map)\n>  \t: Extensible::Private(cameraBuffer)\n>  {\n>  \tmaps_.reserve(camera3Buffer->numFds);\n> @@ -49,12 +50,15 @@ CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n>  \t\t\tbreak;\n>  \t\t}\n>\n> -\t\tvoid *address = mmap(nullptr, length, flags, MAP_SHARED,\n> -\t\t\t\t     camera3Buffer->data[i], 0);\n> -\t\tif (address == MAP_FAILED) {\n> -\t\t\terror_ = -errno;\n> -\t\t\tLOG(HAL, Error) << \"Failed to mmap plane\";\n> -\t\t\tbreak;\n> +\t\tvoid *address = nullptr;\n> +\t\tif (map) {\n> +\t\t\tmmap(nullptr, length, flags, MAP_SHARED,\n> +\t\t\t     camera3Buffer->data[i], 0);\n> +\t\t\tif (address == MAP_FAILED) {\n> +\t\t\t\terror_ = -errno;\n> +\t\t\t\tLOG(HAL, Error) << \"Failed to mmap plane\";\n> +\t\t\t\tbreak;\n> +\t\t\t}\n>  \t\t}\n>\n>  \t\tmaps_.emplace_back(static_cast<uint8_t *>(address),\n> --\n> 2.31.0.208.g409f899ff0-goog\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","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 5210EC0DA3\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  6 Apr 2021 12:47:00 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C68B268786;\n\tTue,  6 Apr 2021 14:46:59 +0200 (CEST)","from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net\n\t[217.70.183.200])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id F0CC360518\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  6 Apr 2021 14:46:58 +0200 (CEST)","from uno.localdomain (93-34-118-233.ip49.fastwebnet.it\n\t[93.34.118.233]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 741692000D;\n\tTue,  6 Apr 2021 12:46:58 +0000 (UTC)"],"X-Originating-IP":"93.34.118.233","Date":"Tue, 6 Apr 2021 14:47:34 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Hirokazu Honda <hiroh@chromium.org>","Message-ID":"<20210406124734.sqyzfnzu2okpkotp@uno.localdomain>","References":"<20210405040424.1929737-1-hiroh@chromium.org>\n\t<20210405040424.1929737-2-hiroh@chromium.org>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20210405040424.1929737-2-hiroh@chromium.org>","Subject":"Re: [libcamera-devel] [PATCH 1/2] android: CameraBuffer: Add option\n\tof not mapping a buffer","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","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18975,"web_url":"https://patchwork.libcamera.org/comment/18975/","msgid":"<YR+RPUS2C1Wo6cNL@pendragon.ideasonboard.com>","date":"2021-08-20T11:25:49","subject":"Re: [libcamera-devel] [PATCH 1/2] android: CameraBuffer: Add option\n\tof not mapping a buffer","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hello,\n\nOn Tue, Apr 06, 2021 at 02:47:34PM +0200, Jacopo Mondi wrote:\n> On Mon, Apr 05, 2021 at 01:04:23PM +0900, Hirokazu Honda wrote:\n> > CameraBuffer always maps a buffer in constructor. This adds an\n> > option to not map a buffer within CameraBuffer. The option is\n> > useful for a caller to only validate a buffer and not have to\n> > map the buffer.\n> \n> Although this requires CameraDevice to create a CameraBuffer in\n> processCaptureRequest() only to validate. Would a static method work\n> better ? After all if the validation shall happen before mapping, it\n> means it is based on static attribute of buffer_handle_t\n> \n> Also, I don't really like the 'map' flag, as it seems to me if only\n> construction is required, but not mapping, we should rather split the\n> two operations in two methods (ie adding an explicit\n> CameraBuffer::map() method)\n\nI agree, I think that the constructor should not map the buffer, this\nshould instead be done in plane() the first time it's called.\n\n> > Signed-off-by: Hirokazu Honda <hiroh@chromium.org>\n> > ---\n> >  src/android/camera_buffer.h              |  7 ++++---\n> >  src/android/mm/cros_camera_buffer.cpp    | 17 +++++++++++++----\n> >  src/android/mm/generic_camera_buffer.cpp | 20 ++++++++++++--------\n> >  3 files changed, 29 insertions(+), 15 deletions(-)\n> >\n> > diff --git a/src/android/camera_buffer.h b/src/android/camera_buffer.h\n> > index 7e8970b4..1fdb76a6 100644\n> > --- a/src/android/camera_buffer.h\n> > +++ b/src/android/camera_buffer.h\n> > @@ -17,7 +17,7 @@ class CameraBuffer final : public libcamera::Extensible\n> >  \tLIBCAMERA_DECLARE_PRIVATE(CameraBuffer)\n> >\n> >  public:\n> > -\tCameraBuffer(buffer_handle_t camera3Buffer, int flags);\n> > +\tCameraBuffer(buffer_handle_t camera3Buffer, int flags, bool map = true);\n> >  \t~CameraBuffer();\n> >\n> >  \tbool isValid() const;\n> > @@ -31,8 +31,9 @@ public:\n> >  };\n> >\n> >  #define PUBLIC_CAMERA_BUFFER_IMPLEMENTATION\t\t\t\t\\\n> > -CameraBuffer::CameraBuffer(buffer_handle_t camera3Buffer, int flags)\t\\\n> > -\t: Extensible(new Private(this, camera3Buffer, flags))\t\t\\\n> > +\tCameraBuffer::CameraBuffer(buffer_handle_t camera3Buffer, int flags, \\\n> > +\t\t\t\t   bool map)\t\t\t\t\\\n> > +\t\t: Extensible(new Private(this, camera3Buffer, flags, map))\\\n> >  {\t\t\t\t\t\t\t\t\t\\\n> >  }\t\t\t\t\t\t\t\t\t\\\n> >  CameraBuffer::~CameraBuffer()\t\t\t\t\t\t\\\n> > diff --git a/src/android/mm/cros_camera_buffer.cpp b/src/android/mm/cros_camera_buffer.cpp\n> > index 1a4fd5d1..71e03766 100644\n> > --- a/src/android/mm/cros_camera_buffer.cpp\n> > +++ b/src/android/mm/cros_camera_buffer.cpp\n> > @@ -21,7 +21,7 @@ class CameraBuffer::Private : public Extensible::Private\n> >\n> >  public:\n> >  \tPrivate(CameraBuffer *cameraBuffer,\n> > -\t\tbuffer_handle_t camera3Buffer, int flags);\n> > +\t\tbuffer_handle_t camera3Buffer, int flags, bool map);\n> >  \t~Private();\n> >\n> >  \tbool isValid() const { return valid_; }\n> > @@ -38,6 +38,7 @@ private:\n> >  \tunsigned int numPlanes_;\n> >  \tbool valid_;\n> >  \tbool registered_;\n> > +\tbool map_;\n> >  \tunion {\n> >  \t\tvoid *addr;\n> >  \t\tandroid_ycbcr ycbcr;\n> > @@ -48,9 +49,10 @@ private:\n> >  };\n> >\n> >  CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n> > -\t\t\t       buffer_handle_t camera3Buffer, int flags)\n> > +\t\t\t       buffer_handle_t camera3Buffer, int flags,\n> > +\t\t\t       bool map)\n> >  \t: Extensible::Private(cameraBuffer), handle_(camera3Buffer),\n> > -\t  numPlanes_(0), valid_(false), registered_(false)\n> > +\t  numPlanes_(0), valid_(false), registered_(false), map_(map)\n> >  {\n> >  \tbufferManager_ = cros::CameraBufferManager::GetInstance();\n> >\n> > @@ -62,6 +64,13 @@ CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n> >\n> >  \tregistered_ = true;\n> >  \tnumPlanes_ = bufferManager_->GetNumPlanes(camera3Buffer);\n> > +\n> > +\tmemset(&mem, 0, sizeof(mem));\n> > +\tif (!map_) {\n> > +\t\tvalid_ = true;\n> > +\t\treturn;\n> > +\t}\n> > +\n> >  \tswitch (numPlanes_) {\n> >  \tcase 1: {\n> >  \t\tret = bufferManager_->Lock(handle_, 0, 0, 0, 0, 0, &mem.addr);\n> > @@ -91,7 +100,7 @@ CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n> >\n> >  CameraBuffer::Private::~Private()\n> >  {\n> > -\tif (valid_)\n> > +\tif (map_ && valid_)\n> >  \t\tbufferManager_->Unlock(handle_);\n> >  \tif (registered_)\n> >  \t\tbufferManager_->Deregister(handle_);\n> > diff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp\n> > index 929e078a..8fa79889 100644\n> > --- a/src/android/mm/generic_camera_buffer.cpp\n> > +++ b/src/android/mm/generic_camera_buffer.cpp\n> > @@ -21,7 +21,7 @@ class CameraBuffer::Private : public Extensible::Private,\n> >\n> >  public:\n> >  \tPrivate(CameraBuffer *cameraBuffer,\n> > -\t\tbuffer_handle_t camera3Buffer, int flags);\n> > +\t\tbuffer_handle_t camera3Buffer, int flags, bool map);\n> >  \t~Private();\n> >\n> >  \tunsigned int numPlanes() const;\n> > @@ -32,7 +32,8 @@ public:\n> >  };\n> >\n> >  CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n> > -\t\t\t       buffer_handle_t camera3Buffer, int flags)\n> > +\t\t\t       buffer_handle_t camera3Buffer,\n> > +\t\t\t       int flags, bool map)\n> >  \t: Extensible::Private(cameraBuffer)\n> >  {\n> >  \tmaps_.reserve(camera3Buffer->numFds);\n> > @@ -49,12 +50,15 @@ CameraBuffer::Private::Private(CameraBuffer *cameraBuffer,\n> >  \t\t\tbreak;\n> >  \t\t}\n> >\n> > -\t\tvoid *address = mmap(nullptr, length, flags, MAP_SHARED,\n> > -\t\t\t\t     camera3Buffer->data[i], 0);\n> > -\t\tif (address == MAP_FAILED) {\n> > -\t\t\terror_ = -errno;\n> > -\t\t\tLOG(HAL, Error) << \"Failed to mmap plane\";\n> > -\t\t\tbreak;\n> > +\t\tvoid *address = nullptr;\n> > +\t\tif (map) {\n> > +\t\t\tmmap(nullptr, length, flags, MAP_SHARED,\n> > +\t\t\t     camera3Buffer->data[i], 0);\n> > +\t\t\tif (address == MAP_FAILED) {\n> > +\t\t\t\terror_ = -errno;\n> > +\t\t\t\tLOG(HAL, Error) << \"Failed to mmap plane\";\n> > +\t\t\t\tbreak;\n> > +\t\t\t}\n> >  \t\t}\n> >\n> >  \t\tmaps_.emplace_back(static_cast<uint8_t *>(address),","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 508CABD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 20 Aug 2021 11:26:00 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B84F468895;\n\tFri, 20 Aug 2021 13:25:59 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1A4386025E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 20 Aug 2021 13:25:59 +0200 (CEST)","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 848528C8;\n\tFri, 20 Aug 2021 13:25:58 +0200 (CEST)"],"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=\"hpo4mzvS\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1629458758;\n\tbh=x6mfLeDmTU05s8y/+esfj4eU7/hac4BFyhgHcZu2LiM=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=hpo4mzvSzxJdtVug2nku/x/QnF5/I4n4sgwA7PvqYlvgaopfhfcahHVmn1fDugpjY\n\tL+nX86oYWQKqX6D3acK3QA8bE6kzekJRFpQWrwcqyeU7c/oqiaqM8euCFli1u/tMpz\n\tHY+X3V+8d6PklT3pCR+dKWyBoybZmQTjfH8lwlrM=","Date":"Fri, 20 Aug 2021 14:25:49 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<YR+RPUS2C1Wo6cNL@pendragon.ideasonboard.com>","References":"<20210405040424.1929737-1-hiroh@chromium.org>\n\t<20210405040424.1929737-2-hiroh@chromium.org>\n\t<20210406124734.sqyzfnzu2okpkotp@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20210406124734.sqyzfnzu2okpkotp@uno.localdomain>","Subject":"Re: [libcamera-devel] [PATCH 1/2] android: CameraBuffer: Add option\n\tof not mapping a buffer","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>"}}]