[{"id":33503,"web_url":"https://patchwork.libcamera.org/comment/33503/","msgid":"<174069185836.31628.9546419944108852400@ping.linuxembedded.co.uk>","date":"2025-02-27T21:30:58","subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Barnabas,\n\nThanks for the fix ups - I see the compilers are all now happy with this\nseries, so the gcc-9 issue is gone.\n\n\nQuoting Barnabás Pőcze (2025-02-17 18:53:34)\n> `ControlInfo(Span<const int32_t>{...})` calls the incorrect constructor\n> of `ControlInfo`. The intended constructor to be called is\n> `ControlInfo(Span<const ControlValue>, ...)` however that is not called\n> because a span of `const int32_t` is passed. Instead, the constructor\n> `ControlInfo(const ControlValue &min, const ControlValue &max, ...)`\n> will be called.\n> \n> Furthermore, since `values.back()` is used, only the last element of\n> the array is actually populated.\n> \n> To fix this, convert the array to contain `ControlValue` objects\n> and use a separate variable to keep track of which element is to\n> be populated next.\n> \n> The available modes are saved for later so that the appropriate mode\n> can be selected when the control is set.\n> \n> Fixes: bad8d591f8acfa (\"libcamera: uvcvideo: Register ExposureTimeMode control\")\n> Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n> ---\n>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 46 ++++++++++++--------\n>  1 file changed, 27 insertions(+), 19 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> index dedcac89b..1f604b91e 100644\n> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> @@ -6,6 +6,7 @@\n>   */\n>  \n>  #include <algorithm>\n> +#include <bitset>\n>  #include <cmath>\n>  #include <fstream>\n>  #include <map>\n> @@ -58,6 +59,13 @@ public:\n>         Stream stream_;\n>         std::map<PixelFormat, std::vector<SizeRange>> formats_;\n>  \n> +       std::bitset<\n> +               std::max(V4L2_EXPOSURE_AUTO,\n> +               std::max(V4L2_EXPOSURE_MANUAL,\n> +               std::max(V4L2_EXPOSURE_APERTURE_PRIORITY,\n> +                        V4L2_EXPOSURE_SHUTTER_PRIORITY))) + 1\n\nI assume std::max becomes constexpr here (checked, and it does).\nclangformat wants to indent these, but it does make sense as a list.\n\nI wonder if putting them it a local const array and using some constexpr\niteration ... but then we may as well put a constexpr helper in to\ninclude/libcamera/base/utils.h ....\n\nMaybe if we find ourselves doing this again ?\n\n\n> +       > availableExposureModes_;\n> +\n>  private:\n>         bool generateId();\n>  \n> @@ -725,25 +733,25 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n>                  * ExposureTimeModeManual = { V4L2_EXPOSURE_MANUAL,\n>                  *                            V4L2_EXPOSURE_SHUTTER_PRIORITY }\n>                  */\n> -               std::array<int32_t, 2> values{};\n> -\n> -               auto it = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> -                       [&](const ControlValue &val) {\n> -                               return (val.get<int32_t>() == V4L2_EXPOSURE_APERTURE_PRIORITY ||\n> -                                       val.get<int32_t>() == V4L2_EXPOSURE_AUTO) ? true : false;\n> -                       });\n> -               if (it != v4l2Values.end())\n> -                       values.back() = static_cast<int32_t>(controls::ExposureTimeModeAuto);\n> -\n> -               it = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> -                       [&](const ControlValue &val) {\n> -                               return (val.get<int32_t>() == V4L2_EXPOSURE_SHUTTER_PRIORITY ||\n> -                                       val.get<int32_t>() == V4L2_EXPOSURE_MANUAL) ? true : false;\n> -                       });\n> -               if (it != v4l2Values.end())\n> -                       values.back() = static_cast<int32_t>(controls::ExposureTimeModeManual);\n> -\n> -               info = ControlInfo{Span<int32_t>{values}, values[0]};\n> +               for (const ControlValue &value : v4l2Values) {\n> +                       auto x = value.get<int32_t>();\n> +                       if (0 <= x && static_cast<size_t>(x) < availableExposureModes_.size())\n> +                               availableExposureModes_[x] = true;\n> +               }\n> +\n> +               std::array<ControlValue, 2> values;\n> +               std::size_t count = 0;\n> +\n> +               if (availableExposureModes_[V4L2_EXPOSURE_AUTO] || availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n\nThis hits some long lines. Might be tempting to format this as:\n\n\n\t\tif (availableExposureModes_[V4L2_EXPOSURE_AUTO] ||\n\t\t    availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n\t\t\tvalues[count++] = controls::ExposureTimeModeAuto;\n\nBut I like this patch for more succinct code.\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> +                       values[count++] = controls::ExposureTimeModeAuto;\n> +\n> +               if (availableExposureModes_[V4L2_EXPOSURE_MANUAL] || availableExposureModes_[V4L2_EXPOSURE_SHUTTER_PRIORITY])\n> +                       values[count++] = controls::ExposureTimeModeManual;\n> +\n> +               if (count == 0)\n> +                       return;\n> +\n> +               info = ControlInfo{ Span<const ControlValue>{ values.data(), count }, values[0] };\n>                 break;\n>         }\n>         case V4L2_CID_EXPOSURE_ABSOLUTE:\n> -- \n> 2.48.1\n> \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CDAF9C3259\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Feb 2025 21:31:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CD56768761;\n\tThu, 27 Feb 2025 22:31:03 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AA91B60322\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Feb 2025 22:31:01 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C0E68982;\n\tThu, 27 Feb 2025 22:29:32 +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=\"gDriOzap\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1740691772;\n\tbh=UDcwoBJ+PZQgQkIVSKYQEezRFfze+VEvKT7sk3gdpmY=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=gDriOzapXpVSbDK1wrAcpoPM5x4JmdDakaLAPOg4nFmR2ZMDR4A274ZPOJgtaiXh8\n\t2YXMbjI0OY0BcWx+N6CYR+u8l2pOFJ2k1Mr1YmxMBjSSSd0bLTFyV6AoftaCQuJbts\n\tgavVAE0cHDow7cREV5p2j2GYM1VBJreELRjCZeWg=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20250217185327.306509-2-pobrn@protonmail.com>","References":"<20250217185327.306509-1-pobrn@protonmail.com>\n\t<20250217185327.306509-2-pobrn@protonmail.com>","Subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Thu, 27 Feb 2025 21:30:58 +0000","Message-ID":"<174069185836.31628.9546419944108852400@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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":33510,"web_url":"https://patchwork.libcamera.org/comment/33510/","msgid":"<lo7xng6m3w4ibmkcwcmtfuklo2exyucqbz7ovw7luxh3apxu25@3ehq2mnxde3x>","date":"2025-02-28T11:06:40","subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Barnabás\n\nOn Mon, Feb 17, 2025 at 06:53:34PM +0000, Barnabás Pőcze wrote:\n> `ControlInfo(Span<const int32_t>{...})` calls the incorrect constructor\n> of `ControlInfo`. The intended constructor to be called is\n> `ControlInfo(Span<const ControlValue>, ...)` however that is not called\n> because a span of `const int32_t` is passed. Instead, the constructor\n> `ControlInfo(const ControlValue &min, const ControlValue &max, ...)`\n> will be called.\n>\n> Furthermore, since `values.back()` is used, only the last element of\n> the array is actually populated.\n>\n> To fix this, convert the array to contain `ControlValue` objects\n> and use a separate variable to keep track of which element is to\n> be populated next.\n>\n> The available modes are saved for later so that the appropriate mode\n> can be selected when the control is set.\n>\n> Fixes: bad8d591f8acfa (\"libcamera: uvcvideo: Register ExposureTimeMode control\")\n> Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n> ---\n>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 46 ++++++++++++--------\n>  1 file changed, 27 insertions(+), 19 deletions(-)\n>\n> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> index dedcac89b..1f604b91e 100644\n> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> @@ -6,6 +6,7 @@\n>   */\n>\n>  #include <algorithm>\n> +#include <bitset>\n>  #include <cmath>\n>  #include <fstream>\n>  #include <map>\n> @@ -58,6 +59,13 @@ public:\n>  \tStream stream_;\n>  \tstd::map<PixelFormat, std::vector<SizeRange>> formats_;\n>\n> +\tstd::bitset<\n> +\t\tstd::max(V4L2_EXPOSURE_AUTO,\n> +\t\tstd::max(V4L2_EXPOSURE_MANUAL,\n> +\t\tstd::max(V4L2_EXPOSURE_APERTURE_PRIORITY,\n> +\t\t\t V4L2_EXPOSURE_SHUTTER_PRIORITY))) + 1\n\nThe enum v4l2_exposure_auto_type definition is part of the linux\nkernel ABI, and I don't expect them to change. Maybe new modes might\nbe added, but in that case you would have to change the above anyway.\n\n\n> +\t> availableExposureModes_;\n> +\n>  private:\n>  \tbool generateId();\n>\n> @@ -725,25 +733,25 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n>  \t\t * ExposureTimeModeManual = { V4L2_EXPOSURE_MANUAL,\n>  \t\t *\t\t\t      V4L2_EXPOSURE_SHUTTER_PRIORITY }\n>  \t\t */\n> -\t\tstd::array<int32_t, 2> values{};\n> -\n> -\t\tauto it = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> -\t\t\t[&](const ControlValue &val) {\n> -\t\t\t\treturn (val.get<int32_t>() == V4L2_EXPOSURE_APERTURE_PRIORITY ||\n> -\t\t\t\t\tval.get<int32_t>() == V4L2_EXPOSURE_AUTO) ? true : false;\n> -\t\t\t});\n> -\t\tif (it != v4l2Values.end())\n> -\t\t\tvalues.back() = static_cast<int32_t>(controls::ExposureTimeModeAuto);\n> -\n> -\t\tit = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> -\t\t\t[&](const ControlValue &val) {\n> -\t\t\t\treturn (val.get<int32_t>() == V4L2_EXPOSURE_SHUTTER_PRIORITY ||\n> -\t\t\t\t\tval.get<int32_t>() == V4L2_EXPOSURE_MANUAL) ? true : false;\n> -\t\t\t});\n> -\t\tif (it != v4l2Values.end())\n> -\t\t\tvalues.back() = static_cast<int32_t>(controls::ExposureTimeModeManual);\n> -\n> -\t\tinfo = ControlInfo{Span<int32_t>{values}, values[0]};\n> +\t\tfor (const ControlValue &value : v4l2Values) {\n> +\t\t\tauto x = value.get<int32_t>();\n> +\t\t\tif (0 <= x && static_cast<size_t>(x) < availableExposureModes_.size())\n\nv4l2Values comes from kernel and can only be a value from enum\nv4l2_exposure_auto_type right ? The above check shouldn't be needed,\nat least the < 0 part..\n\n> +\t\t\t\tavailableExposureModes_[x] = true;\n> +\t\t}\n> +\n> +\t\tstd::array<ControlValue, 2> values;\n> +\t\tstd::size_t count = 0;\n> +\n> +\t\tif (availableExposureModes_[V4L2_EXPOSURE_AUTO] || availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n\nBreak this lines as suggested by Kieran\n\nThanks\n  j\n\n> +\t\t\tvalues[count++] = controls::ExposureTimeModeAuto;\n> +\n> +\t\tif (availableExposureModes_[V4L2_EXPOSURE_MANUAL] || availableExposureModes_[V4L2_EXPOSURE_SHUTTER_PRIORITY])\n> +\t\t\tvalues[count++] = controls::ExposureTimeModeManual;\n> +\n> +\t\tif (count == 0)\n> +\t\t\treturn;\n> +\n> +\t\tinfo = ControlInfo{ Span<const ControlValue>{ values.data(), count }, values[0] };\n>  \t\tbreak;\n>  \t}\n>  \tcase V4L2_CID_EXPOSURE_ABSOLUTE:\n> --\n> 2.48.1\n>\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 5638FC3259\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 28 Feb 2025 11:06:45 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 38F016876A;\n\tFri, 28 Feb 2025 12:06:44 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 65BC561853\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 28 Feb 2025 12:06:43 +0100 (CET)","from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1BE77250;\n\tFri, 28 Feb 2025 12:05:14 +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=\"lEJqabMf\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1740740714;\n\tbh=e5MrjjdpRdsvFWn6JitJFq+MJ5nb3i5xfvvl5JeTqyA=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=lEJqabMfvneYo1PA1rf38DZ71Xw1xnDL65WAt2LTFZMR65wAU4yQJFcjJQsywnv0T\n\tz5ROqjwTQnjVXv9M3d7o4BqZdndfKtAbfUS7YdPJT95hbCvS6tRITlMFuc7Cv+P8AL\n\tLTFXfRqu5PTYaJnzHHM9uCsIhQidexGpde8lcKw8=","Date":"Fri, 28 Feb 2025 12:06:40 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","Message-ID":"<lo7xng6m3w4ibmkcwcmtfuklo2exyucqbz7ovw7luxh3apxu25@3ehq2mnxde3x>","References":"<20250217185327.306509-1-pobrn@protonmail.com>\n\t<20250217185327.306509-2-pobrn@protonmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20250217185327.306509-2-pobrn@protonmail.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":33512,"web_url":"https://patchwork.libcamera.org/comment/33512/","msgid":"<Y2kGCVptH46TrGA8LEIp_KiPQyJpiQMNK64EyKy1c8GL6YbNiunoB_bnCNj3GjhI2j7O7UhNwJfGRdJuzY3xKlE3Z6-Ic_vFZlN4nzxzcEw=@protonmail.com>","date":"2025-02-28T11:45:38","subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","submitter":{"id":133,"url":"https://patchwork.libcamera.org/api/people/133/","name":"Pőcze Barnabás","email":"pobrn@protonmail.com"},"content":"Hi\n\n\n2025. február 28., péntek 12:06 keltezéssel, Jacopo Mondi <jacopo.mondi@ideasonboard.com> írta:\n\n> Hi Barnabás\n> \n> On Mon, Feb 17, 2025 at 06:53:34PM +0000, Barnabás Pőcze wrote:\n> > `ControlInfo(Span<const int32_t>{...})` calls the incorrect constructor\n> > of `ControlInfo`. The intended constructor to be called is\n> > `ControlInfo(Span<const ControlValue>, ...)` however that is not called\n> > because a span of `const int32_t` is passed. Instead, the constructor\n> > `ControlInfo(const ControlValue &min, const ControlValue &max, ...)`\n> > will be called.\n> >\n> > Furthermore, since `values.back()` is used, only the last element of\n> > the array is actually populated.\n> >\n> > To fix this, convert the array to contain `ControlValue` objects\n> > and use a separate variable to keep track of which element is to\n> > be populated next.\n> >\n> > The available modes are saved for later so that the appropriate mode\n> > can be selected when the control is set.\n> >\n> > Fixes: bad8d591f8acfa (\"libcamera: uvcvideo: Register ExposureTimeMode control\")\n> > Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n> > ---\n> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 46 ++++++++++++--------\n> >  1 file changed, 27 insertions(+), 19 deletions(-)\n> >\n> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > index dedcac89b..1f604b91e 100644\n> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > @@ -6,6 +6,7 @@\n> >   */\n> >\n> >  #include <algorithm>\n> > +#include <bitset>\n> >  #include <cmath>\n> >  #include <fstream>\n> >  #include <map>\n> > @@ -58,6 +59,13 @@ public:\n> >  \tStream stream_;\n> >  \tstd::map<PixelFormat, std::vector<SizeRange>> formats_;\n> >\n> > +\tstd::bitset<\n> > +\t\tstd::max(V4L2_EXPOSURE_AUTO,\n> > +\t\tstd::max(V4L2_EXPOSURE_MANUAL,\n> > +\t\tstd::max(V4L2_EXPOSURE_APERTURE_PRIORITY,\n> > +\t\t\t V4L2_EXPOSURE_SHUTTER_PRIORITY))) + 1\n> \n> The enum v4l2_exposure_auto_type definition is part of the linux\n> kernel ABI, and I don't expect them to change. Maybe new modes might\n> be added, but in that case you would have to change the above anyway.\n\nI think the intent here is very clear. Alternatives I can think of: `std::bitset<4>`,\nor `std::bitset<V4L2_EXPOSURE_APERTURE_PRIORITY + 1>` are all less clear in my opinion.\n\nIf there was a `V4L2_EXPOSURE_LAST` or `V4L2_EXPOSURE_COUNT` or whatever, I would\nhave used that, but it doesn't appear to be a thing.\n\n`std::set<v4l2_exposure_auto_type>` is an option, but I would avoid it if possible,\nhowever maybe that will be it...\n\nAny suggestions?\n\n\n> \n> \n> > +\t> availableExposureModes_;\n> > +\n> >  private:\n> >  \tbool generateId();\n> >\n> > @@ -725,25 +733,25 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n> >  \t\t * ExposureTimeModeManual = { V4L2_EXPOSURE_MANUAL,\n> >  \t\t *\t\t\t      V4L2_EXPOSURE_SHUTTER_PRIORITY }\n> >  \t\t */\n> > -\t\tstd::array<int32_t, 2> values{};\n> > -\n> > -\t\tauto it = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> > -\t\t\t[&](const ControlValue &val) {\n> > -\t\t\t\treturn (val.get<int32_t>() == V4L2_EXPOSURE_APERTURE_PRIORITY ||\n> > -\t\t\t\t\tval.get<int32_t>() == V4L2_EXPOSURE_AUTO) ? true : false;\n> > -\t\t\t});\n> > -\t\tif (it != v4l2Values.end())\n> > -\t\t\tvalues.back() = static_cast<int32_t>(controls::ExposureTimeModeAuto);\n> > -\n> > -\t\tit = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> > -\t\t\t[&](const ControlValue &val) {\n> > -\t\t\t\treturn (val.get<int32_t>() == V4L2_EXPOSURE_SHUTTER_PRIORITY ||\n> > -\t\t\t\t\tval.get<int32_t>() == V4L2_EXPOSURE_MANUAL) ? true : false;\n> > -\t\t\t});\n> > -\t\tif (it != v4l2Values.end())\n> > -\t\t\tvalues.back() = static_cast<int32_t>(controls::ExposureTimeModeManual);\n> > -\n> > -\t\tinfo = ControlInfo{Span<int32_t>{values}, values[0]};\n> > +\t\tfor (const ControlValue &value : v4l2Values) {\n> > +\t\t\tauto x = value.get<int32_t>();\n> > +\t\t\tif (0 <= x && static_cast<size_t>(x) < availableExposureModes_.size())\n> \n> v4l2Values comes from kernel and can only be a value from enum\n> v4l2_exposure_auto_type right ? The above check shouldn't be needed,\n> at least the < 0 part..\n\nI suppose you're right, but I still prefer to have bounds checking.\n\n\n> \n> > +\t\t\t\tavailableExposureModes_[x] = true;\n> > +\t\t}\n> > +\n> > +\t\tstd::array<ControlValue, 2> values;\n> > +\t\tstd::size_t count = 0;\n> > +\n> > +\t\tif (availableExposureModes_[V4L2_EXPOSURE_AUTO] || availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n> \n> Break this lines as suggested by Kieran\n\nIn my understanding the suggestion was not to break the line. But regardless, I think\nI would like to send a slightly different new version (which will not have these\nlong lines). Since sending this I have come to the conclusion that the\nlibcamera-control -> v4l2-control mapping should be in a single place.\n\n\nRegards,\nBarnabás Pőcze\n\n> \n> Thanks\n>   j\n> \n> > +\t\t\tvalues[count++] = controls::ExposureTimeModeAuto;\n> > +\n> > +\t\tif (availableExposureModes_[V4L2_EXPOSURE_MANUAL] || availableExposureModes_[V4L2_EXPOSURE_SHUTTER_PRIORITY])\n> > +\t\t\tvalues[count++] = controls::ExposureTimeModeManual;\n> > +\n> > +\t\tif (count == 0)\n> > +\t\t\treturn;\n> > +\n> > +\t\tinfo = ControlInfo{ Span<const ControlValue>{ values.data(), count }, values[0] };\n> >  \t\tbreak;\n> >  \t}\n> >  \tcase V4L2_CID_EXPOSURE_ABSOLUTE:\n> > --\n> > 2.48.1\n> >\n> >\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 5701AC3259\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 28 Feb 2025 11:45:47 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6BDD468773;\n\tFri, 28 Feb 2025 12:45:46 +0100 (CET)","from mail-4316.protonmail.ch (mail-4316.protonmail.ch\n\t[185.70.43.16])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 170C461853\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 28 Feb 2025 12:45:44 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=protonmail.com header.i=@protonmail.com\n\theader.b=\"Z86Fw+ZD\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;\n\ts=protonmail3; t=1740743143; x=1741002343;\n\tbh=91fKQ9o9SYDLG9YJiPARW0UKpqAEb3UMqvXS6laiJLY=;\n\th=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References:\n\tFeedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:\n\tMessage-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post;\n\tb=Z86Fw+ZDQfjVI/apho+GBP13x7SRVOO9zusiXjRp0Dyp9QGEP4JmGMh4wSIDs8HZk\n\tM1zTehcgTIhkVdZx0nBkaH3a42zywhblwTm4FpBGbaWdzphCDoymasw36IAMX5GfU0\n\tBJ95zw6IeUntt/uL+hrQwNDroFCfG3Ei+PeM0TYuWiF1oA22fQ5i92PWrZRTcsrn6B\n\tve6ZxfamFBzm6UCHUDqKGLZbYJtQJaT2viFkugU4FnOBd3kqLJuyLYxwiG8fUVwhN9\n\t5OGJP7QhAZzrDKIZ63NWktL11CZd109h+ZkhPnId4BGUkckgkwVydZd1vJ6JPqy82B\n\tAzXXy11iqivNQ==","Date":"Fri, 28 Feb 2025 11:45:38 +0000","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","Message-ID":"<Y2kGCVptH46TrGA8LEIp_KiPQyJpiQMNK64EyKy1c8GL6YbNiunoB_bnCNj3GjhI2j7O7UhNwJfGRdJuzY3xKlE3Z6-Ic_vFZlN4nzxzcEw=@protonmail.com>","In-Reply-To":"<lo7xng6m3w4ibmkcwcmtfuklo2exyucqbz7ovw7luxh3apxu25@3ehq2mnxde3x>","References":"<20250217185327.306509-1-pobrn@protonmail.com>\n\t<20250217185327.306509-2-pobrn@protonmail.com>\n\t<lo7xng6m3w4ibmkcwcmtfuklo2exyucqbz7ovw7luxh3apxu25@3ehq2mnxde3x>","Feedback-ID":"20568564:user:proton","X-Pm-Message-ID":"6752f3b0a50d9655ccc9ad0d238d37747ea2d410","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"quoted-printable","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":33513,"web_url":"https://patchwork.libcamera.org/comment/33513/","msgid":"<jkgbtytsvureje6yavqy7qrt4vtrgbflswak7inxrx7dbqanyt@k7vovefybngt>","date":"2025-02-28T12:00:00","subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Barnabás\n\nOn Fri, Feb 28, 2025 at 11:45:38AM +0000, Barnabás Pőcze wrote:\n> Hi\n>\n>\n> 2025. február 28., péntek 12:06 keltezéssel, Jacopo Mondi <jacopo.mondi@ideasonboard.com> írta:\n>\n> > Hi Barnabás\n> >\n> > On Mon, Feb 17, 2025 at 06:53:34PM +0000, Barnabás Pőcze wrote:\n> > > `ControlInfo(Span<const int32_t>{...})` calls the incorrect constructor\n> > > of `ControlInfo`. The intended constructor to be called is\n> > > `ControlInfo(Span<const ControlValue>, ...)` however that is not called\n> > > because a span of `const int32_t` is passed. Instead, the constructor\n> > > `ControlInfo(const ControlValue &min, const ControlValue &max, ...)`\n> > > will be called.\n> > >\n> > > Furthermore, since `values.back()` is used, only the last element of\n> > > the array is actually populated.\n> > >\n> > > To fix this, convert the array to contain `ControlValue` objects\n> > > and use a separate variable to keep track of which element is to\n> > > be populated next.\n> > >\n> > > The available modes are saved for later so that the appropriate mode\n> > > can be selected when the control is set.\n> > >\n> > > Fixes: bad8d591f8acfa (\"libcamera: uvcvideo: Register ExposureTimeMode control\")\n> > > Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n> > > ---\n> > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 46 ++++++++++++--------\n> > >  1 file changed, 27 insertions(+), 19 deletions(-)\n> > >\n> > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > index dedcac89b..1f604b91e 100644\n> > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > @@ -6,6 +6,7 @@\n> > >   */\n> > >\n> > >  #include <algorithm>\n> > > +#include <bitset>\n> > >  #include <cmath>\n> > >  #include <fstream>\n> > >  #include <map>\n> > > @@ -58,6 +59,13 @@ public:\n> > >  \tStream stream_;\n> > >  \tstd::map<PixelFormat, std::vector<SizeRange>> formats_;\n> > >\n> > > +\tstd::bitset<\n> > > +\t\tstd::max(V4L2_EXPOSURE_AUTO,\n> > > +\t\tstd::max(V4L2_EXPOSURE_MANUAL,\n> > > +\t\tstd::max(V4L2_EXPOSURE_APERTURE_PRIORITY,\n> > > +\t\t\t V4L2_EXPOSURE_SHUTTER_PRIORITY))) + 1\n> >\n> > The enum v4l2_exposure_auto_type definition is part of the linux\n> > kernel ABI, and I don't expect them to change. Maybe new modes might\n> > be added, but in that case you would have to change the above anyway.\n>\n> I think the intent here is very clear. Alternatives I can think of: `std::bitset<4>`,\n> or `std::bitset<V4L2_EXPOSURE_APERTURE_PRIORITY + 1>` are all less clear in my opinion.\n>\n> If there was a `V4L2_EXPOSURE_LAST` or `V4L2_EXPOSURE_COUNT` or whatever, I would\n> have used that, but it doesn't appear to be a thing.\n\nThat's true as well. I don't know how bitsets are actually\nrepresented, but if they're stored in an integer anyway I would have\njust bitset<32>\n\nAnyway, it's a minor, up to you\n\n>\n> `std::set<v4l2_exposure_auto_type>` is an option, but I would avoid it if possible,\n> however maybe that will be it...\n>\n> Any suggestions?\n>\n>\n> >\n> >\n> > > +\t> availableExposureModes_;\n> > > +\n> > >  private:\n> > >  \tbool generateId();\n> > >\n> > > @@ -725,25 +733,25 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n> > >  \t\t * ExposureTimeModeManual = { V4L2_EXPOSURE_MANUAL,\n> > >  \t\t *\t\t\t      V4L2_EXPOSURE_SHUTTER_PRIORITY }\n> > >  \t\t */\n> > > -\t\tstd::array<int32_t, 2> values{};\n> > > -\n> > > -\t\tauto it = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> > > -\t\t\t[&](const ControlValue &val) {\n> > > -\t\t\t\treturn (val.get<int32_t>() == V4L2_EXPOSURE_APERTURE_PRIORITY ||\n> > > -\t\t\t\t\tval.get<int32_t>() == V4L2_EXPOSURE_AUTO) ? true : false;\n> > > -\t\t\t});\n> > > -\t\tif (it != v4l2Values.end())\n> > > -\t\t\tvalues.back() = static_cast<int32_t>(controls::ExposureTimeModeAuto);\n> > > -\n> > > -\t\tit = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> > > -\t\t\t[&](const ControlValue &val) {\n> > > -\t\t\t\treturn (val.get<int32_t>() == V4L2_EXPOSURE_SHUTTER_PRIORITY ||\n> > > -\t\t\t\t\tval.get<int32_t>() == V4L2_EXPOSURE_MANUAL) ? true : false;\n> > > -\t\t\t});\n> > > -\t\tif (it != v4l2Values.end())\n> > > -\t\t\tvalues.back() = static_cast<int32_t>(controls::ExposureTimeModeManual);\n> > > -\n> > > -\t\tinfo = ControlInfo{Span<int32_t>{values}, values[0]};\n> > > +\t\tfor (const ControlValue &value : v4l2Values) {\n> > > +\t\t\tauto x = value.get<int32_t>();\n> > > +\t\t\tif (0 <= x && static_cast<size_t>(x) < availableExposureModes_.size())\n> >\n> > v4l2Values comes from kernel and can only be a value from enum\n> > v4l2_exposure_auto_type right ? The above check shouldn't be needed,\n> > at least the < 0 part..\n>\n> I suppose you're right, but I still prefer to have bounds checking.\n>\n\nI understand.\n\nWhen I see checks for things that are apparently not needed I always\nend up asking what am I missing and in what case, using this example,\nx might be less than 0 (because it's clear it can't).\n\nHowever, defensive programming is surely welcome at the expense of some\nfuture me asking \"why the heck can x be < 0 ?\"\n>\n> >\n> > > +\t\t\t\tavailableExposureModes_[x] = true;\n> > > +\t\t}\n> > > +\n> > > +\t\tstd::array<ControlValue, 2> values;\n> > > +\t\tstd::size_t count = 0;\n> > > +\n> > > +\t\tif (availableExposureModes_[V4L2_EXPOSURE_AUTO] || availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n> >\n> > Break this lines as suggested by Kieran\n>\n> In my understanding the suggestion was not to break the line. But regardless, I think\n\nWasn't it ?\n\n-------------------------------------------------------------------------------\nThis hits some long lines. Might be tempting to format this as:\n\n\n                if (availableExposureModes_[V4L2_EXPOSURE_AUTO] ||\n                    availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n                        values[count++] = controls::ExposureTimeModeAuto;\n-------------------------------------------------------------------------------\n\n> I would like to send a slightly different new version (which will not have these\n> long lines). Since sending this I have come to the conclusion that the\n> libcamera-control -> v4l2-control mapping should be in a single place.\n\nYup, no problems\n\n>\n>\n> Regards,\n> Barnabás Pőcze\n>\n> >\n> > Thanks\n> >   j\n> >\n> > > +\t\t\tvalues[count++] = controls::ExposureTimeModeAuto;\n> > > +\n> > > +\t\tif (availableExposureModes_[V4L2_EXPOSURE_MANUAL] || availableExposureModes_[V4L2_EXPOSURE_SHUTTER_PRIORITY])\n> > > +\t\t\tvalues[count++] = controls::ExposureTimeModeManual;\n> > > +\n> > > +\t\tif (count == 0)\n> > > +\t\t\treturn;\n> > > +\n> > > +\t\tinfo = ControlInfo{ Span<const ControlValue>{ values.data(), count }, values[0] };\n> > >  \t\tbreak;\n> > >  \t}\n> > >  \tcase V4L2_CID_EXPOSURE_ABSOLUTE:\n> > > --\n> > > 2.48.1\n> > >\n> > >\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 9C1CCBE080\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 28 Feb 2025 12:00:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A6DDA68774;\n\tFri, 28 Feb 2025 13:00:04 +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 ABFAB61853\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 28 Feb 2025 13:00:03 +0100 (CET)","from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 23242250;\n\tFri, 28 Feb 2025 12:58:34 +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=\"r+JGOvPP\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1740743914;\n\tbh=h1pM9P2W1rgTzx1heBMen4GjsWIRkOvx6IJ0Q/c7DRA=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=r+JGOvPP7+DKSQfObgubK1ug5oglisFq8eGLCDgi4NhqzHC6OQe7qcz6Ioac0i3U5\n\t9hhm0z5F9F1focNMZrP2RGkK5ifthwAkKR0l8jtAKHsZCXj/ezxAiFr47cq+BVJc6T\n\taUP3yjPSUffxPWiB1fR0YkZ5vvShQBFmDykJG+nw=","Date":"Fri, 28 Feb 2025 13:00:00 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","Message-ID":"<jkgbtytsvureje6yavqy7qrt4vtrgbflswak7inxrx7dbqanyt@k7vovefybngt>","References":"<20250217185327.306509-1-pobrn@protonmail.com>\n\t<20250217185327.306509-2-pobrn@protonmail.com>\n\t<lo7xng6m3w4ibmkcwcmtfuklo2exyucqbz7ovw7luxh3apxu25@3ehq2mnxde3x>\n\t<Y2kGCVptH46TrGA8LEIp_KiPQyJpiQMNK64EyKy1c8GL6YbNiunoB_bnCNj3GjhI2j7O7UhNwJfGRdJuzY3xKlE3Z6-Ic_vFZlN4nzxzcEw=@protonmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<Y2kGCVptH46TrGA8LEIp_KiPQyJpiQMNK64EyKy1c8GL6YbNiunoB_bnCNj3GjhI2j7O7UhNwJfGRdJuzY3xKlE3Z6-Ic_vFZlN4nzxzcEw=@protonmail.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":33532,"web_url":"https://patchwork.libcamera.org/comment/33532/","msgid":"<OFWUdZXdJwy5SqKGTekAiPGCRqPqhXF13XkPUTbod5yYcoMHakmNU5Ku5USFYfjAKG0uics6kov3Pt0R-iggTnu2S6AqYGv69v9-BzPmyy4=@protonmail.com>","date":"2025-03-03T10:18:20","subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","submitter":{"id":133,"url":"https://patchwork.libcamera.org/api/people/133/","name":"Pőcze Barnabás","email":"pobrn@protonmail.com"},"content":"Hi\n\n\n2025. február 27., csütörtök 22:30 keltezéssel, Kieran Bingham <kieran.bingham@ideasonboard.com> írta:\n\n> Hi Barnabas,\n> \n> Thanks for the fix ups - I see the compilers are all now happy with this\n> series, so the gcc-9 issue is gone.\n> \n> \n> Quoting Barnabás Pőcze (2025-02-17 18:53:34)\n> > `ControlInfo(Span<const int32_t>{...})` calls the incorrect constructor\n> > of `ControlInfo`. The intended constructor to be called is\n> > `ControlInfo(Span<const ControlValue>, ...)` however that is not called\n> > because a span of `const int32_t` is passed. Instead, the constructor\n> > `ControlInfo(const ControlValue &min, const ControlValue &max, ...)`\n> > will be called.\n> >\n> > Furthermore, since `values.back()` is used, only the last element of\n> > the array is actually populated.\n> >\n> > To fix this, convert the array to contain `ControlValue` objects\n> > and use a separate variable to keep track of which element is to\n> > be populated next.\n> >\n> > The available modes are saved for later so that the appropriate mode\n> > can be selected when the control is set.\n> >\n> > Fixes: bad8d591f8acfa (\"libcamera: uvcvideo: Register ExposureTimeMode control\")\n> > Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n> > ---\n> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 46 ++++++++++++--------\n> >  1 file changed, 27 insertions(+), 19 deletions(-)\n> >\n> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > index dedcac89b..1f604b91e 100644\n> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > @@ -6,6 +6,7 @@\n> >   */\n> >\n> >  #include <algorithm>\n> > +#include <bitset>\n> >  #include <cmath>\n> >  #include <fstream>\n> >  #include <map>\n> > @@ -58,6 +59,13 @@ public:\n> >         Stream stream_;\n> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;\n> >\n> > +       std::bitset<\n> > +               std::max(V4L2_EXPOSURE_AUTO,\n> > +               std::max(V4L2_EXPOSURE_MANUAL,\n> > +               std::max(V4L2_EXPOSURE_APERTURE_PRIORITY,\n> > +                        V4L2_EXPOSURE_SHUTTER_PRIORITY))) + 1\n> \n> I assume std::max becomes constexpr here (checked, and it does).\n> clangformat wants to indent these, but it does make sense as a list.\n> \n> I wonder if putting them it a local const array and using some constexpr\n> iteration ... but then we may as well put a constexpr helper in to\n> include/libcamera/base/utils.h ....\n> \n> Maybe if we find ourselves doing this again ?\n\nThe C++ standard library already covers this. std::min/max/minmax all support\nstd::initializer_list arguments. But unfortunately the libstdc++ implementation\nbefore GCC10 is not actually constexpr if `_GLIBCXX_DEBUG` is defined. I would\nbe more in favor of dropping GCC9 than introducing a bespoke implementation just\nfor this GCC bug.\n\n\nRegards,\nBarnabás Pőcze\n\n> \n> \n> > +       > availableExposureModes_;\n> > +\n> >  private:\n> >         bool generateId();\n> >\n> > @@ -725,25 +733,25 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n> >                  * ExposureTimeModeManual = { V4L2_EXPOSURE_MANUAL,\n> >                  *                            V4L2_EXPOSURE_SHUTTER_PRIORITY }\n> >                  */\n> > -               std::array<int32_t, 2> values{};\n> > -\n> > -               auto it = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> > -                       [&](const ControlValue &val) {\n> > -                               return (val.get<int32_t>() == V4L2_EXPOSURE_APERTURE_PRIORITY ||\n> > -                                       val.get<int32_t>() == V4L2_EXPOSURE_AUTO) ? true : false;\n> > -                       });\n> > -               if (it != v4l2Values.end())\n> > -                       values.back() = static_cast<int32_t>(controls::ExposureTimeModeAuto);\n> > -\n> > -               it = std::find_if(v4l2Values.begin(), v4l2Values.end(),\n> > -                       [&](const ControlValue &val) {\n> > -                               return (val.get<int32_t>() == V4L2_EXPOSURE_SHUTTER_PRIORITY ||\n> > -                                       val.get<int32_t>() == V4L2_EXPOSURE_MANUAL) ? true : false;\n> > -                       });\n> > -               if (it != v4l2Values.end())\n> > -                       values.back() = static_cast<int32_t>(controls::ExposureTimeModeManual);\n> > -\n> > -               info = ControlInfo{Span<int32_t>{values}, values[0]};\n> > +               for (const ControlValue &value : v4l2Values) {\n> > +                       auto x = value.get<int32_t>();\n> > +                       if (0 <= x && static_cast<size_t>(x) < availableExposureModes_.size())\n> > +                               availableExposureModes_[x] = true;\n> > +               }\n> > +\n> > +               std::array<ControlValue, 2> values;\n> > +               std::size_t count = 0;\n> > +\n> > +               if (availableExposureModes_[V4L2_EXPOSURE_AUTO] || availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n> \n> This hits some long lines. Might be tempting to format this as:\n> \n> \n> \t\tif (availableExposureModes_[V4L2_EXPOSURE_AUTO] ||\n> \t\t    availableExposureModes_[V4L2_EXPOSURE_APERTURE_PRIORITY])\n> \t\t\tvalues[count++] = controls::ExposureTimeModeAuto;\n> \n> But I like this patch for more succinct code.\n> \n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> > +                       values[count++] = controls::ExposureTimeModeAuto;\n> > +\n> > +               if (availableExposureModes_[V4L2_EXPOSURE_MANUAL] || availableExposureModes_[V4L2_EXPOSURE_SHUTTER_PRIORITY])\n> > +                       values[count++] = controls::ExposureTimeModeManual;\n> > +\n> > +               if (count == 0)\n> > +                       return;\n> > +\n> > +               info = ControlInfo{ Span<const ControlValue>{ values.data(), count }, values[0] };\n> >                 break;\n> >         }\n> >         case V4L2_CID_EXPOSURE_ABSOLUTE:\n> > --\n> > 2.48.1\n> >\n> >\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 37188C3263\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Mar 2025 10:18:31 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2B632687DD;\n\tMon,  3 Mar 2025 11:18:30 +0100 (CET)","from mail-40131.protonmail.ch (mail-40131.protonmail.ch\n\t[185.70.40.131])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E4B9268772\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Mar 2025 11:18:27 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=protonmail.com header.i=@protonmail.com\n\theader.b=\"PWK7LByi\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;\n\ts=protonmail3; t=1740997107; x=1741256307;\n\tbh=MtmMD01Bd31R7OjZrTSucrqnhiYR5uvZWXCQzH8XdkA=;\n\th=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References:\n\tFeedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:\n\tMessage-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post;\n\tb=PWK7LByieV9L+gyn+I2+dxtcPKe59hy5y1MClaVy2Ay0obA2JSEpx30wfJ0ti80YG\n\tstAiY9aAQdhsQA2zTrj5JUCeZ5PrhWou9X0hESKm4ThBaUUz4bV5+l31N58WkpczfL\n\tueo3rNsLGinzJwRT3KDAHT0NuFdxhbVI/vWHgmlTYsGTW2MLtsnu/sYM2LwlX60q8P\n\tq+0XJIzxETzv2XtTN6tAfozlVKwnwNLgOEv1T2vM+uzpECPgX4LyE9sTnYrklB+UtN\n\tuBWWYUAmMqQVQh3vPTpiDexJr5PqstyKPC/Fi6x02rtZ6hqbgRyrpMFzjN4IOWhZvq\n\t3n8Pcxt2raMXw==","Date":"Mon, 03 Mar 2025 10:18:20 +0000","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2 1/2] libcamera: pipeline: uvcvideo: Fix\n\t`ExposureTimeMode` control setup","Message-ID":"<OFWUdZXdJwy5SqKGTekAiPGCRqPqhXF13XkPUTbod5yYcoMHakmNU5Ku5USFYfjAKG0uics6kov3Pt0R-iggTnu2S6AqYGv69v9-BzPmyy4=@protonmail.com>","In-Reply-To":"<174069185836.31628.9546419944108852400@ping.linuxembedded.co.uk>","References":"<20250217185327.306509-1-pobrn@protonmail.com>\n\t<20250217185327.306509-2-pobrn@protonmail.com>\n\t<174069185836.31628.9546419944108852400@ping.linuxembedded.co.uk>","Feedback-ID":"20568564:user:proton","X-Pm-Message-ID":"bba86b4eaf59a3f843c9e4aa2502ceffda5ac1be","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"quoted-printable","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>"}}]