[{"id":22749,"web_url":"https://patchwork.libcamera.org/comment/22749/","msgid":"<Yl8Ftg718idFYxNs@pendragon.ideasonboard.com>","date":"2022-04-19T20:46:18","subject":"Re: [libcamera-devel] [PATCH v3 3/4] apply explicit fixed-sized\n\tSpan type casts","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Christian,\n\nThank you for the patch.\n\nOn Fri, Apr 08, 2022 at 02:42:30AM +0100, Christian Rauch via libcamera-devel wrote:\n> The change of types of some Controls from variable- to fixed-sized requires\n> explicit casting of FrameDurationLimits, ColourGains and SensorBlackLevels.\n> \n> Signed-off-by: Christian Rauch <Rauch.Christian@gmx.de>\n> ---\n>  src/ipa/raspberrypi/raspberrypi.cpp            | 18 +++++++++---------\n>  .../pipeline/raspberrypi/raspberrypi.cpp       |  2 +-\n>  src/qcam/dng_writer.cpp                        |  6 +++---\n>  3 files changed, 13 insertions(+), 13 deletions(-)\n> \n> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> index 89767a9d..5a5cdf66 100644\n> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> @@ -500,18 +500,18 @@ void IPARPi::reportMetadata()\n> \n>  \tAwbStatus *awbStatus = rpiMetadata_.GetLocked<AwbStatus>(\"awb.status\");\n>  \tif (awbStatus) {\n> -\t\tlibcameraMetadata_.set(controls::ColourGains, { static_cast<float>(awbStatus->gain_r),\n> -\t\t\t\t\t\t\t\tstatic_cast<float>(awbStatus->gain_b) });\n> +\t\tlibcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({ static_cast<float>(awbStatus->gain_r),\n> +\t\t\t\t\t\t\t\t\t\t     static_cast<float>(awbStatus->gain_b) }));\n\nThose lines are too long. I'm bothered here, as I think it's very nice\nto use fixed-extent spans to catch errors at compilation time, but the\ncast is ugly :-( This is caused by the explicit constructor for\nfixed-extent spans, which we can't change if we want to remain\ncompatible with std::span.\n\nI was also wondering it we could drop the static_cast<float> to\ncompensate for the additional explicit constructor, but that generates\nother errors:\n\n../../src/ipa/raspberrypi/raspberrypi.cpp:505:72: error: non-constant-expression cannot be narrowed from type 'double' to 'libcamera::Span<const float, 2>::element_type' (aka 'const float') in initializer list [-Wc++11-narrowing]\n                libcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({ awbStatus->gain_r,\n                                                                                     ^~~~~~~~~~~~~~~~~\n../../src/ipa/raspberrypi/raspberrypi.cpp:505:72: note: insert an explicit cast to silence this issue\n                libcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({ awbStatus->gain_r,\n                                                                                     ^~~~~~~~~~~~~~~~~\n                                                                                     static_cast<element_type>( )\n../../src/ipa/raspberrypi/raspberrypi.cpp:506:16: error: non-constant-expression cannot be narrowed from type 'double' to 'libcamera::Span<const float, 2>::element_type' (aka 'const float') in initializer list [-Wc++11-narrowing]\n                                                                                     awbStatus->gain_b }));\n                                                                                     ^~~~~~~~~~~~~~~~~\n../../src/ipa/raspberrypi/raspberrypi.cpp:506:16: note: insert an explicit cast to silence this issue\n                                                                                     awbStatus->gain_b }));\n                                                                                     ^~~~~~~~~~~~~~~~~\n                                                                                     static_cast<element_type>( )\n2 errors generated.\n\nI suppose stars don't always align.\n\nWith proper line wraps, such as\n\n\t\tlibcameraMetadata_.set(controls::ColourGains,\n\t\t\t\t       Span<const float, 2>({ static_cast<float>(awbStatus->gain_r),\n\t\t\t\t\t\t\t      static_cast<float>(awbStatus->gain_b) }));\n\nor maybe\n\n\t\tlibcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({\n\t\t\t\t       static_cast<float>(awbStatus->gain_r),\n\t\t\t\t       static_cast<float>(awbStatus->gain_b) }));\n\nI'm OK with this patch. I'd like to hear from others though. Bonus\npoints if someone can find a nicer way to express all this. We could,\nfor instance, add new ControlList::set() overloads specialized for\nspans.\n\n>  \t\tlibcameraMetadata_.set(controls::ColourTemperature, awbStatus->temperature_K);\n>  \t}\n> \n>  \tBlackLevelStatus *blackLevelStatus = rpiMetadata_.GetLocked<BlackLevelStatus>(\"black_level.status\");\n>  \tif (blackLevelStatus)\n>  \t\tlibcameraMetadata_.set(controls::SensorBlackLevels,\n> -\t\t\t\t       { static_cast<int32_t>(blackLevelStatus->black_level_r),\n> -\t\t\t\t\t static_cast<int32_t>(blackLevelStatus->black_level_g),\n> -\t\t\t\t\t static_cast<int32_t>(blackLevelStatus->black_level_g),\n> -\t\t\t\t\t static_cast<int32_t>(blackLevelStatus->black_level_b) });\n> +\t\t\t\t       Span<const int32_t, 4>({ static_cast<int32_t>(blackLevelStatus->black_level_r),\n> +\t\t\t\t\t\t\t\tstatic_cast<int32_t>(blackLevelStatus->black_level_g),\n> +\t\t\t\t\t\t\t\tstatic_cast<int32_t>(blackLevelStatus->black_level_g),\n> +\t\t\t\t\t\t\t\tstatic_cast<int32_t>(blackLevelStatus->black_level_b) }));\n> \n>  \tFocusStatus *focusStatus = rpiMetadata_.GetLocked<FocusStatus>(\"focus.status\");\n>  \tif (focusStatus && focusStatus->num == 12) {\n> @@ -816,7 +816,7 @@ void IPARPi::queueRequest(const ControlList &controls)\n>  \t\t\tif (gains[0] != 0.0f && gains[1] != 0.0f)\n>  \t\t\t\t/* A gain of 0.0f will switch back to auto mode. */\n>  \t\t\t\tlibcameraMetadata_.set(controls::ColourGains,\n> -\t\t\t\t\t\t       { gains[0], gains[1] });\n> +\t\t\t\t\t\t       Span<const float, 2>({ gains[0], gains[1] }));\n>  \t\t\tbreak;\n>  \t\t}\n> \n> @@ -1100,8 +1100,8 @@ void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDur\n> \n>  \t/* Return the validated limits via metadata. */\n>  \tlibcameraMetadata_.set(controls::FrameDurationLimits,\n> -\t\t\t       { static_cast<int64_t>(minFrameDuration_.get<std::micro>()),\n> -\t\t\t\t static_cast<int64_t>(maxFrameDuration_.get<std::micro>()) });\n> +\t\t\t       Span<const int64_t, 2>({ static_cast<int64_t>(minFrameDuration_.get<std::micro>()),\n> +\t\t\t\t\t\t\tstatic_cast<int64_t>(maxFrameDuration_.get<std::micro>()) }));\n> \n>  \t/*\n>  \t * Calculate the maximum exposure time possible for the AGC to use.\n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index d6148724..0fa294d4 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -1696,7 +1696,7 @@ void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList &\n>  \t * V4L2_CID_NOTIFY_GAINS control (which means notifyGainsUnity_ is set).\n>  \t */\n>  \tif (notifyGainsUnity_ && controls.contains(libcamera::controls::ColourGains)) {\n> -\t\tlibcamera::Span<const float> colourGains = controls.get(libcamera::controls::ColourGains);\n> +\t\tlibcamera::Span<const float, 2> colourGains = controls.get(libcamera::controls::ColourGains);\n>  \t\t/* The control wants linear gains in the order B, Gb, Gr, R. */\n>  \t\tControlList ctrls(sensor_->controls());\n>  \t\tstd::array<int32_t, 4> gains{\n> diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp\n> index 34c8df5a..2fb527d8 100644\n> --- a/src/qcam/dng_writer.cpp\n> +++ b/src/qcam/dng_writer.cpp\n> @@ -438,7 +438,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,\n>  \tconst double eps = 1e-2;\n> \n>  \tif (metadata.contains(controls::ColourGains)) {\n> -\t\tSpan<const float> const &colourGains = metadata.get(controls::ColourGains);\n> +\t\tSpan<const float, 2> const &colourGains = metadata.get(controls::ColourGains);\n>  \t\tif (colourGains[0] > eps && colourGains[1] > eps) {\n>  \t\t\twbGain = Matrix3d::diag(colourGains[0], 1, colourGains[1]);\n>  \t\t\tneutral[0] = 1.0 / colourGains[0]; /* red */\n> @@ -446,7 +446,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,\n>  \t\t}\n>  \t}\n>  \tif (metadata.contains(controls::ColourCorrectionMatrix)) {\n> -\t\tSpan<const float> const &coeffs = metadata.get(controls::ColourCorrectionMatrix);\n> +\t\tSpan<const float, 9> const &coeffs = metadata.get(controls::ColourCorrectionMatrix);\n>  \t\tMatrix3d ccmSupplied(coeffs);\n>  \t\tif (ccmSupplied.determinant() > eps)\n>  \t\t\tccm = ccmSupplied;\n> @@ -515,7 +515,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,\n>  \tuint32_t whiteLevel = (1 << info->bitsPerSample) - 1;\n> \n>  \tif (metadata.contains(controls::SensorBlackLevels)) {\n> -\t\tSpan<const int32_t> levels = metadata.get(controls::SensorBlackLevels);\n> +\t\tSpan<const int32_t, 4> levels = metadata.get(controls::SensorBlackLevels);\n> \n>  \t\t/*\n>  \t\t * The black levels control is specified in R, Gr, Gb, B order.","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 7747FC3256\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 19 Apr 2022 20:46:19 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4382165644;\n\tTue, 19 Apr 2022 22:46:19 +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 003F4604B2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 Apr 2022 22:46:17 +0200 (CEST)","from pendragon.ideasonboard.com (85-76-5-145-nat.elisa-mobile.fi\n\t[85.76.5.145])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 7661125B;\n\tTue, 19 Apr 2022 22:46:17 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1650401179;\n\tbh=k9SaEqXkP2hNcV6x1cz1B75y3FC2SJ7sl2bjHxpsWUE=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=Eg7BrEIUiVJilo0ojltt0i6L0zGPV6FEuIYVqCavjAERYWa00PohyINRUmvHBHgeq\n\t0kqp1itsTOoPF0toGN6CyX52zUnvocJK+TWqW/7G9mk6nruhBz6vfgfL90p6BvpkG/\n\tBf1jBRYKEhKLuBCl4u244BVNx34IyzLSz+9I7oVno1Nd235I1WZpzbOcoIoYQI06+j\n\tTU2SZAGj12jthL82j9fppSPc7vdNE5fv84juaASK2U/bHbaxhhohML6gJ1tMRN1Ghs\n\t+vq25PCGJYdOM86ZfzJ/+ldCLSljx8raEI0uS1KD+CicXdx2qmJDX/Upxm8kCkydcp\n\tn4/F1yIR5oU7w==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1650401177;\n\tbh=k9SaEqXkP2hNcV6x1cz1B75y3FC2SJ7sl2bjHxpsWUE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=We8bQ26396rHxtSahhqYToATHiaenbQCLv5EVg12NiXXVI2lmT+3ELDPGPg58N2Kf\n\thYk+KLBOdpU/LASURilK6kK4G12UWf4ybWedbhG9dgVfpFp7IpW799W8BoF6KVsg0G\n\tdQNMt1l30vLwHnsJQLfBvZRALLxYakalnkCGivtY="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"We8bQ263\"; dkim-atps=neutral","Date":"Tue, 19 Apr 2022 23:46:18 +0300","To":"Christian Rauch <Rauch.Christian@gmx.de>","Message-ID":"<Yl8Ftg718idFYxNs@pendragon.ideasonboard.com>","References":"<20220408014231.231083-1-Rauch.Christian@gmx.de>\n\t<20220408014231.231083-4-Rauch.Christian@gmx.de>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220408014231.231083-4-Rauch.Christian@gmx.de>","Subject":"Re: [libcamera-devel] [PATCH v3 3/4] apply explicit fixed-sized\n\tSpan type casts","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":22753,"web_url":"https://patchwork.libcamera.org/comment/22753/","msgid":"<cefcf9a5-ff6e-f337-a6c8-0443340fdc04@gmx.de>","date":"2022-04-19T22:47:54","subject":"Re: [libcamera-devel] [PATCH v3 3/4] apply explicit fixed-sized\n\tSpan type casts","submitter":{"id":111,"url":"https://patchwork.libcamera.org/api/people/111/","name":"Christian Rauch","email":"Rauch.Christian@gmx.de"},"content":"Hi Laurent,\n\nIn short: We can skip a lot of casts, if those values would already be\nin the \"target type\".\n\nAm 19.04.22 um 21:46 schrieb Laurent Pinchart:\n> Hi Christian,\n>\n> Thank you for the patch.\n>\n> On Fri, Apr 08, 2022 at 02:42:30AM +0100, Christian Rauch via libcamera-devel wrote:\n>> The change of types of some Controls from variable- to fixed-sized requires\n>> explicit casting of FrameDurationLimits, ColourGains and SensorBlackLevels.\n>>\n>> Signed-off-by: Christian Rauch <Rauch.Christian@gmx.de>\n>> ---\n>>  src/ipa/raspberrypi/raspberrypi.cpp            | 18 +++++++++---------\n>>  .../pipeline/raspberrypi/raspberrypi.cpp       |  2 +-\n>>  src/qcam/dng_writer.cpp                        |  6 +++---\n>>  3 files changed, 13 insertions(+), 13 deletions(-)\n>>\n>> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n>> index 89767a9d..5a5cdf66 100644\n>> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n>> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n>> @@ -500,18 +500,18 @@ void IPARPi::reportMetadata()\n>>\n>>  \tAwbStatus *awbStatus = rpiMetadata_.GetLocked<AwbStatus>(\"awb.status\");\n>>  \tif (awbStatus) {\n>> -\t\tlibcameraMetadata_.set(controls::ColourGains, { static_cast<float>(awbStatus->gain_r),\n>> -\t\t\t\t\t\t\t\tstatic_cast<float>(awbStatus->gain_b) });\n>> +\t\tlibcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({ static_cast<float>(awbStatus->gain_r),\n>> +\t\t\t\t\t\t\t\t\t\t     static_cast<float>(awbStatus->gain_b) }));\n>\n> Those lines are too long. I'm bothered here, as I think it's very nice\n> to use fixed-extent spans to catch errors at compilation time, but the\n> cast is ugly :-( This is caused by the explicit constructor for\n> fixed-extent spans, which we can't change if we want to remain\n> compatible with std::span.\n>\n> I was also wondering it we could drop the static_cast<float> to\n> compensate for the additional explicit constructor, but that generates\n> other errors:\n>\n> ../../src/ipa/raspberrypi/raspberrypi.cpp:505:72: error: non-constant-expression cannot be narrowed from type 'double' to 'libcamera::Span<const float, 2>::element_type' (aka 'const float') in initializer list [-Wc++11-narrowing]\n>                 libcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({ awbStatus->gain_r,\n>                                                                                      ^~~~~~~~~~~~~~~~~\n> ../../src/ipa/raspberrypi/raspberrypi.cpp:505:72: note: insert an explicit cast to silence this issue\n>                 libcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({ awbStatus->gain_r,\n>                                                                                      ^~~~~~~~~~~~~~~~~\n>                                                                                      static_cast<element_type>( )\n> ../../src/ipa/raspberrypi/raspberrypi.cpp:506:16: error: non-constant-expression cannot be narrowed from type 'double' to 'libcamera::Span<const float, 2>::element_type' (aka 'const float') in initializer list [-Wc++11-narrowing]\n>                                                                                      awbStatus->gain_b }));\n>                                                                                      ^~~~~~~~~~~~~~~~~\n> ../../src/ipa/raspberrypi/raspberrypi.cpp:506:16: note: insert an explicit cast to silence this issue\n>                                                                                      awbStatus->gain_b }));\n>                                                                                      ^~~~~~~~~~~~~~~~~\n>                                                                                      static_cast<element_type>( )\n> 2 errors generated.\n>\n> I suppose stars don't always align.\n\nThe \"AwbStatus\" stores its values as \"double\". If you either change that\nstruct to \"float\" or the \"ColourGains\" Control to \"double\", then you can\nskip the explicit casts. You still have to call the explicit \"Span\"\nconstructor.\n\nThere are a couple of other places where these \"static_cast\" are required.\n\n>\n> With proper line wraps, such as\n>\n> \t\tlibcameraMetadata_.set(controls::ColourGains,\n> \t\t\t\t       Span<const float, 2>({ static_cast<float>(awbStatus->gain_r),\n> \t\t\t\t\t\t\t      static_cast<float>(awbStatus->gain_b) }));\n>\n> or maybe\n>\n> \t\tlibcameraMetadata_.set(controls::ColourGains, Span<const float, 2>({\n> \t\t\t\t       static_cast<float>(awbStatus->gain_r),\n> \t\t\t\t       static_cast<float>(awbStatus->gain_b) }));\n>\n> I'm OK with this patch. I'd like to hear from others though. Bonus\n> points if someone can find a nicer way to express all this. We could,\n> for instance, add new ControlList::set() overloads specialized for\n> spans.\n>\n>>  \t\tlibcameraMetadata_.set(controls::ColourTemperature, awbStatus->temperature_K);\n>>  \t}\n>>\n>>  \tBlackLevelStatus *blackLevelStatus = rpiMetadata_.GetLocked<BlackLevelStatus>(\"black_level.status\");\n>>  \tif (blackLevelStatus)\n>>  \t\tlibcameraMetadata_.set(controls::SensorBlackLevels,\n>> -\t\t\t\t       { static_cast<int32_t>(blackLevelStatus->black_level_r),\n>> -\t\t\t\t\t static_cast<int32_t>(blackLevelStatus->black_level_g),\n>> -\t\t\t\t\t static_cast<int32_t>(blackLevelStatus->black_level_g),\n>> -\t\t\t\t\t static_cast<int32_t>(blackLevelStatus->black_level_b) });\n>> +\t\t\t\t       Span<const int32_t, 4>({ static_cast<int32_t>(blackLevelStatus->black_level_r),\n>> +\t\t\t\t\t\t\t\tstatic_cast<int32_t>(blackLevelStatus->black_level_g),\n>> +\t\t\t\t\t\t\t\tstatic_cast<int32_t>(blackLevelStatus->black_level_g),\n>> +\t\t\t\t\t\t\t\tstatic_cast<int32_t>(blackLevelStatus->black_level_b) }));\n>>\n>>  \tFocusStatus *focusStatus = rpiMetadata_.GetLocked<FocusStatus>(\"focus.status\");\n>>  \tif (focusStatus && focusStatus->num == 12) {\n>> @@ -816,7 +816,7 @@ void IPARPi::queueRequest(const ControlList &controls)\n>>  \t\t\tif (gains[0] != 0.0f && gains[1] != 0.0f)\n>>  \t\t\t\t/* A gain of 0.0f will switch back to auto mode. */\n>>  \t\t\t\tlibcameraMetadata_.set(controls::ColourGains,\n>> -\t\t\t\t\t\t       { gains[0], gains[1] });\n>> +\t\t\t\t\t\t       Span<const float, 2>({ gains[0], gains[1] }));\n>>  \t\t\tbreak;\n>>  \t\t}\n>>\n>> @@ -1100,8 +1100,8 @@ void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDur\n>>\n>>  \t/* Return the validated limits via metadata. */\n>>  \tlibcameraMetadata_.set(controls::FrameDurationLimits,\n>> -\t\t\t       { static_cast<int64_t>(minFrameDuration_.get<std::micro>()),\n>> -\t\t\t\t static_cast<int64_t>(maxFrameDuration_.get<std::micro>()) });\n>> +\t\t\t       Span<const int64_t, 2>({ static_cast<int64_t>(minFrameDuration_.get<std::micro>()),\n>> +\t\t\t\t\t\t\tstatic_cast<int64_t>(maxFrameDuration_.get<std::micro>()) }));\n>>\n>>  \t/*\n>>  \t * Calculate the maximum exposure time possible for the AGC to use.\n>> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n>> index d6148724..0fa294d4 100644\n>> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n>> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n>> @@ -1696,7 +1696,7 @@ void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList &\n>>  \t * V4L2_CID_NOTIFY_GAINS control (which means notifyGainsUnity_ is set).\n>>  \t */\n>>  \tif (notifyGainsUnity_ && controls.contains(libcamera::controls::ColourGains)) {\n>> -\t\tlibcamera::Span<const float> colourGains = controls.get(libcamera::controls::ColourGains);\n>> +\t\tlibcamera::Span<const float, 2> colourGains = controls.get(libcamera::controls::ColourGains);\n>>  \t\t/* The control wants linear gains in the order B, Gb, Gr, R. */\n>>  \t\tControlList ctrls(sensor_->controls());\n>>  \t\tstd::array<int32_t, 4> gains{\n>> diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp\n>> index 34c8df5a..2fb527d8 100644\n>> --- a/src/qcam/dng_writer.cpp\n>> +++ b/src/qcam/dng_writer.cpp\n>> @@ -438,7 +438,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,\n>>  \tconst double eps = 1e-2;\n>>\n>>  \tif (metadata.contains(controls::ColourGains)) {\n>> -\t\tSpan<const float> const &colourGains = metadata.get(controls::ColourGains);\n>> +\t\tSpan<const float, 2> const &colourGains = metadata.get(controls::ColourGains);\n>>  \t\tif (colourGains[0] > eps && colourGains[1] > eps) {\n>>  \t\t\twbGain = Matrix3d::diag(colourGains[0], 1, colourGains[1]);\n>>  \t\t\tneutral[0] = 1.0 / colourGains[0]; /* red */\n>> @@ -446,7 +446,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,\n>>  \t\t}\n>>  \t}\n>>  \tif (metadata.contains(controls::ColourCorrectionMatrix)) {\n>> -\t\tSpan<const float> const &coeffs = metadata.get(controls::ColourCorrectionMatrix);\n>> +\t\tSpan<const float, 9> const &coeffs = metadata.get(controls::ColourCorrectionMatrix);\n>>  \t\tMatrix3d ccmSupplied(coeffs);\n>>  \t\tif (ccmSupplied.determinant() > eps)\n>>  \t\t\tccm = ccmSupplied;\n>> @@ -515,7 +515,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,\n>>  \tuint32_t whiteLevel = (1 << info->bitsPerSample) - 1;\n>>\n>>  \tif (metadata.contains(controls::SensorBlackLevels)) {\n>> -\t\tSpan<const int32_t> levels = metadata.get(controls::SensorBlackLevels);\n>> +\t\tSpan<const int32_t, 4> levels = metadata.get(controls::SensorBlackLevels);\n>>\n>>  \t\t/*\n>>  \t\t * The black levels control is specified in R, Gr, Gb, B order.\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 6D687C3256\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 19 Apr 2022 22:47:57 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CE18665642;\n\tWed, 20 Apr 2022 00:47:56 +0200 (CEST)","from mout.gmx.net (mout.gmx.net [212.227.15.18])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6E7B36563F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 20 Apr 2022 00:47:55 +0200 (CEST)","from [192.168.1.209] ([92.10.251.63]) by mail.gmx.net (mrgmx004\n\t[212.227.17.190]) with ESMTPSA (Nemesis) id 1MgNh7-1o7jGf3pWh-00hxdV\n\tfor\n\t<libcamera-devel@lists.libcamera.org>; Wed, 20 Apr 2022 00:47:55 +0200"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1650408476;\n\tbh=AUdINt6+UwLYEatC0vm132Q5yy9Xmi2QiKKrqOPPMis=;\n\th=Date:Cc:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=ayXNXT08mstVO0iEA/g6bY+NVeA8wkWuryG7hc9q8dj2s1dhZn3vS/9Ef7tH25JuW\n\tGwWTWqq7rEx+yNTCiHuDoXbY1uOPUh1/0zHhiv9RdMomYKhC8vFHUgC57GG5lvluaq\n\tRzE7dbg+Ii6XA0BGYi+4TtRkis9F8NybnaPlKNk4Y6LDVB3ciobCF3JdXIKoqYOkav\n\tzn9LDzm5CgY6K/dMzF6iSUe9PXc5iGIqZRV+Dt7JZWbAhaZXMEkRHirfZgZv+cdUxt\n\tbBQK+AQjbXZSCUNoLstWC9LWmH9KezvZoIxGVrMti0aBt7Pg3548u12CKjVD/CI/tA\n\tm3HAvHMquAolQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net;\n\ts=badeba3b8450; t=1650408475;\n\tbh=AUdINt6+UwLYEatC0vm132Q5yy9Xmi2QiKKrqOPPMis=;\n\th=X-UI-Sender-Class:Date:Subject:Cc:References:From:In-Reply-To;\n\tb=gibqoPPsGgMarxTOyKkllUeBMwGJewhRXX2mKv76OW7mGvzcnIjsJJ5TOlBCoVZ9V\n\tvktfIMBtW5Nyq//aNjDN4cuSX9G8O7oGQo1D6dgztRQHm/RYNRXc2/kTBZjRmgM4LU\n\tEmTk2dRQQf26YokqnYzgBS4iT4Ti11cSKRxlVz/A="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=gmx.net header.i=@gmx.net\n\theader.b=\"gibqoPPs\"; dkim-atps=neutral","X-UI-Sender-Class":"01bb95c1-4bf8-414a-932a-4f6e2808ef9c","Message-ID":"<cefcf9a5-ff6e-f337-a6c8-0443340fdc04@gmx.de>","Date":"Tue, 19 Apr 2022 23:47:54 +0100","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n\tThunderbird/91.7.0","Content-Language":"en-CA","Cc":"libcamera-devel@lists.libcamera.org","References":"<20220408014231.231083-1-Rauch.Christian@gmx.de>\n\t<20220408014231.231083-4-Rauch.Christian@gmx.de>\n\t<Yl8Ftg718idFYxNs@pendragon.ideasonboard.com>","In-Reply-To":"<Yl8Ftg718idFYxNs@pendragon.ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"quoted-printable","X-Provags-ID":"V03:K1:S2JBlGDtgSomLeROH6WNMNujWv/jQ5TUQHjd/CrZrUbCYSmDrF8\n\tPLbpYddTVBsDXDsQNSIdNeWTqP09/izqp6yitCxUi6J+s5MNH8Ayx/zGtIPCMZyitBVo9I+\n\tfnuxpQ4SwZxAc15tf/KqiplhBDKYDapMMa5KCSiZz7wKO+FKokx+/xpxk4XdM4XeB9X4GZY\n\tMBGXkrhEywrpPRDoyUlAw==","X-Spam-Flag":"NO","X-UI-Out-Filterresults":"notjunk:1; V03:K0:k2Rki+F2FDk=:TXHAgEZbCN3myGRIPOT/Qh\n\tyJKLGioZxEHqoytVoD2tVUNKfYfCU+5HEn2u72HGmbafI14Wz6YYELD6riX3/UtwtaNi05G+c\n\t8jydnC+hJ34zWDvHWSVOitqfgfXjTDbdTZdfTEdZue1gvhm+c5aczmFUnuyB7PxrS/yLG+JCF\n\tgwjoKlcLFZe9tjylhKoeg76qbjyvL+C8WNJOxfx6/G4b6VjfNjYJbRk0mZd+zfVyKUk6uhJ4H\n\tPKdBV/UdNZ59Nn/w8hQHpZI5hz54wB8vFQ2u3pXVehfisRZgzxB6Wa9VIT7wWrmTrDlyUPIHf\n\tK6Imb0A8ZbLB71KQpu21ahJcyK3iCcbF1fxSm84KHbl9x/1waGeEf2ra30D1WTodAAsY3ER1L\n\t4o49fegdy8RhH5c83rqPcMprfuqXuoIIL68L0BHCm3/hC5jRp6QnEBHLzF1Y5TiWpcdBKhyTV\n\teM++WO0djHiMzI4nrN1ugN8rHGarDTeBCLM0GdOCH04B3CsPHtvYPd1lM0n0jycfSVZvq7JNa\n\tNK/jEzkgjA6iMzNIrlx8cyHp5ubiKvYmvQdU/ezNE9GE4VhQPIHEV1FTNVRFS44YDY2B8x7HF\n\tTQraDO8lzTKqL3gqqQC8UB0E0LSDUaMldELHU6pZJEpb7ZOHT2+X/ai7eqxQH2TRmpWutG9jn\n\tW8g2bZ63RkEFFdQWx15sL2W/cWV2Vk02QHdFn3HsnmL5tZ2q1Ewym8Xquhw/TJv6p9T+lB43F\n\t9hJZsMWbCDDEKhX3S8VTu36XO97hqa77Zy2K/FHXPYWEKgeT2YznHpOuhNP4dVtzhabZZETqc\n\tDXoh/6V5por/40IjBNplegRm6joFzvtam2NzIijRTOGYolhgBIemK0sADq+nq7Uv7CoSuj1Zu\n\tmIpRzPRiFVp5wZbwstpt/uA9AYGh/K/UEQAj3Bm1F4FO7c9Sw+gWotJ7HvYuUqN2NfsI2b7hQ\n\taznW59YGbDaBPxFQ6tKxqJjZC0+gXxtGQkJipG99yNNhyJlgXvCP5o4G1/0WTOnA7YBujQBnW\n\tJXE7t/mWl2sw1RtRofX+NxrfQvoQR5FANgVhjPJsTMFDdcZ7C5WaRvLK4hZiADE/SvjfHumvs\n\trw7EQlva9aVNxc=","Subject":"Re: [libcamera-devel] [PATCH v3 3/4] apply explicit fixed-sized\n\tSpan type casts","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Christian Rauch via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Christian Rauch <Rauch.Christian@gmx.de>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]