[{"id":5373,"web_url":"https://patchwork.libcamera.org/comment/5373/","msgid":"<20200624091810.nqwmovs27gtpf3v6@uno.localdomain>","date":"2020-06-24T09:18:10","subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Niklas,\n\nOn Tue, Jun 23, 2020 at 04:09:21AM +0200, Niklas Söderlund wrote:\n> It makes little sens for a CameraSensor to support the same media bus\n\nsense\ns/a CameraSensor/the CameraSensor class/\n> format multiple times, change the container from a vector<> to a set<>.\n>\n> This was discovered while working with the IPU3 pipeline handler that\n> Unnecessarily had to carry code to sort vectors in order to find\n\ns/Un/un/\n\n> intersections. As this change requires switching the container to set<>\n> in that pipeline handler as well fix this while we are at it.\n\nas well,\n\nWhich sensor does report mulitple times the same mbus_code ? Isn't\nthis a driver bug if it happens ?\n\nI see  V4L2Subdevice::formats() populating the image formats with the\nmbus codes returned by V4L2Subdevice::enumPadCodes() and when I print\nout on Soraka the codes there collected I only get MEDIA_BUS_FMT_SGRBG10_1X10.\n\nLooking at the drivers of the two there installed sensors confirms\nthat only one format is supported..\n\n>\n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> ---\n>  include/libcamera/internal/camera_sensor.h |  4 ++--\n>  include/libcamera/internal/formats.h       |  2 +-\n>  src/libcamera/camera_sensor.cpp            |  1 -\n>  src/libcamera/formats.cpp                  |  7 +++----\n>  src/libcamera/pipeline/ipu3/ipu3.cpp       | 13 +++++--------\n>  test/camera-sensor.cpp                     |  2 +-\n>  6 files changed, 12 insertions(+), 17 deletions(-)\n>\n> diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\n> index 7f07413f95602881..6d92818f16e4b752 100644\n> --- a/include/libcamera/internal/camera_sensor.h\n> +++ b/include/libcamera/internal/camera_sensor.h\n> @@ -50,7 +50,7 @@ public:\n>\n>  \tconst std::string &model() const { return model_; }\n>  \tconst MediaEntity *entity() const { return entity_; }\n> -\tconst std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> +\tconst std::set<unsigned int> &mbusCodes() const { return mbusCodes_; }\n>  \tconst std::vector<Size> &sizes() const { return sizes_; }\n>  \tconst Size &resolution() const { return resolution_; }\n>\n> @@ -77,7 +77,7 @@ private:\n>\n>  \tImageFormats formats_;\n>  \tSize resolution_;\n> -\tstd::vector<unsigned int> mbusCodes_;\n> +\tstd::set<unsigned int> mbusCodes_;\n>  \tstd::vector<Size> sizes_;\n>\n>  \tControlList properties_;\n> diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h\n> index 4b172efc6588d374..e8aa555dcbe99350 100644\n> --- a/include/libcamera/internal/formats.h\n> +++ b/include/libcamera/internal/formats.h\n> @@ -24,7 +24,7 @@ public:\n>  \tint addFormat(unsigned int format, const std::vector<SizeRange> &sizes);\n>\n>  \tbool isEmpty() const;\n> -\tstd::vector<unsigned int> formats() const;\n> +\tstd::set<unsigned int> formats() const;\n>  \tconst std::vector<SizeRange> &sizes(unsigned int format) const;\n>  \tconst std::map<unsigned int, std::vector<SizeRange>> &data() const;\n>\n> diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp\n> index b14b4051dca606b9..5ab50de660534f3f 100644\n> --- a/src/libcamera/camera_sensor.cpp\n> +++ b/src/libcamera/camera_sensor.cpp\n> @@ -251,7 +251,6 @@ int CameraSensor::init()\n>  \t}\n>\n>  \tmbusCodes_ = formats_.formats();\n> -\tstd::sort(mbusCodes_.begin(), mbusCodes_.end());\n>\n>  \tfor (const auto &format : formats_.data()) {\n>  \t\tconst std::vector<SizeRange> &ranges = format.second;\n> diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp\n> index 1272de29c802c539..6234fd98f3e2002c 100644\n> --- a/src/libcamera/formats.cpp\n> +++ b/src/libcamera/formats.cpp\n> @@ -68,14 +68,13 @@ bool ImageFormats::isEmpty() const\n>   * \\brief Retrieve a list of all supported image formats\n>   * \\return List of pixel formats or media bus codes\n>   */\n> -std::vector<unsigned int> ImageFormats::formats() const\n> +std::set<unsigned int> ImageFormats::formats() const\n>  {\n> -\tstd::vector<unsigned int> formats;\n> -\tformats.reserve(data_.size());\n> +\tstd::set<unsigned int> formats;\n>\n>  \t/* \\todo: Should this be cached instead of computed each time? */\n>  \tfor (auto const &it : data_)\n> -\t\tformats.push_back(it.first);\n> +\t\tformats.insert(it.first);\n>\n>  \treturn formats;\n>  }\n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index 5544288b14f739c0..1a59de0c58975b3c 100644\n> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> @@ -1441,15 +1441,12 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index)\n>  \t/*\n>  \t * Make sure the sensor produces at least one format compatible with\n>  \t * the CIO2 requirements.\n> -\t *\n> -\t * utils::set_overlap requires the ranges to be sorted, keep the\n> -\t * cio2Codes vector sorted in ascending order.\n>  \t */\n> -\tconst std::vector<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGRBG10_1X10,\n> -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGBRG10_1X10,\n> -\t\t\t\t\t\t   MEDIA_BUS_FMT_SRGGB10_1X10 };\n> -\tconst std::vector<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> +\tconst std::set<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> +\t\t\t\t\t\tMEDIA_BUS_FMT_SGRBG10_1X10,\n> +\t\t\t\t\t\tMEDIA_BUS_FMT_SGBRG10_1X10,\n> +\t\t\t\t\t\tMEDIA_BUS_FMT_SRGGB10_1X10 };\n> +\tconst std::set<unsigned int> &sensorCodes = sensor_->mbusCodes();\n>  \tif (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(),\n>  \t\t\t\tcio2Codes.begin(), cio2Codes.end())) {\n>  \t\tLOG(IPU3, Error)\n> diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp\n> index 8c7fd1d2d4445db3..146b1b7d6c294fdb 100644\n> --- a/test/camera-sensor.cpp\n> +++ b/test/camera-sensor.cpp\n> @@ -67,7 +67,7 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> -\t\tconst std::vector<unsigned int> &codes = sensor_->mbusCodes();\n> +\t\tconst std::set<unsigned int> &codes = sensor_->mbusCodes();\n>  \t\tauto iter = std::find(codes.begin(), codes.end(),\n>  \t\t\t\t      MEDIA_BUS_FMT_ARGB8888_1X32);\n>  \t\tif (iter == codes.end()) {\n> --\n> 2.27.0\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net\n\t[217.70.183.193])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A73B3609A7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 24 Jun 2020 11:14:43 +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 relay1-d.mail.gandi.net (Postfix) with ESMTPSA id 28A9B24000C;\n\tWed, 24 Jun 2020 09:14:42 +0000 (UTC)"],"X-Originating-IP":"93.34.118.233","Date":"Wed, 24 Jun 2020 11:18:10 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200624091810.nqwmovs27gtpf3v6@uno.localdomain>","References":"<20200623020930.1781469-1-niklas.soderlund@ragnatech.se>\n\t<20200623020930.1781469-2-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20200623020930.1781469-2-niklas.soderlund@ragnatech.se>","Subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","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>","X-List-Received-Date":"Wed, 24 Jun 2020 09:14:43 -0000"}},{"id":5378,"web_url":"https://patchwork.libcamera.org/comment/5378/","msgid":"<20200624234436.GL5980@pendragon.ideasonboard.com>","date":"2020-06-24T23:44:36","subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nOn Wed, Jun 24, 2020 at 07:53:37PM +0200, Niklas Söderlund wrote:\n> On 2020-06-24 11:18:10 +0200, Jacopo Mondi wrote:\n> > On Tue, Jun 23, 2020 at 04:09:21AM +0200, Niklas Söderlund wrote:\n> > > It makes little sens for a CameraSensor to support the same media bus\n> > \n> > sense\n> > s/a CameraSensor/the CameraSensor class/\n\nOr \"for a camera sensor\".\n\n> > > format multiple times, change the container from a vector<> to a set<>.\n> > >\n> > > This was discovered while working with the IPU3 pipeline handler that\n> > > Unnecessarily had to carry code to sort vectors in order to find\n> > \n> > s/Un/un/\n> > \n> > > intersections. As this change requires switching the container to set<>\n> > > in that pipeline handler as well fix this while we are at it.\n> > \n> > as well,\n> > \n> > Which sensor does report mulitple times the same mbus_code ? Isn't\n> > this a driver bug if it happens ?\n> \n> None does so today, and if it happens I would indeed consider it a \n> driver bug. That is the reason for this change, to us an API to \n> demonstrate that it's impossible to have the same format twice.\n> \n> As an added bonus the set will always be sorted so the possibility that \n> an implementation somewhere forgets to sort the vector is completely \n> avoided.\n\nstd::set is however more complex than std::vector. None of this should\nrun in a hot path, so I'm ok with the change, but I think we need to\ntake complexity into account in API design.\n\n> > I see  V4L2Subdevice::formats() populating the image formats with the\n> > mbus codes returned by V4L2Subdevice::enumPadCodes() and when I print\n> > out on Soraka the codes there collected I only get MEDIA_BUS_FMT_SGRBG10_1X10.\n> > \n> > Looking at the drivers of the two there installed sensors confirms\n> > that only one format is supported..\n> > \n> > >\n> > > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > > ---\n> > >  include/libcamera/internal/camera_sensor.h |  4 ++--\n> > >  include/libcamera/internal/formats.h       |  2 +-\n> > >  src/libcamera/camera_sensor.cpp            |  1 -\n> > >  src/libcamera/formats.cpp                  |  7 +++----\n> > >  src/libcamera/pipeline/ipu3/ipu3.cpp       | 13 +++++--------\n> > >  test/camera-sensor.cpp                     |  2 +-\n> > >  6 files changed, 12 insertions(+), 17 deletions(-)\n> > >\n> > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\n> > > index 7f07413f95602881..6d92818f16e4b752 100644\n> > > --- a/include/libcamera/internal/camera_sensor.h\n> > > +++ b/include/libcamera/internal/camera_sensor.h\n> > > @@ -50,7 +50,7 @@ public:\n> > >\n> > >  \tconst std::string &model() const { return model_; }\n> > >  \tconst MediaEntity *entity() const { return entity_; }\n> > > -\tconst std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> > > +\tconst std::set<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> > >  \tconst std::vector<Size> &sizes() const { return sizes_; }\n> > >  \tconst Size &resolution() const { return resolution_; }\n> > >\n> > > @@ -77,7 +77,7 @@ private:\n> > >\n> > >  \tImageFormats formats_;\n> > >  \tSize resolution_;\n> > > -\tstd::vector<unsigned int> mbusCodes_;\n> > > +\tstd::set<unsigned int> mbusCodes_;\n> > >  \tstd::vector<Size> sizes_;\n> > >\n> > >  \tControlList properties_;\n> > > diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h\n> > > index 4b172efc6588d374..e8aa555dcbe99350 100644\n> > > --- a/include/libcamera/internal/formats.h\n> > > +++ b/include/libcamera/internal/formats.h\n> > > @@ -24,7 +24,7 @@ public:\n> > >  \tint addFormat(unsigned int format, const std::vector<SizeRange> &sizes);\n> > >\n> > >  \tbool isEmpty() const;\n> > > -\tstd::vector<unsigned int> formats() const;\n> > > +\tstd::set<unsigned int> formats() const;\n> > >  \tconst std::vector<SizeRange> &sizes(unsigned int format) const;\n> > >  \tconst std::map<unsigned int, std::vector<SizeRange>> &data() const;\n> > >\n> > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp\n> > > index b14b4051dca606b9..5ab50de660534f3f 100644\n> > > --- a/src/libcamera/camera_sensor.cpp\n> > > +++ b/src/libcamera/camera_sensor.cpp\n> > > @@ -251,7 +251,6 @@ int CameraSensor::init()\n> > >  \t}\n> > >\n> > >  \tmbusCodes_ = formats_.formats();\n> > > -\tstd::sort(mbusCodes_.begin(), mbusCodes_.end());\n> > >\n> > >  \tfor (const auto &format : formats_.data()) {\n> > >  \t\tconst std::vector<SizeRange> &ranges = format.second;\n> > > diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp\n> > > index 1272de29c802c539..6234fd98f3e2002c 100644\n> > > --- a/src/libcamera/formats.cpp\n> > > +++ b/src/libcamera/formats.cpp\n> > > @@ -68,14 +68,13 @@ bool ImageFormats::isEmpty() const\n> > >   * \\brief Retrieve a list of all supported image formats\n> > >   * \\return List of pixel formats or media bus codes\n> > >   */\n> > > -std::vector<unsigned int> ImageFormats::formats() const\n> > > +std::set<unsigned int> ImageFormats::formats() const\n> > >  {\n> > > -\tstd::vector<unsigned int> formats;\n> > > -\tformats.reserve(data_.size());\n> > > +\tstd::set<unsigned int> formats;\n> > >\n> > >  \t/* \\todo: Should this be cached instead of computed each time? */\n> > >  \tfor (auto const &it : data_)\n> > > -\t\tformats.push_back(it.first);\n> > > +\t\tformats.insert(it.first);\n> > >\n> > >  \treturn formats;\n> > >  }\n> > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > index 5544288b14f739c0..1a59de0c58975b3c 100644\n> > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > @@ -1441,15 +1441,12 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index)\n> > >  \t/*\n> > >  \t * Make sure the sensor produces at least one format compatible with\n> > >  \t * the CIO2 requirements.\n> > > -\t *\n> > > -\t * utils::set_overlap requires the ranges to be sorted, keep the\n> > > -\t * cio2Codes vector sorted in ascending order.\n> > >  \t */\n> > > -\tconst std::vector<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGRBG10_1X10,\n> > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGBRG10_1X10,\n> > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SRGGB10_1X10 };\n> > > -\tconst std::vector<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> > > +\tconst std::set<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGRBG10_1X10,\n> > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGBRG10_1X10,\n> > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SRGGB10_1X10 };\n\nShould we make this static const ?\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> > > +\tconst std::set<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> > >  \tif (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(),\n> > >  \t\t\t\tcio2Codes.begin(), cio2Codes.end())) {\n> > >  \t\tLOG(IPU3, Error)\n> > > diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp\n> > > index 8c7fd1d2d4445db3..146b1b7d6c294fdb 100644\n> > > --- a/test/camera-sensor.cpp\n> > > +++ b/test/camera-sensor.cpp\n> > > @@ -67,7 +67,7 @@ protected:\n> > >  \t\t\treturn TestFail;\n> > >  \t\t}\n> > >\n> > > -\t\tconst std::vector<unsigned int> &codes = sensor_->mbusCodes();\n> > > +\t\tconst std::set<unsigned int> &codes = sensor_->mbusCodes();\n> > >  \t\tauto iter = std::find(codes.begin(), codes.end(),\n> > >  \t\t\t\t      MEDIA_BUS_FMT_ARGB8888_1X32);\n> > >  \t\tif (iter == codes.end()) {","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 3E70EC0101\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 24 Jun 2020 23:44:40 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B5BC4609A5;\n\tThu, 25 Jun 2020 01:44:39 +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 33BE0603BB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 25 Jun 2020 01:44:38 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8BF942A8;\n\tThu, 25 Jun 2020 01:44:37 +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=\"t8pY2DvD\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1593042277;\n\tbh=k++jBNTLpHms+1G4O6KSEV5wcf+nPEh46ODN+KiCOIE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=t8pY2DvD52MxWoLOBfgb0SXeb+HrE6WxW6XP3d4hTKQBD9u7PZHqN1VaAq1OK/XIz\n\tAsvrPq7qgxhx6zEkI/O+l9PNMkePBqzUizyjOX5jb4/Pe/CelwqcqePY0HGrkGTqKW\n\tc7tiHDDoJQpS5jFlx7At4OLyUvfkvAcS0IZM8pHU=","Date":"Thu, 25 Jun 2020 02:44:36 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Message-ID":"<20200624234436.GL5980@pendragon.ideasonboard.com>","References":"<20200623020930.1781469-1-niklas.soderlund@ragnatech.se>\n\t<20200623020930.1781469-2-niklas.soderlund@ragnatech.se>\n\t<20200624091810.nqwmovs27gtpf3v6@uno.localdomain>\n\t<20200624175337.GD1595450@oden.dyn.berto.se>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200624175337.GD1595450@oden.dyn.berto.se>","Subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","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=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":5407,"web_url":"https://patchwork.libcamera.org/comment/5407/","msgid":"<20200625074835.n3mujvxmhfpn4foo@uno.localdomain>","date":"2020-06-25T07:48:35","subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi\n\nOn Thu, Jun 25, 2020 at 02:44:36AM +0300, Laurent Pinchart wrote:\n> Hi Niklas,\n>\n> On Wed, Jun 24, 2020 at 07:53:37PM +0200, Niklas Söderlund wrote:\n> > On 2020-06-24 11:18:10 +0200, Jacopo Mondi wrote:\n> > > On Tue, Jun 23, 2020 at 04:09:21AM +0200, Niklas Söderlund wrote:\n> > > > It makes little sens for a CameraSensor to support the same media bus\n> > >\n> > > sense\n> > > s/a CameraSensor/the CameraSensor class/\n>\n> Or \"for a camera sensor\".\n>\n> > > > format multiple times, change the container from a vector<> to a set<>.\n> > > >\n> > > > This was discovered while working with the IPU3 pipeline handler that\n> > > > Unnecessarily had to carry code to sort vectors in order to find\n> > >\n> > > s/Un/un/\n> > >\n> > > > intersections. As this change requires switching the container to set<>\n> > > > in that pipeline handler as well fix this while we are at it.\n> > >\n> > > as well,\n> > >\n> > > Which sensor does report mulitple times the same mbus_code ? Isn't\n> > > this a driver bug if it happens ?\n> >\n> > None does so today, and if it happens I would indeed consider it a\n> > driver bug. That is the reason for this change, to us an API to\n> > demonstrate that it's impossible to have the same format twice.\n> >\n> > As an added bonus the set will always be sorted so the possibility that\n> > an implementation somewhere forgets to sort the vector is completely\n> > avoided.\n>\n> std::set is however more complex than std::vector. None of this should\n> run in a hot path, so I'm ok with the change, but I think we need to\n> take complexity into account in API design.\n\nI still don't think we need any of this. If a driver reports two\nidentical mbus codes, it's buggy and should be fixed. There's no\nreason I can see to work around it \"just in case\" here.\n\n>\n> > > I see  V4L2Subdevice::formats() populating the image formats with the\n> > > mbus codes returned by V4L2Subdevice::enumPadCodes() and when I print\n> > > out on Soraka the codes there collected I only get MEDIA_BUS_FMT_SGRBG10_1X10.\n> > >\n> > > Looking at the drivers of the two there installed sensors confirms\n> > > that only one format is supported..\n> > >\n> > > >\n> > > > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > > > ---\n> > > >  include/libcamera/internal/camera_sensor.h |  4 ++--\n> > > >  include/libcamera/internal/formats.h       |  2 +-\n> > > >  src/libcamera/camera_sensor.cpp            |  1 -\n> > > >  src/libcamera/formats.cpp                  |  7 +++----\n> > > >  src/libcamera/pipeline/ipu3/ipu3.cpp       | 13 +++++--------\n> > > >  test/camera-sensor.cpp                     |  2 +-\n> > > >  6 files changed, 12 insertions(+), 17 deletions(-)\n> > > >\n> > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\n> > > > index 7f07413f95602881..6d92818f16e4b752 100644\n> > > > --- a/include/libcamera/internal/camera_sensor.h\n> > > > +++ b/include/libcamera/internal/camera_sensor.h\n> > > > @@ -50,7 +50,7 @@ public:\n> > > >\n> > > >  \tconst std::string &model() const { return model_; }\n> > > >  \tconst MediaEntity *entity() const { return entity_; }\n> > > > -\tconst std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> > > > +\tconst std::set<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> > > >  \tconst std::vector<Size> &sizes() const { return sizes_; }\n> > > >  \tconst Size &resolution() const { return resolution_; }\n> > > >\n> > > > @@ -77,7 +77,7 @@ private:\n> > > >\n> > > >  \tImageFormats formats_;\n> > > >  \tSize resolution_;\n> > > > -\tstd::vector<unsigned int> mbusCodes_;\n> > > > +\tstd::set<unsigned int> mbusCodes_;\n> > > >  \tstd::vector<Size> sizes_;\n> > > >\n> > > >  \tControlList properties_;\n> > > > diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h\n> > > > index 4b172efc6588d374..e8aa555dcbe99350 100644\n> > > > --- a/include/libcamera/internal/formats.h\n> > > > +++ b/include/libcamera/internal/formats.h\n> > > > @@ -24,7 +24,7 @@ public:\n> > > >  \tint addFormat(unsigned int format, const std::vector<SizeRange> &sizes);\n> > > >\n> > > >  \tbool isEmpty() const;\n> > > > -\tstd::vector<unsigned int> formats() const;\n> > > > +\tstd::set<unsigned int> formats() const;\n> > > >  \tconst std::vector<SizeRange> &sizes(unsigned int format) const;\n> > > >  \tconst std::map<unsigned int, std::vector<SizeRange>> &data() const;\n> > > >\n> > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp\n> > > > index b14b4051dca606b9..5ab50de660534f3f 100644\n> > > > --- a/src/libcamera/camera_sensor.cpp\n> > > > +++ b/src/libcamera/camera_sensor.cpp\n> > > > @@ -251,7 +251,6 @@ int CameraSensor::init()\n> > > >  \t}\n> > > >\n> > > >  \tmbusCodes_ = formats_.formats();\n> > > > -\tstd::sort(mbusCodes_.begin(), mbusCodes_.end());\n> > > >\n> > > >  \tfor (const auto &format : formats_.data()) {\n> > > >  \t\tconst std::vector<SizeRange> &ranges = format.second;\n> > > > diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp\n> > > > index 1272de29c802c539..6234fd98f3e2002c 100644\n> > > > --- a/src/libcamera/formats.cpp\n> > > > +++ b/src/libcamera/formats.cpp\n> > > > @@ -68,14 +68,13 @@ bool ImageFormats::isEmpty() const\n> > > >   * \\brief Retrieve a list of all supported image formats\n> > > >   * \\return List of pixel formats or media bus codes\n> > > >   */\n> > > > -std::vector<unsigned int> ImageFormats::formats() const\n> > > > +std::set<unsigned int> ImageFormats::formats() const\n> > > >  {\n> > > > -\tstd::vector<unsigned int> formats;\n> > > > -\tformats.reserve(data_.size());\n> > > > +\tstd::set<unsigned int> formats;\n> > > >\n> > > >  \t/* \\todo: Should this be cached instead of computed each time? */\n> > > >  \tfor (auto const &it : data_)\n> > > > -\t\tformats.push_back(it.first);\n> > > > +\t\tformats.insert(it.first);\n> > > >\n> > > >  \treturn formats;\n> > > >  }\n> > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > index 5544288b14f739c0..1a59de0c58975b3c 100644\n> > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > @@ -1441,15 +1441,12 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index)\n> > > >  \t/*\n> > > >  \t * Make sure the sensor produces at least one format compatible with\n> > > >  \t * the CIO2 requirements.\n> > > > -\t *\n> > > > -\t * utils::set_overlap requires the ranges to be sorted, keep the\n> > > > -\t * cio2Codes vector sorted in ascending order.\n> > > >  \t */\n> > > > -\tconst std::vector<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGRBG10_1X10,\n> > > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGBRG10_1X10,\n> > > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SRGGB10_1X10 };\n> > > > -\tconst std::vector<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> > > > +\tconst std::set<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGRBG10_1X10,\n> > > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGBRG10_1X10,\n> > > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SRGGB10_1X10 };\n>\n> Should we make this static const ?\n>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>\n> > > > +\tconst std::set<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> > > >  \tif (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(),\n> > > >  \t\t\t\tcio2Codes.begin(), cio2Codes.end())) {\n> > > >  \t\tLOG(IPU3, Error)\n> > > > diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp\n> > > > index 8c7fd1d2d4445db3..146b1b7d6c294fdb 100644\n> > > > --- a/test/camera-sensor.cpp\n> > > > +++ b/test/camera-sensor.cpp\n> > > > @@ -67,7 +67,7 @@ protected:\n> > > >  \t\t\treturn TestFail;\n> > > >  \t\t}\n> > > >\n> > > > -\t\tconst std::vector<unsigned int> &codes = sensor_->mbusCodes();\n> > > > +\t\tconst std::set<unsigned int> &codes = sensor_->mbusCodes();\n> > > >  \t\tauto iter = std::find(codes.begin(), codes.end(),\n> > > >  \t\t\t\t      MEDIA_BUS_FMT_ARGB8888_1X32);\n> > > >  \t\tif (iter == codes.end()) {\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 838AFC0100\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 25 Jun 2020 07:45:09 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6169E609A3;\n\tThu, 25 Jun 2020 09:45:09 +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 ED31A603BE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 25 Jun 2020 09:45:07 +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 3CA2F2000D;\n\tThu, 25 Jun 2020 07:45:06 +0000 (UTC)"],"X-Originating-IP":"93.34.118.233","Date":"Thu, 25 Jun 2020 09:48:35 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20200625074835.n3mujvxmhfpn4foo@uno.localdomain>","References":"<20200623020930.1781469-1-niklas.soderlund@ragnatech.se>\n\t<20200623020930.1781469-2-niklas.soderlund@ragnatech.se>\n\t<20200624091810.nqwmovs27gtpf3v6@uno.localdomain>\n\t<20200624175337.GD1595450@oden.dyn.berto.se>\n\t<20200624234436.GL5980@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200624234436.GL5980@pendragon.ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","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=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":10804,"web_url":"https://patchwork.libcamera.org/comment/10804/","msgid":"<20200624175337.GD1595450@oden.dyn.berto.se>","date":"2020-06-24T17:53:37","subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Jacopo,\n\nThanks for your feedback.\n\nOn 2020-06-24 11:18:10 +0200, Jacopo Mondi wrote:\n> Hi Niklas,\n> \n> On Tue, Jun 23, 2020 at 04:09:21AM +0200, Niklas Söderlund wrote:\n> > It makes little sens for a CameraSensor to support the same media bus\n> \n> sense\n> s/a CameraSensor/the CameraSensor class/\n> > format multiple times, change the container from a vector<> to a set<>.\n> >\n> > This was discovered while working with the IPU3 pipeline handler that\n> > Unnecessarily had to carry code to sort vectors in order to find\n> \n> s/Un/un/\n> \n> > intersections. As this change requires switching the container to set<>\n> > in that pipeline handler as well fix this while we are at it.\n> \n> as well,\n> \n> Which sensor does report mulitple times the same mbus_code ? Isn't\n> this a driver bug if it happens ?\n\nNone does so today, and if it happens I would indeed consider it a \ndriver bug. That is the reason for this change, to us an API to \ndemonstrate that it's impossible to have the same format twice.\n\nAs an added bonus the set will always be sorted so the possibility that \nan implementation somewhere forgets to sort the vector is completely \navoided.\n\n> \n> I see  V4L2Subdevice::formats() populating the image formats with the\n> mbus codes returned by V4L2Subdevice::enumPadCodes() and when I print\n> out on Soraka the codes there collected I only get MEDIA_BUS_FMT_SGRBG10_1X10.\n> \n> Looking at the drivers of the two there installed sensors confirms\n> that only one format is supported..\n> \n> >\n> > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > ---\n> >  include/libcamera/internal/camera_sensor.h |  4 ++--\n> >  include/libcamera/internal/formats.h       |  2 +-\n> >  src/libcamera/camera_sensor.cpp            |  1 -\n> >  src/libcamera/formats.cpp                  |  7 +++----\n> >  src/libcamera/pipeline/ipu3/ipu3.cpp       | 13 +++++--------\n> >  test/camera-sensor.cpp                     |  2 +-\n> >  6 files changed, 12 insertions(+), 17 deletions(-)\n> >\n> > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\n> > index 7f07413f95602881..6d92818f16e4b752 100644\n> > --- a/include/libcamera/internal/camera_sensor.h\n> > +++ b/include/libcamera/internal/camera_sensor.h\n> > @@ -50,7 +50,7 @@ public:\n> >\n> >  \tconst std::string &model() const { return model_; }\n> >  \tconst MediaEntity *entity() const { return entity_; }\n> > -\tconst std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> > +\tconst std::set<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> >  \tconst std::vector<Size> &sizes() const { return sizes_; }\n> >  \tconst Size &resolution() const { return resolution_; }\n> >\n> > @@ -77,7 +77,7 @@ private:\n> >\n> >  \tImageFormats formats_;\n> >  \tSize resolution_;\n> > -\tstd::vector<unsigned int> mbusCodes_;\n> > +\tstd::set<unsigned int> mbusCodes_;\n> >  \tstd::vector<Size> sizes_;\n> >\n> >  \tControlList properties_;\n> > diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h\n> > index 4b172efc6588d374..e8aa555dcbe99350 100644\n> > --- a/include/libcamera/internal/formats.h\n> > +++ b/include/libcamera/internal/formats.h\n> > @@ -24,7 +24,7 @@ public:\n> >  \tint addFormat(unsigned int format, const std::vector<SizeRange> &sizes);\n> >\n> >  \tbool isEmpty() const;\n> > -\tstd::vector<unsigned int> formats() const;\n> > +\tstd::set<unsigned int> formats() const;\n> >  \tconst std::vector<SizeRange> &sizes(unsigned int format) const;\n> >  \tconst std::map<unsigned int, std::vector<SizeRange>> &data() const;\n> >\n> > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp\n> > index b14b4051dca606b9..5ab50de660534f3f 100644\n> > --- a/src/libcamera/camera_sensor.cpp\n> > +++ b/src/libcamera/camera_sensor.cpp\n> > @@ -251,7 +251,6 @@ int CameraSensor::init()\n> >  \t}\n> >\n> >  \tmbusCodes_ = formats_.formats();\n> > -\tstd::sort(mbusCodes_.begin(), mbusCodes_.end());\n> >\n> >  \tfor (const auto &format : formats_.data()) {\n> >  \t\tconst std::vector<SizeRange> &ranges = format.second;\n> > diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp\n> > index 1272de29c802c539..6234fd98f3e2002c 100644\n> > --- a/src/libcamera/formats.cpp\n> > +++ b/src/libcamera/formats.cpp\n> > @@ -68,14 +68,13 @@ bool ImageFormats::isEmpty() const\n> >   * \\brief Retrieve a list of all supported image formats\n> >   * \\return List of pixel formats or media bus codes\n> >   */\n> > -std::vector<unsigned int> ImageFormats::formats() const\n> > +std::set<unsigned int> ImageFormats::formats() const\n> >  {\n> > -\tstd::vector<unsigned int> formats;\n> > -\tformats.reserve(data_.size());\n> > +\tstd::set<unsigned int> formats;\n> >\n> >  \t/* \\todo: Should this be cached instead of computed each time? */\n> >  \tfor (auto const &it : data_)\n> > -\t\tformats.push_back(it.first);\n> > +\t\tformats.insert(it.first);\n> >\n> >  \treturn formats;\n> >  }\n> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > index 5544288b14f739c0..1a59de0c58975b3c 100644\n> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > @@ -1441,15 +1441,12 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index)\n> >  \t/*\n> >  \t * Make sure the sensor produces at least one format compatible with\n> >  \t * the CIO2 requirements.\n> > -\t *\n> > -\t * utils::set_overlap requires the ranges to be sorted, keep the\n> > -\t * cio2Codes vector sorted in ascending order.\n> >  \t */\n> > -\tconst std::vector<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGRBG10_1X10,\n> > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGBRG10_1X10,\n> > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SRGGB10_1X10 };\n> > -\tconst std::vector<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> > +\tconst std::set<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGRBG10_1X10,\n> > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGBRG10_1X10,\n> > +\t\t\t\t\t\tMEDIA_BUS_FMT_SRGGB10_1X10 };\n> > +\tconst std::set<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> >  \tif (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(),\n> >  \t\t\t\tcio2Codes.begin(), cio2Codes.end())) {\n> >  \t\tLOG(IPU3, Error)\n> > diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp\n> > index 8c7fd1d2d4445db3..146b1b7d6c294fdb 100644\n> > --- a/test/camera-sensor.cpp\n> > +++ b/test/camera-sensor.cpp\n> > @@ -67,7 +67,7 @@ protected:\n> >  \t\t\treturn TestFail;\n> >  \t\t}\n> >\n> > -\t\tconst std::vector<unsigned int> &codes = sensor_->mbusCodes();\n> > +\t\tconst std::set<unsigned int> &codes = sensor_->mbusCodes();\n> >  \t\tauto iter = std::find(codes.begin(), codes.end(),\n> >  \t\t\t\t      MEDIA_BUS_FMT_ARGB8888_1X32);\n> >  \t\tif (iter == codes.end()) {\n> > --\n> > 2.27.0\n> >\n> > _______________________________________________\n> > libcamera-devel mailing list\n> > libcamera-devel@lists.libcamera.org\n> > https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-lf1-x142.google.com (mail-lf1-x142.google.com\n\t[IPv6:2a00:1450:4864:20::142])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 672D8603BA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 24 Jun 2020 19:53:39 +0200 (CEST)","by mail-lf1-x142.google.com with SMTP id y18so1735431lfh.11\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 24 Jun 2020 10:53:39 -0700 (PDT)","from localhost (h-209-203.A463.priv.bahnhof.se. [155.4.209.203])\n\tby smtp.gmail.com with ESMTPSA id\n\tn21sm4320748ljj.97.2020.06.24.10.53.37\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 24 Jun 2020 10:53:37 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=ragnatech-se.20150623.gappssmtp.com\n\theader.i=@ragnatech-se.20150623.gappssmtp.com header.b=\"nWEzkqzi\"; \n\tdkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to;\n\tbh=XvlltenyBWzLrwboD/6zeCiAiGQqoI55q0uCKF8bRBQ=;\n\tb=nWEzkqziXU6rlMv+MbBKuq5F+mHpITz9V6qySuJAjPh3QBuaA2UVRYr2m3a+EgZGTe\n\tVaKc3mdSqearn9Pfn0EH2JJw17C4f6MXAdtNgygbYU92uoP7AIbevodSERj555Vq7SZO\n\tim9FxKWYqVCpvihZYbSHkv4gUnhwqMCt1UHl89B8QWZ+UvJX8rZz0+dyNJxuh33++bDr\n\tRzAy3IJ4Vmr9DiZDZaU6qHIBOK/U9k7KTGgcgqv8U8CfBKAB6Mxrb7Ct/rmK3fDRJ/oh\n\tdEv/h9LpfX28aPjIu3dOSVRiZY/XWIqsqo00dUnS3AdiaMcvRO2Evw4HJNn5Bd9SPKL8\n\tpfug==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to;\n\tbh=XvlltenyBWzLrwboD/6zeCiAiGQqoI55q0uCKF8bRBQ=;\n\tb=g909A0Rhe//tTj6wFDGSpciLWdKWGD78oiVlYeQmDdYvg6H64Hgk8n60SXacbotufy\n\t4IwyexKXBemF5WGAna61Mq5gxwMTul/6cQ7gNz9i1F9Ii3AnmidlEtst5cIM2O0FSKHw\n\twdhdRa+s/FoG11/gpAwl3U57EsfPk7WzCDEhlcEeI9k2ouVyzXbyle8UIUI9aHIPPdlN\n\tK3KOnqVUN5L11dJ5IYMDdBrUmLNErhV16lqGyAJGtztMWWAxbRiARDgWB6829NWOMugj\n\tba09NlKaxkFrAa9wzlL6jR85O3cuE/c0ViqF8gje7/geuSR7oFtvFisyNaeXHIoBz84E\n\th9nQ==","X-Gm-Message-State":"AOAM5320dF2c+0eMTQlIfBhuDA9uCPuguoJIstCu9CLlSdpckdetgqPq\n\t5E2wHmWHKrJE84R3dFX9AR97nOKrx+Y=","X-Google-Smtp-Source":"ABdhPJzKHq3fdxwo5Xk4WRVjiv5FiHR/ssB1cxB5J+22KWJ7qpKogCCey/5HGEhwmdBUJrqQVNJp4A==","X-Received":"by 2002:a19:e346:: with SMTP id\n\tc6mr16394538lfk.177.1593021218639; \n\tWed, 24 Jun 2020 10:53:38 -0700 (PDT)","Date":"Wed, 24 Jun 2020 19:53:37 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200624175337.GD1595450@oden.dyn.berto.se>","References":"<20200623020930.1781469-1-niklas.soderlund@ragnatech.se>\n\t<20200623020930.1781469-2-niklas.soderlund@ragnatech.se>\n\t<20200624091810.nqwmovs27gtpf3v6@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20200624091810.nqwmovs27gtpf3v6@uno.localdomain>","Subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","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>","X-List-Received-Date":"Wed, 24 Jun 2020 17:53:39 -0000"}},{"id":10862,"web_url":"https://patchwork.libcamera.org/comment/10862/","msgid":"<20200625190944.GB303959@oden.dyn.berto.se>","date":"2020-06-25T19:09:44","subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi,\n\nOn 2020-06-25 09:48:35 +0200, Jacopo Mondi wrote:\n> Hi\n> \n> On Thu, Jun 25, 2020 at 02:44:36AM +0300, Laurent Pinchart wrote:\n> > Hi Niklas,\n> >\n> > On Wed, Jun 24, 2020 at 07:53:37PM +0200, Niklas Söderlund wrote:\n> > > On 2020-06-24 11:18:10 +0200, Jacopo Mondi wrote:\n> > > > On Tue, Jun 23, 2020 at 04:09:21AM +0200, Niklas Söderlund wrote:\n> > > > > It makes little sens for a CameraSensor to support the same media bus\n> > > >\n> > > > sense\n> > > > s/a CameraSensor/the CameraSensor class/\n> >\n> > Or \"for a camera sensor\".\n> >\n> > > > > format multiple times, change the container from a vector<> to a set<>.\n> > > > >\n> > > > > This was discovered while working with the IPU3 pipeline handler that\n> > > > > Unnecessarily had to carry code to sort vectors in order to find\n> > > >\n> > > > s/Un/un/\n> > > >\n> > > > > intersections. As this change requires switching the container to set<>\n> > > > > in that pipeline handler as well fix this while we are at it.\n> > > >\n> > > > as well,\n> > > >\n> > > > Which sensor does report mulitple times the same mbus_code ? Isn't\n> > > > this a driver bug if it happens ?\n> > >\n> > > None does so today, and if it happens I would indeed consider it a\n> > > driver bug. That is the reason for this change, to us an API to\n> > > demonstrate that it's impossible to have the same format twice.\n> > >\n> > > As an added bonus the set will always be sorted so the possibility that\n> > > an implementation somewhere forgets to sort the vector is completely\n> > > avoided.\n> >\n> > std::set is however more complex than std::vector. None of this should\n> > run in a hot path, so I'm ok with the change, but I think we need to\n> > take complexity into account in API design.\n> \n> I still don't think we need any of this. If a driver reports two\n> identical mbus codes, it's buggy and should be fixed. There's no\n> reason I can see to work around it \"just in case\" here.\n\nI think it's more then \"just in case\". IMHO it's a better API because it \ntells the user it's impossible to have multiple entries of the same \nvalue. Without this in the API the user must know this as a fact of the \nV4L2 API and if it would find duplicates that the bug is in the driver \nand not somewhere else.\n\n> \n> >\n> > > > I see  V4L2Subdevice::formats() populating the image formats with the\n> > > > mbus codes returned by V4L2Subdevice::enumPadCodes() and when I print\n> > > > out on Soraka the codes there collected I only get MEDIA_BUS_FMT_SGRBG10_1X10.\n> > > >\n> > > > Looking at the drivers of the two there installed sensors confirms\n> > > > that only one format is supported..\n> > > >\n> > > > >\n> > > > > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > > > > ---\n> > > > >  include/libcamera/internal/camera_sensor.h |  4 ++--\n> > > > >  include/libcamera/internal/formats.h       |  2 +-\n> > > > >  src/libcamera/camera_sensor.cpp            |  1 -\n> > > > >  src/libcamera/formats.cpp                  |  7 +++----\n> > > > >  src/libcamera/pipeline/ipu3/ipu3.cpp       | 13 +++++--------\n> > > > >  test/camera-sensor.cpp                     |  2 +-\n> > > > >  6 files changed, 12 insertions(+), 17 deletions(-)\n> > > > >\n> > > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\n> > > > > index 7f07413f95602881..6d92818f16e4b752 100644\n> > > > > --- a/include/libcamera/internal/camera_sensor.h\n> > > > > +++ b/include/libcamera/internal/camera_sensor.h\n> > > > > @@ -50,7 +50,7 @@ public:\n> > > > >\n> > > > >  \tconst std::string &model() const { return model_; }\n> > > > >  \tconst MediaEntity *entity() const { return entity_; }\n> > > > > -\tconst std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> > > > > +\tconst std::set<unsigned int> &mbusCodes() const { return mbusCodes_; }\n> > > > >  \tconst std::vector<Size> &sizes() const { return sizes_; }\n> > > > >  \tconst Size &resolution() const { return resolution_; }\n> > > > >\n> > > > > @@ -77,7 +77,7 @@ private:\n> > > > >\n> > > > >  \tImageFormats formats_;\n> > > > >  \tSize resolution_;\n> > > > > -\tstd::vector<unsigned int> mbusCodes_;\n> > > > > +\tstd::set<unsigned int> mbusCodes_;\n> > > > >  \tstd::vector<Size> sizes_;\n> > > > >\n> > > > >  \tControlList properties_;\n> > > > > diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h\n> > > > > index 4b172efc6588d374..e8aa555dcbe99350 100644\n> > > > > --- a/include/libcamera/internal/formats.h\n> > > > > +++ b/include/libcamera/internal/formats.h\n> > > > > @@ -24,7 +24,7 @@ public:\n> > > > >  \tint addFormat(unsigned int format, const std::vector<SizeRange> &sizes);\n> > > > >\n> > > > >  \tbool isEmpty() const;\n> > > > > -\tstd::vector<unsigned int> formats() const;\n> > > > > +\tstd::set<unsigned int> formats() const;\n> > > > >  \tconst std::vector<SizeRange> &sizes(unsigned int format) const;\n> > > > >  \tconst std::map<unsigned int, std::vector<SizeRange>> &data() const;\n> > > > >\n> > > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp\n> > > > > index b14b4051dca606b9..5ab50de660534f3f 100644\n> > > > > --- a/src/libcamera/camera_sensor.cpp\n> > > > > +++ b/src/libcamera/camera_sensor.cpp\n> > > > > @@ -251,7 +251,6 @@ int CameraSensor::init()\n> > > > >  \t}\n> > > > >\n> > > > >  \tmbusCodes_ = formats_.formats();\n> > > > > -\tstd::sort(mbusCodes_.begin(), mbusCodes_.end());\n> > > > >\n> > > > >  \tfor (const auto &format : formats_.data()) {\n> > > > >  \t\tconst std::vector<SizeRange> &ranges = format.second;\n> > > > > diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp\n> > > > > index 1272de29c802c539..6234fd98f3e2002c 100644\n> > > > > --- a/src/libcamera/formats.cpp\n> > > > > +++ b/src/libcamera/formats.cpp\n> > > > > @@ -68,14 +68,13 @@ bool ImageFormats::isEmpty() const\n> > > > >   * \\brief Retrieve a list of all supported image formats\n> > > > >   * \\return List of pixel formats or media bus codes\n> > > > >   */\n> > > > > -std::vector<unsigned int> ImageFormats::formats() const\n> > > > > +std::set<unsigned int> ImageFormats::formats() const\n> > > > >  {\n> > > > > -\tstd::vector<unsigned int> formats;\n> > > > > -\tformats.reserve(data_.size());\n> > > > > +\tstd::set<unsigned int> formats;\n> > > > >\n> > > > >  \t/* \\todo: Should this be cached instead of computed each time? */\n> > > > >  \tfor (auto const &it : data_)\n> > > > > -\t\tformats.push_back(it.first);\n> > > > > +\t\tformats.insert(it.first);\n> > > > >\n> > > > >  \treturn formats;\n> > > > >  }\n> > > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > index 5544288b14f739c0..1a59de0c58975b3c 100644\n> > > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > @@ -1441,15 +1441,12 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index)\n> > > > >  \t/*\n> > > > >  \t * Make sure the sensor produces at least one format compatible with\n> > > > >  \t * the CIO2 requirements.\n> > > > > -\t *\n> > > > > -\t * utils::set_overlap requires the ranges to be sorted, keep the\n> > > > > -\t * cio2Codes vector sorted in ascending order.\n> > > > >  \t */\n> > > > > -\tconst std::vector<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > > > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGRBG10_1X10,\n> > > > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SGBRG10_1X10,\n> > > > > -\t\t\t\t\t\t   MEDIA_BUS_FMT_SRGGB10_1X10 };\n> > > > > -\tconst std::vector<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> > > > > +\tconst std::set<unsigned int> cio2Codes{ MEDIA_BUS_FMT_SBGGR10_1X10,\n> > > > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGRBG10_1X10,\n> > > > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SGBRG10_1X10,\n> > > > > +\t\t\t\t\t\tMEDIA_BUS_FMT_SRGGB10_1X10 };\n> >\n> > Should we make this static const ?\n> >\n> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >\n> > > > > +\tconst std::set<unsigned int> &sensorCodes = sensor_->mbusCodes();\n> > > > >  \tif (!utils::set_overlap(sensorCodes.begin(), sensorCodes.end(),\n> > > > >  \t\t\t\tcio2Codes.begin(), cio2Codes.end())) {\n> > > > >  \t\tLOG(IPU3, Error)\n> > > > > diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp\n> > > > > index 8c7fd1d2d4445db3..146b1b7d6c294fdb 100644\n> > > > > --- a/test/camera-sensor.cpp\n> > > > > +++ b/test/camera-sensor.cpp\n> > > > > @@ -67,7 +67,7 @@ protected:\n> > > > >  \t\t\treturn TestFail;\n> > > > >  \t\t}\n> > > > >\n> > > > > -\t\tconst std::vector<unsigned int> &codes = sensor_->mbusCodes();\n> > > > > +\t\tconst std::set<unsigned int> &codes = sensor_->mbusCodes();\n> > > > >  \t\tauto iter = std::find(codes.begin(), codes.end(),\n> > > > >  \t\t\t\t      MEDIA_BUS_FMT_ARGB8888_1X32);\n> > > > >  \t\tif (iter == codes.end()) {\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 CBAE8C0109\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 25 Jun 2020 19:09:49 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 34037609C5;\n\tThu, 25 Jun 2020 21:09:49 +0200 (CEST)","from mail-lj1-x242.google.com (mail-lj1-x242.google.com\n\t[IPv6:2a00:1450:4864:20::242])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0C817609A5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 25 Jun 2020 21:09:47 +0200 (CEST)","by mail-lj1-x242.google.com with SMTP id 9so7733559ljc.8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 25 Jun 2020 12:09:46 -0700 (PDT)","from localhost (h-209-203.A463.priv.bahnhof.se. [155.4.209.203])\n\tby smtp.gmail.com with ESMTPSA id\n\ty12sm5846ljj.113.2020.06.25.12.09.44\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 25 Jun 2020 12:09:45 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=ragnatech-se.20150623.gappssmtp.com\n\theader.i=@ragnatech-se.20150623.gappssmtp.com\n\theader.b=\"c/7LutO6\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to;\n\tbh=Ci9UDja8v6LWZrG7CmiiCHQf3jGX2y4RpSiEJij7rcQ=;\n\tb=c/7LutO61RJuT+QtlMBLpLvm9MLnMTGR60V6DQkEiAUPPpRKGOA72/qFfKxpnWrBmw\n\tw35ZQiTQlgaOn9RNZK08WM97QEkqj+HqKGx61EVFPiXVLfEuGs4zRGzWmtbQC3YTp2dZ\n\to9rxm+I5vHZEvypMDzPhmcAM0Lx0sKkgl9R+JaeP0FSw2D6rKgKurBfyRHOHut5fkegk\n\tCXx9h1IJNgHUgaIzBAXPSIoyWafTLMa9pz3PEf5Ko/lebDo2VRert7E4ohqM5efVCC93\n\t3XJR+Vb0LVMAEBsjK0F0zMsfxovw12g5XeFPLFNGmx2xZFaPXYmPQoiKru3uMvuSrget\n\tmYgQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to;\n\tbh=Ci9UDja8v6LWZrG7CmiiCHQf3jGX2y4RpSiEJij7rcQ=;\n\tb=J9JfwUfwR86WGcdmxYMw4slrW9rHA/VPgaP0hco2RbZ/EQ+vzxxRKhlumN8FjAnMhF\n\tWYxs+KqxsunFD9jaBTIiTNWRt26KqAd1cgrKsrt20lpJWe55sVEqH5Z2dC7rBrT9kWS9\n\t9LOdTCJomuil+nMy3nalU8UUe0eAqyWCvV3jOLVoEyfR2WTCcx9FfHlE5Vm1KKSi6wlG\n\tXwvAFQ5gjgi8YQYApVLWLp3tJQeNWqv5y6wKuLPDAxg4Zg4JGKaVPLc3gR5T3sdyDF4O\n\tAnCkZaodABhQgPQmW9OoxJiHG/V6436q9AEFfxoSEPkVnRkiLn10mQWXotPq5IJjbs8f\n\t3Pjw==","X-Gm-Message-State":"AOAM530APOL61LyFa4YrwQt7kHVSs6NwNRy/Byx8qpNRMK80L9h7+S5z\n\tCGtq8HPtDiTw9YK2Kv0nWTf0oQ==","X-Google-Smtp-Source":"ABdhPJyWyn7Pzs7zyek6PY2OQal7HsvWX2W7P/0jSyeZUgra9LmPg7SnFOF4FUhFZnbif/WCVPpWRw==","X-Received":"by 2002:a2e:9790:: with SMTP id\n\ty16mr16575489lji.150.1593112185825; \n\tThu, 25 Jun 2020 12:09:45 -0700 (PDT)","Date":"Thu, 25 Jun 2020 21:09:44 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<20200625190944.GB303959@oden.dyn.berto.se>","References":"<20200623020930.1781469-1-niklas.soderlund@ragnatech.se>\n\t<20200623020930.1781469-2-niklas.soderlund@ragnatech.se>\n\t<20200624091810.nqwmovs27gtpf3v6@uno.localdomain>\n\t<20200624175337.GD1595450@oden.dyn.berto.se>\n\t<20200624234436.GL5980@pendragon.ideasonboard.com>\n\t<20200625074835.n3mujvxmhfpn4foo@uno.localdomain>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200625074835.n3mujvxmhfpn4foo@uno.localdomain>","Subject":"Re: [libcamera-devel] [PATCH v3 01/10] libcamera: camera_sensor:\n\tMake mbusCodes() return a set","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=\"iso-8859-1\"","Content-Transfer-Encoding":"quoted-printable","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]