[{"id":37585,"web_url":"https://patchwork.libcamera.org/comment/37585/","msgid":"<a0cf2901-288f-4608-bcd8-d67ba5e8f135@ideasonboard.com>","date":"2026-01-13T08:57:25","subject":"Re: [PATCH 03/36] libcamera: Replace plain pointers with\n\tstd::unique<>","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 01. 13. 1:07 keltezéssel, Laurent Pinchart írta:\n> libcamera uses std::unique_ptr<> to simplify life time management of\n> objects and avoid leaks. For historical reasons there are a fair number\n> of plain pointers with manual memory management. Replace them with\n> std::unique_ptr<> when the conversion is simple.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>   .../guides/application-developer.rst          |  5 +++--\n>   Documentation/guides/pipeline-handler.rst     |  7 +++---\n>   .../internal/device_enumerator_udev.h         |  2 +-\n>   include/libcamera/internal/ipc_unixsocket.h   |  3 ++-\n>   include/libcamera/internal/v4l2_device.h      |  2 +-\n>   include/libcamera/internal/v4l2_videodevice.h | 12 +++++-----\n>   src/apps/qcam/main.cpp                        |  5 ++---\n>   src/apps/qcam/main_window.cpp                 | 11 +++++-----\n>   src/apps/qcam/main_window.h                   |  2 +-\n>   src/libcamera/device_enumerator_udev.cpp      |  6 ++---\n>   src/libcamera/ipc_unixsocket.cpp              |  7 +++---\n>   src/libcamera/v4l2_device.cpp                 |  5 +++--\n>   src/libcamera/v4l2_videodevice.cpp            | 22 ++++++++-----------\n>   src/v4l2/v4l2_camera.cpp                      |  7 +++---\n>   src/v4l2/v4l2_camera.h                        |  2 +-\n>   src/v4l2/v4l2_compat_manager.cpp              | 18 +++++----------\n>   src/v4l2/v4l2_compat_manager.h                |  2 +-\n>   17 files changed, 52 insertions(+), 66 deletions(-)\n> \n> diff --git a/Documentation/guides/application-developer.rst b/Documentation/guides/application-developer.rst\n> index 06c07d1e9449..d981b6a4f9e7 100644\n> --- a/Documentation/guides/application-developer.rst\n> +++ b/Documentation/guides/application-developer.rst\n> @@ -279,7 +279,8 @@ as the parameter of the ``FrameBufferAllocator::buffers()`` function.\n> \n>   .. code:: cpp\n> \n> -   FrameBufferAllocator *allocator = new FrameBufferAllocator(camera);\n> +   std::unique_ptr<FrameBufferAllocator> allocator =\n> +       std::make_unique<FrameBufferAllocator>(camera);\n> \n>      for (StreamConfiguration &cfg : *config) {\n>          int ret = allocator->allocate(cfg.stream());\n> @@ -539,7 +540,7 @@ uses, so needs to do the following:\n> \n>      camera->stop();\n>      allocator->free(stream);\n> -   delete allocator;\n> +   allocator.reset();\n>      camera->release();\n>      camera.reset();\n>      cm->stop();\n> diff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst\n> index 85d9cc870021..c28eccb7cf0e 100644\n> --- a/Documentation/guides/pipeline-handler.rst\n> +++ b/Documentation/guides/pipeline-handler.rst\n> @@ -424,20 +424,19 @@ it will be used:\n>      {\n>      public:\n>             VividCameraData(PipelineHandler *pipe, MediaDevice *media)\n> -                : Camera::Private(pipe), media_(media), video_(nullptr)\n> +                : Camera::Private(pipe), media_(media)\n>             {\n>             }\n> \n>             ~VividCameraData()\n>             {\n> -                delete video_;\n>             }\n> \n>             int init();\n>             void bufferReady(FrameBuffer *buffer);\n> \n>             MediaDevice *media_;\n> -          V4L2VideoDevice *video_;\n> +          std::unique_ptr<V4L2VideoDevice> video_;\n>             Stream stream_;\n>      };\n> \n> @@ -468,7 +467,7 @@ open a single capture device named 'vivid-000-vid-cap' by the device.\n> \n>      int VividCameraData::init()\n>      {\n> -          video_ = new V4L2VideoDevice(media_->getEntityByName(\"vivid-000-vid-cap\"));\n> +          video_ = std::make_unique<V4L2VideoDevice>(media_->getEntityByName(\"vivid-000-vid-cap\"));\n>             if (video_->open())\n>                   return -ENODEV;\n> \n\nThe above is addressed by https://lists.libcamera.org/pipermail/libcamera-devel/2025-December/055929.html\ndo you think that can be merged and this rebased, or should it be done the other way around?\n\n\n> diff --git a/include/libcamera/internal/device_enumerator_udev.h b/include/libcamera/internal/device_enumerator_udev.h\n> index 0bf78b551e75..1ce988ab84d1 100644\n> --- a/include/libcamera/internal/device_enumerator_udev.h\n> +++ b/include/libcamera/internal/device_enumerator_udev.h\n> @@ -69,7 +69,7 @@ private:\n> \n>   \tstruct udev *udev_;\n>   \tstruct udev_monitor *monitor_;\n> -\tEventNotifier *notifier_;\n> +\tstd::unique_ptr<EventNotifier> notifier_;\n\nLocally I have been testing very similar changes, but I ended up with\n`std::optional<>` in most cases (e.g. here), since that\n\n   (1) avoids the extra memory allocation\n   (2) provides the same interface as a pointer (so not many changes)\n   (3) most of these allocations are long lived, so there do not appear\n       to be many memory savings with separate allocations\n\nso I think it's worth at least some consideration.\n\n> \n>   \tstd::set<dev_t> orphans_;\n>   \tstd::unordered_set<dev_t> devices_;\n> [...]\n> diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h\n> index 57db0036db6b..10367e4e178a 100644\n> --- a/include/libcamera/internal/v4l2_videodevice.h\n> +++ b/include/libcamera/internal/v4l2_videodevice.h\n> @@ -280,10 +280,10 @@ private:\n>   \tenum v4l2_buf_type bufferType_;\n>   \tenum v4l2_memory memoryType_;\n> \n> -\tV4L2BufferCache *cache_;\n> +\tstd::unique_ptr<V4L2BufferCache> cache_;\n>   \tstd::map<unsigned int, FrameBuffer *> queuedBuffers_;\n> \n> -\tEventNotifier *fdBufferNotifier_;\n> +\tstd::unique_ptr<EventNotifier> fdBufferNotifier_;\n> \n>   \tState state_;\n>   \tstd::optional<unsigned int> firstFrame_;\n> @@ -301,14 +301,14 @@ public:\n>   \tint open();\n>   \tvoid close();\n> \n> -\tV4L2VideoDevice *output() { return output_; }\n> -\tV4L2VideoDevice *capture() { return capture_; }\n> +\tV4L2VideoDevice *output() { return output_.get(); }\n> +\tV4L2VideoDevice *capture() { return capture_.get(); }\n> \n>   private:\n>   \tstd::string deviceNode_;\n> \n> -\tV4L2VideoDevice *output_;\n> -\tV4L2VideoDevice *capture_;\n> +\tstd::unique_ptr<V4L2VideoDevice> output_;\n> +\tstd::unique_ptr<V4L2VideoDevice> capture_;\n\nHere for example, directly embedding them is also an option.\n\n\n>   };\n> \n>   } /* namespace libcamera */\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 54A08BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 13 Jan 2026 08:57:30 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 07DF261FC0;\n\tTue, 13 Jan 2026 09:57:30 +0100 (CET)","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 C08EC61FBB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Jan 2026 09:57:28 +0100 (CET)","from [192.168.33.30] (185.221.143.114.nat.pool.zt.hu\n\t[185.221.143.114])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E24266A6;\n\tTue, 13 Jan 2026 09:57:02 +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=\"vHAEU/3t\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768294623;\n\tbh=KTJrnNITuB9LerpONfbNGtpJh8ZhbzFZNspWvBVU+Ls=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=vHAEU/3tIj4kcU+7+Upf2MTwKxHpXeUlpujrd762kchySWTUShznkiUlcnH3zGBaE\n\tBpsZfxsTWhv49LnJdDP1VN8jvbnGWhZkW8EGPVNTVTVp/E8p+Qr2pkZAr52MU/j6hj\n\tM/2ezhUAMwP6fydB3RR2iBPom/cp5j7VEK/K5bp0=","Message-ID":"<a0cf2901-288f-4608-bcd8-d67ba5e8f135@ideasonboard.com>","Date":"Tue, 13 Jan 2026 09:57:25 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 03/36] libcamera: Replace plain pointers with\n\tstd::unique<>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260113000808.15395-1-laurent.pinchart@ideasonboard.com>\n\t<diS9PEIkLnOpkO1Jy_rRDcm_cpdnKDD8XBaYOvC1zhgCZeSfAIWofbdv2iB3B89Ng4GPlYeocPkmS8YHjqm1ig==@protonmail.internalid>\n\t<20260113000808.15395-4-laurent.pinchart@ideasonboard.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260113000808.15395-4-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37606,"web_url":"https://patchwork.libcamera.org/comment/37606/","msgid":"<20260113135845.GH6198@pendragon.ideasonboard.com>","date":"2026-01-13T13:58:45","subject":"Re: [PATCH 03/36] libcamera: Replace plain pointers with\n\tstd::unique<>","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Tue, Jan 13, 2026 at 09:57:25AM +0100, Barnabás Pőcze wrote:\n> 2026. 01. 13. 1:07 keltezéssel, Laurent Pinchart írta:\n> > libcamera uses std::unique_ptr<> to simplify life time management of\n> > objects and avoid leaks. For historical reasons there are a fair number\n> > of plain pointers with manual memory management. Replace them with\n> > std::unique_ptr<> when the conversion is simple.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >   .../guides/application-developer.rst          |  5 +++--\n> >   Documentation/guides/pipeline-handler.rst     |  7 +++---\n> >   .../internal/device_enumerator_udev.h         |  2 +-\n> >   include/libcamera/internal/ipc_unixsocket.h   |  3 ++-\n> >   include/libcamera/internal/v4l2_device.h      |  2 +-\n> >   include/libcamera/internal/v4l2_videodevice.h | 12 +++++-----\n> >   src/apps/qcam/main.cpp                        |  5 ++---\n> >   src/apps/qcam/main_window.cpp                 | 11 +++++-----\n> >   src/apps/qcam/main_window.h                   |  2 +-\n> >   src/libcamera/device_enumerator_udev.cpp      |  6 ++---\n> >   src/libcamera/ipc_unixsocket.cpp              |  7 +++---\n> >   src/libcamera/v4l2_device.cpp                 |  5 +++--\n> >   src/libcamera/v4l2_videodevice.cpp            | 22 ++++++++-----------\n> >   src/v4l2/v4l2_camera.cpp                      |  7 +++---\n> >   src/v4l2/v4l2_camera.h                        |  2 +-\n> >   src/v4l2/v4l2_compat_manager.cpp              | 18 +++++----------\n> >   src/v4l2/v4l2_compat_manager.h                |  2 +-\n> >   17 files changed, 52 insertions(+), 66 deletions(-)\n> > \n> > diff --git a/Documentation/guides/application-developer.rst b/Documentation/guides/application-developer.rst\n> > index 06c07d1e9449..d981b6a4f9e7 100644\n> > --- a/Documentation/guides/application-developer.rst\n> > +++ b/Documentation/guides/application-developer.rst\n> > @@ -279,7 +279,8 @@ as the parameter of the ``FrameBufferAllocator::buffers()`` function.\n> > \n> >   .. code:: cpp\n> > \n> > -   FrameBufferAllocator *allocator = new FrameBufferAllocator(camera);\n> > +   std::unique_ptr<FrameBufferAllocator> allocator =\n> > +       std::make_unique<FrameBufferAllocator>(camera);\n> > \n> >      for (StreamConfiguration &cfg : *config) {\n> >          int ret = allocator->allocate(cfg.stream());\n> > @@ -539,7 +540,7 @@ uses, so needs to do the following:\n> > \n> >      camera->stop();\n> >      allocator->free(stream);\n> > -   delete allocator;\n> > +   allocator.reset();\n> >      camera->release();\n> >      camera.reset();\n> >      cm->stop();\n> > diff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst\n> > index 85d9cc870021..c28eccb7cf0e 100644\n> > --- a/Documentation/guides/pipeline-handler.rst\n> > +++ b/Documentation/guides/pipeline-handler.rst\n> > @@ -424,20 +424,19 @@ it will be used:\n> >      {\n> >      public:\n> >             VividCameraData(PipelineHandler *pipe, MediaDevice *media)\n> > -                : Camera::Private(pipe), media_(media), video_(nullptr)\n> > +                : Camera::Private(pipe), media_(media)\n> >             {\n> >             }\n> > \n> >             ~VividCameraData()\n> >             {\n> > -                delete video_;\n> >             }\n> > \n> >             int init();\n> >             void bufferReady(FrameBuffer *buffer);\n> > \n> >             MediaDevice *media_;\n> > -          V4L2VideoDevice *video_;\n> > +          std::unique_ptr<V4L2VideoDevice> video_;\n> >             Stream stream_;\n> >      };\n> > \n> > @@ -468,7 +467,7 @@ open a single capture device named 'vivid-000-vid-cap' by the device.\n> > \n> >      int VividCameraData::init()\n> >      {\n> > -          video_ = new V4L2VideoDevice(media_->getEntityByName(\"vivid-000-vid-cap\"));\n> > +          video_ = std::make_unique<V4L2VideoDevice>(media_->getEntityByName(\"vivid-000-vid-cap\"));\n> >             if (video_->open())\n> >                   return -ENODEV;\n> > \n> \n> The above is addressed by https://lists.libcamera.org/pipermail/libcamera-devel/2025-December/055929.html\n> do you think that can be merged and this rebased, or should it be done the other way around?\n\nI've just reviewed that patch, please merge it and I'll rebase v2 on\ntop.\n\n> > diff --git a/include/libcamera/internal/device_enumerator_udev.h b/include/libcamera/internal/device_enumerator_udev.h\n> > index 0bf78b551e75..1ce988ab84d1 100644\n> > --- a/include/libcamera/internal/device_enumerator_udev.h\n> > +++ b/include/libcamera/internal/device_enumerator_udev.h\n> > @@ -69,7 +69,7 @@ private:\n> > \n> >   \tstruct udev *udev_;\n> >   \tstruct udev_monitor *monitor_;\n> > -\tEventNotifier *notifier_;\n> > +\tstd::unique_ptr<EventNotifier> notifier_;\n> \n> Locally I have been testing very similar changes, but I ended up with\n> `std::optional<>` in most cases (e.g. here), since that\n> \n>    (1) avoids the extra memory allocation\n>    (2) provides the same interface as a pointer (so not many changes)\n>    (3) most of these allocations are long lived, so there do not appear\n>        to be many memory savings with separate allocations\n> \n> so I think it's worth at least some consideration.\n\nI agree, but I'd like to do that separately. This patch is about\nconsistency, as we have standardized on std::unique_ptr<>. We can then\nreplace some instances of unique_ptr with optional, or embed member\nvariables directly as suggested below.\n\n> > \n> >   \tstd::set<dev_t> orphans_;\n> >   \tstd::unordered_set<dev_t> devices_;\n> > [...]\n> > diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h\n> > index 57db0036db6b..10367e4e178a 100644\n> > --- a/include/libcamera/internal/v4l2_videodevice.h\n> > +++ b/include/libcamera/internal/v4l2_videodevice.h\n> > @@ -280,10 +280,10 @@ private:\n> >   \tenum v4l2_buf_type bufferType_;\n> >   \tenum v4l2_memory memoryType_;\n> > \n> > -\tV4L2BufferCache *cache_;\n> > +\tstd::unique_ptr<V4L2BufferCache> cache_;\n> >   \tstd::map<unsigned int, FrameBuffer *> queuedBuffers_;\n> > \n> > -\tEventNotifier *fdBufferNotifier_;\n> > +\tstd::unique_ptr<EventNotifier> fdBufferNotifier_;\n> > \n> >   \tState state_;\n> >   \tstd::optional<unsigned int> firstFrame_;\n> > @@ -301,14 +301,14 @@ public:\n> >   \tint open();\n> >   \tvoid close();\n> > \n> > -\tV4L2VideoDevice *output() { return output_; }\n> > -\tV4L2VideoDevice *capture() { return capture_; }\n> > +\tV4L2VideoDevice *output() { return output_.get(); }\n> > +\tV4L2VideoDevice *capture() { return capture_.get(); }\n> > \n> >   private:\n> >   \tstd::string deviceNode_;\n> > \n> > -\tV4L2VideoDevice *output_;\n> > -\tV4L2VideoDevice *capture_;\n> > +\tstd::unique_ptr<V4L2VideoDevice> output_;\n> > +\tstd::unique_ptr<V4L2VideoDevice> capture_;\n> \n> Here for example, directly embedding them is also an option.\n> \n> >   };\n> > \n> >   } /* namespace libcamera */\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 4D325BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 13 Jan 2026 13:59:08 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 649C761FBC;\n\tTue, 13 Jan 2026 14:59:07 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8BEBF61FA0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Jan 2026 14:59:06 +0100 (CET)","from pendragon.ideasonboard.com (81-175-209-152.bb.dnainternet.fi\n\t[81.175.209.152])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 3801B316;\n\tTue, 13 Jan 2026 14:58:40 +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=\"FYv92zm0\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768312720;\n\tbh=lRLQPWl3B1LHWg7iYXDr9FWOwjxg+WPAqMQ9Oiv859A=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=FYv92zm0LenJExSky5OzV24B1//bCz620PNxS+aGziQote6S7nxFxIcbDmWku41qr\n\tiDyvzLrawi4dMsuDyHooYAsshVkRb7+ELISblQlSVFg616rFcGf/+j1F6EBoqvMJkV\n\tBln0RHKf6LSKuHYAbXkb7devTkI5M6IAvcT1mhc4=","Date":"Tue, 13 Jan 2026 15:58:45 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 03/36] libcamera: Replace plain pointers with\n\tstd::unique<>","Message-ID":"<20260113135845.GH6198@pendragon.ideasonboard.com>","References":"<20260113000808.15395-1-laurent.pinchart@ideasonboard.com>\n\t<diS9PEIkLnOpkO1Jy_rRDcm_cpdnKDD8XBaYOvC1zhgCZeSfAIWofbdv2iB3B89Ng4GPlYeocPkmS8YHjqm1ig==@protonmail.internalid>\n\t<20260113000808.15395-4-laurent.pinchart@ideasonboard.com>\n\t<a0cf2901-288f-4608-bcd8-d67ba5e8f135@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<a0cf2901-288f-4608-bcd8-d67ba5e8f135@ideasonboard.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>"}}]