[{"id":23085,"web_url":"https://patchwork.libcamera.org/comment/23085/","msgid":"<YoYgEIUBahO8HwFN@pendragon.ideasonboard.com>","date":"2022-05-19T10:46:40","subject":"Re: [libcamera-devel] [PATCH 1/5] py: Generate pixel formats list","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Tomi,\n\nThank you for the patch.\n\nOn Thu, May 19, 2022 at 01:33:43PM +0300, Tomi Valkeinen wrote:\n> Generate a list of pixel formats under 'libcamera.formats'.\n> \n> The 'formats' is a \"dummy\" container class, the only purpose of which is\n> to contain the read-only pixel format properties.\n> \n> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  src/py/libcamera/gen-py-formats.py           | 56 ++++++++++++++++++++\n>  src/py/libcamera/meson.build                 | 12 +++++\n>  src/py/libcamera/py_formats_generated.cpp.in | 23 ++++++++\n>  src/py/libcamera/py_main.cpp                 |  3 ++\n>  4 files changed, 94 insertions(+)\n>  create mode 100755 src/py/libcamera/gen-py-formats.py\n>  create mode 100644 src/py/libcamera/py_formats_generated.cpp.in\n> \n> diff --git a/src/py/libcamera/gen-py-formats.py b/src/py/libcamera/gen-py-formats.py\n> new file mode 100755\n> index 00000000..0ff1d12a\n> --- /dev/null\n> +++ b/src/py/libcamera/gen-py-formats.py\n> @@ -0,0 +1,56 @@\n> +#!/usr/bin/env python3\n> +# SPDX-License-Identifier: GPL-2.0-or-later\n> +#\n> +# Generate Python format definitions from YAML\n> +\n> +import argparse\n> +import string\n> +import sys\n> +import yaml\n> +\n> +\n> +def generate(formats):\n> +    fmts = []\n> +\n> +    for format in formats:\n> +        name, format = format.popitem()\n> +        fmts.append(f'\\t\\t.def_readonly_static(\"{name}\", &libcamera::formats::{name})')\n> +\n> +    return {'formats': '\\n'.join(fmts)}\n> +\n> +\n> +def fill_template(template, data):\n> +    with open(template, encoding='utf-8') as f:\n> +        template = f.read()\n> +\n> +    template = string.Template(template)\n> +    return template.substitute(data)\n> +\n> +\n> +def main(argv):\n> +    parser = argparse.ArgumentParser()\n> +    parser.add_argument('-o', dest='output', metavar='file', type=str,\n> +                        help='Output file name. Defaults to standard output if not specified.')\n> +    parser.add_argument('input', type=str,\n> +                        help='Input file name.')\n> +    parser.add_argument('template', type=str,\n> +                        help='Template file name.')\n> +    args = parser.parse_args(argv[1:])\n> +\n> +    with open(args.input, encoding='utf-8') as f:\n> +        formats = yaml.safe_load(f)['formats']\n> +\n> +    data = generate(formats)\n> +    data = fill_template(args.template, data)\n> +\n> +    if args.output:\n> +        with open(args.output, 'w', encoding='utf-8') as f:\n> +            f.write(data)\n> +    else:\n> +        sys.stdout.write(data)\n> +\n> +    return 0\n> +\n> +\n> +if __name__ == '__main__':\n> +    sys.exit(main(sys.argv))\n> diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build\n> index a3388c63..0a7b65f3 100644\n> --- a/src/py/libcamera/meson.build\n> +++ b/src/py/libcamera/meson.build\n> @@ -30,6 +30,18 @@ pycamera_sources += custom_target('py_gen_controls',\n>                                    output : ['py_control_enums_generated.cpp'],\n>                                    command : [gen_py_control_enums, '-o', '@OUTPUT@', '@INPUT@'])\n>  \n> +gen_py_formats_input_files = files([\n> +    '../../libcamera/formats.yaml',\n> +    'py_formats_generated.cpp.in',\n> +])\n> +\n> +gen_py_formats = files('gen-py-formats.py')\n> +\n> +pycamera_sources += custom_target('py_gen_formats',\n> +                                  input : gen_py_formats_input_files,\n> +                                  output : ['py_formats_generated.cpp'],\n> +                                  command : [gen_py_formats, '-o', '@OUTPUT@', '@INPUT@'])\n> +\n>  pycamera_deps = [\n>      libcamera_public,\n>      py3_dep,\n> diff --git a/src/py/libcamera/py_formats_generated.cpp.in b/src/py/libcamera/py_formats_generated.cpp.in\n> new file mode 100644\n> index 00000000..5824966f\n> --- /dev/null\n> +++ b/src/py/libcamera/py_formats_generated.cpp.in\n> @@ -0,0 +1,23 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> + *\n> + * Python bindings - Auto-generated formats\n> + *\n> + * This file is auto-generated. Do not edit.\n> + */\n> +\n> +#include <libcamera/formats.h>\n> +\n> +#include <pybind11/smart_holder.h>\n> +\n> +namespace py = pybind11;\n> +\n> +class PyFormats {};\n> +\n> +void init_py_formats_generated(py::module& m)\n> +{\n> +\tpy::class_<PyFormats>(m, \"formats\")\n> +${formats}\n> +\t;\n> +}\n> diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp\n> index 1d941160..e7066841 100644\n> --- a/src/py/libcamera/py_main.cpp\n> +++ b/src/py/libcamera/py_main.cpp\n> @@ -132,6 +132,7 @@ static void handleRequestCompleted(Request *req)\n>  \n>  void init_py_enums(py::module &m);\n>  void init_py_control_enums_generated(py::module &m);\n> +void init_py_formats_generated(py::module &m);\n>  void init_py_geometry(py::module &m);\n>  \n>  PYBIND11_MODULE(_libcamera, m)\n> @@ -171,6 +172,8 @@ PYBIND11_MODULE(_libcamera, m)\n>  \tauto pyColorSpaceRange = py::enum_<ColorSpace::Range>(pyColorSpace, \"Range\");\n>  \tauto pyPixelFormat = py::class_<PixelFormat>(m, \"PixelFormat\");\n>  \n> +\tinit_py_formats_generated(m);\n> +\n>  \t/* Global functions */\n>  \tm.def(\"log_set_level\", &logSetLevel);\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 6525AC3256\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 19 May 2022 10:46:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C415A65655;\n\tThu, 19 May 2022 12:46:49 +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 A902660420\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 19 May 2022 12:46:47 +0200 (CEST)","from pendragon.ideasonboard.com (unknown [45.131.31.124])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E9C28A16;\n\tThu, 19 May 2022 12:46:46 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1652957209;\n\tbh=tpn0Xkj7ABuu7aJQ2LVFrLXnzWppfWw8ImdSyrzeGpw=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=hV0fIZPoj1fw9z3bWUUY8knz6ktxiF52OCamyCavB9QDfBnpbQs76NSbjrJWJqAF6\n\t1eww794/cQpJnCUDhBgIykq49bTiIJwkqrWFcl+NwnSDFPf+Hx6Q8GqujBqiRnaMt5\n\tt+Cm/uxHqqoadKNKHyZxcq7fSoPsNUaiC//IIf4ZEIyPcuZuU3MUSIx/9/Ea+Pmqm6\n\tRzZhhpYdn4Tpre7lIIrMIQ9Lzp5Nnk/P2vyFl7btrtl14eH+2sQa9cMMAV6OXWTcAH\n\tojCbcP01ECvHCFynJgvh4wc2kR7YewQdnRbXYIHh+x2bDFySU/cmL66yjHYCgfY8A2\n\tUqfVHqMevUy4A==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1652957207;\n\tbh=tpn0Xkj7ABuu7aJQ2LVFrLXnzWppfWw8ImdSyrzeGpw=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=LpPRGCadcllJo1PFQEo3RuJrxPtLA1UlrKlqJ8ovOs0BoMd2/TVj9i/lOVKAqT+RS\n\tgU/ZNNGekESzdr1WuhuFnsq1jmQoQULDKK/zxCEIwd+5+aszBOAfRnMnjny6CBMwEr\n\tklbMiroKajDQei3+nBcZMm4woUciR92jRivMg8LI="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"LpPRGCad\"; dkim-atps=neutral","Date":"Thu, 19 May 2022 13:46:40 +0300","To":"Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>","Message-ID":"<YoYgEIUBahO8HwFN@pendragon.ideasonboard.com>","References":"<20220519103347.33295-1-tomi.valkeinen@ideasonboard.com>\n\t<20220519103347.33295-2-tomi.valkeinen@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220519103347.33295-2-tomi.valkeinen@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 1/5] py: Generate pixel formats list","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":23086,"web_url":"https://patchwork.libcamera.org/comment/23086/","msgid":"<YoYgUNRzqqajtKv0@pendragon.ideasonboard.com>","date":"2022-05-19T10:47:44","subject":"Re: [libcamera-devel] [PATCH 1/5] py: Generate pixel formats list","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Thu, May 19, 2022 at 01:46:41PM +0300, Laurent Pinchart wrote:\n> Hi Tomi,\n> \n> Thank you for the patch.\n> \n> On Thu, May 19, 2022 at 01:33:43PM +0300, Tomi Valkeinen wrote:\n> > Generate a list of pixel formats under 'libcamera.formats'.\n> > \n> > The 'formats' is a \"dummy\" container class, the only purpose of which is\n> > to contain the read-only pixel format properties.\n> > \n> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> \n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> \n> > ---\n> >  src/py/libcamera/gen-py-formats.py           | 56 ++++++++++++++++++++\n> >  src/py/libcamera/meson.build                 | 12 +++++\n> >  src/py/libcamera/py_formats_generated.cpp.in | 23 ++++++++\n> >  src/py/libcamera/py_main.cpp                 |  3 ++\n> >  4 files changed, 94 insertions(+)\n> >  create mode 100755 src/py/libcamera/gen-py-formats.py\n> >  create mode 100644 src/py/libcamera/py_formats_generated.cpp.in\n> > \n> > diff --git a/src/py/libcamera/gen-py-formats.py b/src/py/libcamera/gen-py-formats.py\n> > new file mode 100755\n> > index 00000000..0ff1d12a\n> > --- /dev/null\n> > +++ b/src/py/libcamera/gen-py-formats.py\n> > @@ -0,0 +1,56 @@\n> > +#!/usr/bin/env python3\n> > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > +#\n> > +# Generate Python format definitions from YAML\n> > +\n> > +import argparse\n> > +import string\n> > +import sys\n> > +import yaml\n> > +\n> > +\n> > +def generate(formats):\n> > +    fmts = []\n> > +\n> > +    for format in formats:\n> > +        name, format = format.popitem()\n> > +        fmts.append(f'\\t\\t.def_readonly_static(\"{name}\", &libcamera::formats::{name})')\n> > +\n> > +    return {'formats': '\\n'.join(fmts)}\n> > +\n> > +\n> > +def fill_template(template, data):\n> > +    with open(template, encoding='utf-8') as f:\n> > +        template = f.read()\n> > +\n> > +    template = string.Template(template)\n> > +    return template.substitute(data)\n> > +\n> > +\n> > +def main(argv):\n> > +    parser = argparse.ArgumentParser()\n> > +    parser.add_argument('-o', dest='output', metavar='file', type=str,\n> > +                        help='Output file name. Defaults to standard output if not specified.')\n> > +    parser.add_argument('input', type=str,\n> > +                        help='Input file name.')\n> > +    parser.add_argument('template', type=str,\n> > +                        help='Template file name.')\n> > +    args = parser.parse_args(argv[1:])\n> > +\n> > +    with open(args.input, encoding='utf-8') as f:\n> > +        formats = yaml.safe_load(f)['formats']\n> > +\n> > +    data = generate(formats)\n> > +    data = fill_template(args.template, data)\n> > +\n> > +    if args.output:\n> > +        with open(args.output, 'w', encoding='utf-8') as f:\n> > +            f.write(data)\n> > +    else:\n> > +        sys.stdout.write(data)\n> > +\n> > +    return 0\n> > +\n> > +\n> > +if __name__ == '__main__':\n> > +    sys.exit(main(sys.argv))\n> > diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build\n> > index a3388c63..0a7b65f3 100644\n> > --- a/src/py/libcamera/meson.build\n> > +++ b/src/py/libcamera/meson.build\n> > @@ -30,6 +30,18 @@ pycamera_sources += custom_target('py_gen_controls',\n> >                                    output : ['py_control_enums_generated.cpp'],\n> >                                    command : [gen_py_control_enums, '-o', '@OUTPUT@', '@INPUT@'])\n> >  \n> > +gen_py_formats_input_files = files([\n> > +    '../../libcamera/formats.yaml',\n> > +    'py_formats_generated.cpp.in',\n> > +])\n> > +\n> > +gen_py_formats = files('gen-py-formats.py')\n> > +\n> > +pycamera_sources += custom_target('py_gen_formats',\n> > +                                  input : gen_py_formats_input_files,\n> > +                                  output : ['py_formats_generated.cpp'],\n> > +                                  command : [gen_py_formats, '-o', '@OUTPUT@', '@INPUT@'])\n> > +\n> >  pycamera_deps = [\n> >      libcamera_public,\n> >      py3_dep,\n> > diff --git a/src/py/libcamera/py_formats_generated.cpp.in b/src/py/libcamera/py_formats_generated.cpp.in\n> > new file mode 100644\n> > index 00000000..5824966f\n> > --- /dev/null\n> > +++ b/src/py/libcamera/py_formats_generated.cpp.in\n> > @@ -0,0 +1,23 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> > + *\n> > + * Python bindings - Auto-generated formats\n> > + *\n> > + * This file is auto-generated. Do not edit.\n> > + */\n> > +\n> > +#include <libcamera/formats.h>\n> > +\n> > +#include <pybind11/smart_holder.h>\n> > +\n> > +namespace py = pybind11;\n> > +\n> > +class PyFormats {};\n\nActually the following would be more in line with our coding style:\n\nclass PyFormats\n{\n};\n\nThat's very minor, I can fix it when applying.\n\n> > +\n> > +void init_py_formats_generated(py::module& m)\n> > +{\n> > +\tpy::class_<PyFormats>(m, \"formats\")\n> > +${formats}\n> > +\t;\n> > +}\n> > diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp\n> > index 1d941160..e7066841 100644\n> > --- a/src/py/libcamera/py_main.cpp\n> > +++ b/src/py/libcamera/py_main.cpp\n> > @@ -132,6 +132,7 @@ static void handleRequestCompleted(Request *req)\n> >  \n> >  void init_py_enums(py::module &m);\n> >  void init_py_control_enums_generated(py::module &m);\n> > +void init_py_formats_generated(py::module &m);\n> >  void init_py_geometry(py::module &m);\n> >  \n> >  PYBIND11_MODULE(_libcamera, m)\n> > @@ -171,6 +172,8 @@ PYBIND11_MODULE(_libcamera, m)\n> >  \tauto pyColorSpaceRange = py::enum_<ColorSpace::Range>(pyColorSpace, \"Range\");\n> >  \tauto pyPixelFormat = py::class_<PixelFormat>(m, \"PixelFormat\");\n> >  \n> > +\tinit_py_formats_generated(m);\n> > +\n> >  \t/* Global functions */\n> >  \tm.def(\"log_set_level\", &logSetLevel);\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 952E2C3256\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 19 May 2022 10:47:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5CD4265663;\n\tThu, 19 May 2022 12:47:52 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8706860420\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 19 May 2022 12:47:51 +0200 (CEST)","from pendragon.ideasonboard.com (unknown [45.131.31.124])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 27F4EA16;\n\tThu, 19 May 2022 12:47:51 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1652957272;\n\tbh=/heFRROJ2q0ailWHz7fs1TIb36qVyQooFeA6VtDE3fk=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=KB6q+ENf8ahLZVZVvY3tXeqj53Pg1y414r/avsEGApFaIzQygaIWUUFtecPCxn2c0\n\tDFzCf81HFwia5ufjTQBy7SgEpCMKx4T8Lk0kwvHTYAT5g4s41Z3pB21+MYnMPaDZBJ\n\tzomr6om3IuoAvWS0bGa3ni1MJ1eRHqgnbMy8Z3TEc4mm37AQ9ijHlrh5kGaIX2qeyb\n\t0YRaJ60R6Lcg0lBryHiKokNERUCyDQC2Tak8SjpX+Vt3t2+IISdy7WS3o/budgDVeA\n\tJAc7g6G93t6LgH0PcZ5ynPZ6uKwMh2F96uwjQcszaDLEP5a5feE8o/MqVCbxdxviME\n\tRFEstRCMyyG+Q==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1652957271;\n\tbh=/heFRROJ2q0ailWHz7fs1TIb36qVyQooFeA6VtDE3fk=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=OHT5ohGLZxsqPIuuCiVizyLd/Qgb8nx4En4I+1YVdRBcguUbZVzzr/8GwxyZLF2k5\n\t2wgj6qfijQpRowJuRY1XreP19ZepvYNMtn3MB2jiW21mA9jURi6KnajU4mQIQGwICU\n\tF5+NQ9fybZa6vs2qtM6wpYPtKX5W9RVoMZ9yd1dA="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"OHT5ohGL\"; dkim-atps=neutral","Date":"Thu, 19 May 2022 13:47:44 +0300","To":"Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>","Message-ID":"<YoYgUNRzqqajtKv0@pendragon.ideasonboard.com>","References":"<20220519103347.33295-1-tomi.valkeinen@ideasonboard.com>\n\t<20220519103347.33295-2-tomi.valkeinen@ideasonboard.com>\n\t<YoYgEIUBahO8HwFN@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<YoYgEIUBahO8HwFN@pendragon.ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 1/5] py: Generate pixel formats list","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]