[{"id":25539,"web_url":"https://patchwork.libcamera.org/comment/25539/","msgid":"<166660807272.2560709.18376612569572892760@Monstersaurus>","date":"2022-10-24T10:41:12","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Nicholas,\n\nThanks for breaking these up - much easier to review, and work out how\nto integrate.\n\nCould I ask you to read https://cbea.ms/git-commit/ please?\n\nThat's not written by us, but it's a close summary of how we like to see\ncommit messages formed for the project.\n\n\n\nQuoting Nicholas Roth via libcamera-devel (2022-10-24 06:55:33)\n> From: Nicholas Roth <nicholas@rothemail.net>\n> \n\nSo for this patch, I would propose a subject line / commit message of:\n\nipa: workaround libcxx duration limitation\n\nA bug in libcxx used by clang version 11.0.2 is prevalent when building\nlibcamera for Android SDK30. This has been fixed and integrated upstream\nwith [0]. As a workaround, directly cast the affected chrono types \n\n\n[0] https://github.com/llvm/llvm-project/commit/efa6d803c624f9251d0ab7881122501bb9d27368\n\n> ---\n>  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n>  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n>  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n>  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n>  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n>  src/ipa/rkisp1/algorithms/agc.cpp          | 22 ++++++++++++++++++----\n>  6 files changed, 60 insertions(+), 17 deletions(-)\n> \n> diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\n> index a1a3c38f..80c551bb 100644\n> --- a/src/ipa/ipu3/algorithms/agc.cpp\n> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n>  \n>         /* Configure the default exposure and gain. */\n>         activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n> -       activeState.agc.exposure = 10ms / configuration.sensor.lineDuration;\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> +       activeState.agc.exposure = ten_millis /\n> +               configuration.sensor.lineDuration.get<std::nano>();\n\nIt's not yet clear to me if it's Duration / Duration that breaks, or\n(explicitly) Chrono / Duration ?\n\nEdit: Reading further I think the below won't work...\n\n\nDo we need the extra casts? Is this possible? :\n\n\t/*\n\t * Default to 10 milliseconds. Avoid use of chrono suffixes due\n\t * to Bug: 156.\n\t *\n\t * \\todo: Bug 156: Use a chrono suffixed duration (10ms) when possible\n\t */\n \tutils::Duration exposure = utils::Duration(10000) / configuration.sensor.lineDuration;\n\tactiveState.agc.exposure = exposure.get<std::nano>();\n\nOr perhaps even does that then allow this directly?:\n\n\tactiveState.agc.exposure = utils::Duration(10000) / configuration.sensor.lineDuration;\n\n\nI'm not sure which part of the bug causes the breakage, so it might be\nthat those are affected too. If so, please try to include a description\nin the commit of precisely what the limitations are of the bug and what\nwe're prevented from doing.\n\n\n\n>         frameCount_ = 0;\n>         return 0;\n> @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n>          *\n>          * Push the shutter time up to the maximum first, and only then\n>          * increase the gain.\n> +        *\n> +        * TODO(Bug 156): Workaround for LLVM bug.\n\nWe use \"\\todo\" for todo's, to match doxygen. Though this component isn't\nparsed by doxygen, but it's useful to be constent.\n\n\t  * \\todo Bug 156: Workaround for LLVM \n\n>          */\n> +       double exposureValueDouble = exposureValue.get<std::nano>();\n> +       utils::Duration shutterTimeRaw(exposureValueDouble / minAnalogueGain_);\n>         utils::Duration shutterTime =\n> -               std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,\n> +               std::clamp<utils::Duration>(shutterTimeRaw,\n>                                             minShutterSpeed_, maxShutterSpeed_);\n> -       double stepGain = std::clamp(exposureValue / shutterTime,\n> +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> +       double stepGain = std::clamp(exposureValueDouble / shutterTimeDouble,\n>                                      minAnalogueGain_, maxAnalogueGain_);\n\nAha, ok so the limiation is that we can't do a Duration / Duration ?\n\n(So my above suggestions are useless, but I'll leave them there as that was\nmy thought process above).\n\n>         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n>                             << shutterTime << \" and \"\n> @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n>  \n>         IPAActiveState &activeState = context.activeState;\n>         /* Update the estimated exposure and gain. */\n> -       activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +       double lineDurationDouble = configuration.sensor.lineDuration.get<std::nano>();\n> +       activeState.agc.exposure = shutterTimeDouble / lineDurationDouble;\n>         activeState.agc.gain = stepGain;\n>  }\n>  \n> diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp\n> index d90ac1de..31a9a1ef 100644\n> --- a/src/ipa/raspberrypi/cam_helper.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr &stats,\n>  \n>  uint32_t CamHelper::exposureLines(const Duration exposure, const Duration lineLength) const\n>  {\n> -       return exposure / lineLength;\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n\nSame minor about the todo styles.\n\n> +       return exposure.get<std::nano>() / lineLength.get<std::nano>();\n>  }\n>  \n>  Duration CamHelper::exposure(uint32_t exposureLines, const Duration lineLength) const\n> @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t> CamHelper::getBlanking(Duration &exposure,\n>          *\n>          * frameLengthMax gets calculated on the smallest line length as we do\n>          * not want to extend that unless absolutely necessary.\n> +        *\n> +        * TODO(Bug 156): Workaround for LLVM bug.\n>          */\n> -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> +       frameLengthMin = minFrameDuration.get<std::nano>() / mode_.minLineLength.get<std::nano>();\n> +       frameLengthMax = maxFrameDuration.get<std::nano>() / mode_.minLineLength.get<std::nano>();\n>  \n>         /*\n>          * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> index ecb845e7..e48f5cf2 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n>  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n>                                         [[maybe_unused]] const Duration lineLength) const\n>  {\n> -       return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) / timePerLine);\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +       double exposureTime = Duration(exposure - 14.26us).get<std::nano>();\n> +       double timePerLineNano = timePerLine.get<std::nano>();\n> +       return std::max<uint32_t>(minExposureLines, exposureTime / timePerLineNano);\n>  }\n>  \n>  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> index bd54a639..720ba788 100644\n> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n>                         Duration actualExposure = deviceStatus.shutterSpeed *\n>                                                   deviceStatus.analogueGain;\n>                         if (actualExposure) {\n> -                               status_.digitalGain = status_.totalExposureValue / actualExposure;\n> +                               /* TODO(Bug 156): Workaround for LLVM bug. */\n> +                               double totalExposureDouble = status_.totalExposureValue.get<std::nano>();\n> +                               double actualExposureDouble = actualExposure.get<std::nano>();\n> +                               status_.digitalGain = totalExposureDouble / actualExposureDouble;\n>                                 LOG(RPiAgc, Debug) << \"Want total exposure \" << status_.totalExposureValue;\n>                                 /*\n>                                  * Never ask for a gain < 1.0, and also impose\n> @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n>                         }\n>                         if (status_.fixedAnalogueGain == 0.0) {\n>                                 if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {\n> -                                       analogueGain = exposureValue / shutterTime;\n> +                                       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +                                       double exposureDouble = exposureValue.get<std::nano>();\n> +                                       double shutterTimeDouble = shutterTime.get<std::nano>();\n> +                                       analogueGain = exposureDouble / shutterTimeDouble;\n>                                         break;\n>                                 }\n>                                 analogueGain = exposureMode_->gain[stage];\n> @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n>          */\n>         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n>             status_.flickerPeriod) {\n> -               int flickerPeriods = shutterTime / status_.flickerPeriod;\n> +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> +               double shutterTimeDouble = shutterTime.get<std::nano>();\n> +               double flickerPeriod = status_.flickerPeriod.get<std::nano>();\n> +               int flickerPeriods = shutterTimeDouble / flickerPeriod;\n>                 if (flickerPeriods) {\n>                         Duration newShutterTime = flickerPeriods * status_.flickerPeriod;\n> -                       analogueGain *= shutterTime / newShutterTime;\n> +                       double newShutterTimeDouble = newShutterTime.get<std::nano>();\n> +                       analogueGain *= shutterTimeDouble / newShutterTimeDouble;\n>                         /*\n>                          * We should still not allow the ag to go over the\n>                          * largest value in the exposure mode. Note that this\n> diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> index 9759186a..49303409 100644\n> --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata)\n>                 /* add .5 to reflect the mid-points of bins */\n>                 double currentY = sum / (double)num + .5;\n>                 double gainRatio = referenceGain_ / currentGain;\n> +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> +               double referenceShutterSpeedDouble = referenceShutterSpeed_.get<std::nano>();\n> +               double deviceShutterSpeed = deviceStatus.shutterSpeed.get<std::nano>();\n>                 double shutterSpeedRatio =\n> -                       referenceShutterSpeed_ / deviceStatus.shutterSpeed;\n> +                       referenceShutterSpeedDouble / deviceShutterSpeed;\n>                 double apertureRatio = referenceAperture_ / currentAperture;\n>                 double yRatio = currentY * (65536 / numBins) / referenceY_;\n>                 double estimatedLux = shutterSpeedRatio * gainRatio *\n> diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\n> index 04062a36..3ea0b732 100644\n> --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)\n>  {\n>         /* Configure the default exposure and gain. */\n>         context.activeState.agc.gain = std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> -       context.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration;\n> +       /* TODO(Bug 156): Explicit division of ticks (e.g., `x.get<std::nano>() /\n> +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> +        * LLVM bug 41130 and should be reverted once we no longer target\n> +        * Android 11 / sdk30 since it compromises unit safety and readability. */\n\n\t/*\n\t * For multiline comments, please keep the opening '/*' and\n\t * closing '*/' on their own line.\n\t */\n\n> +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> +       long double exposure = ten_millis.get<std::nano>() / context.configuration.sensor.lineDuration.get<std::nano>();\n> +       context.activeState.agc.exposure = uint32_t(exposure);\n>  \n>         /*\n>          * According to the RkISP1 documentation:\n> @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n>         /*\n>          * Push the shutter time up to the maximum first, and only then\n>          * increase the gain.\n> +        *\n> +        * TODO(Bug 156): Explicit division of ticks (e.g., `x.get<std::nano>() /\n> +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> +        * LLVM bug 41130 and should be reverted once we no longer target\n> +        * Android 11 / sdk30 since it compromises unit safety and readability.\n>          */\n> -       utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> +       utils::Duration shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> +       utils::Duration shutterTime = std::clamp<utils::Duration>(shutterTimeUnclamped,\n>                                                                   minShutterSpeed, maxShutterSpeed);\n> -       double stepGain = std::clamp(exposureValue / shutterTime,\n> +       double stepGainUnclamped = exposureValue.get<std::nano>() / shutterTime.get<std::nano>();\n> +       double stepGain = std::clamp(stepGainUnclamped,\n>                                      minAnalogueGain, maxAnalogueGain);\n>         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n>                               << shutterTime << \" and \"\n>                               << stepGain;\n>  \n>         /* Update the estimated exposure and gain. */\n> -       activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;\n> +       activeState.agc.exposure = uint32_t(shutterTime.get<std::nano>() /\n> +               configuration.sensor.lineDuration.get<std::nano>());\n\n(Not for your patch, but) I wonder if activeState.agc.exposure would be\nbetter stored as a Duration. I guess it depends on where it gets used\nmost. (as a duration, or as a double)\n\n\n>         activeState.agc.gain = stepGain;\n>  }\n>  \n> -- \n> 2.34.1\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 05823BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Oct 2022 10:41:18 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3824162F0F;\n\tMon, 24 Oct 2022 12:41:17 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C602262EC6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Oct 2022 12:41:15 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 47C9D3D7;\n\tMon, 24 Oct 2022 12:41:15 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666608077;\n\tbh=tQ0Vdd24qFj2UiGFgnXxSifwU29JOWCMU62KONHV8Jo=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=ZGyXBPF5fv7x3hW+/tLSkAfNpMEnAsHvMYAr0gsXmidzcJaH2pkeOXpYFD2a4cEeK\n\tLqxPfcVYf2W9bW1EJnjBn9APq49+lQVRMIsXyXlIh9fzK/NgMjI8ni6YUwhccSTjvk\n\toGT6G5WvWxXrbHZaME2hMOWgjyDnsDSuCA1SFYAYd6kJTTqaJBxN0mo6clFNcBuDCd\n\tckTPbfudDH/CswV8zViqFb4UE1vwNalXJtsWu3niww7IuWWTkQLVSXO2o1oidHXZEM\n\tNQ08EKILR53j1yPZD2eAoPRV5qWgl/Gad4meX1WrTCMUnc2ADGNVxGbzOlYApgL3p0\n\tF6jIK2xDeb56w==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666608075;\n\tbh=tQ0Vdd24qFj2UiGFgnXxSifwU29JOWCMU62KONHV8Jo=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=AxZEZLwZZORhQSgOfA7VNX3d6v6qUmkXO/7kqB/D+qDyPgoZDqIJR5A0frFQr6gbz\n\tiv7V63p5t+pXawalOz3+MmPq+a9pyICEHG/a1wjgzj+E0+F/7jIdQXIJOVkUd74tIT\n\tX2tc2N3wmXFytpz2z3+6VZsUhN8e4D8E58anr6I4="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"AxZEZLwZ\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20221024055543.116040-2-nicholas@rothemail.net>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>","To":"libcamera-devel@lists.libcamera.org","Date":"Mon, 24 Oct 2022 11:41:12 +0100","Message-ID":"<166660807272.2560709.18376612569572892760@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"nicholas@rothemail.net","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25540,"web_url":"https://patchwork.libcamera.org/comment/25540/","msgid":"<166660821851.2560709.15197334109665152747@Monstersaurus>","date":"2022-10-24T10:43:38","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Kieran Bingham (2022-10-24 11:41:12)\n> Hi Nicholas,\n> \n> Thanks for breaking these up - much easier to review, and work out how\n> to integrate.\n> \n> Could I ask you to read https://cbea.ms/git-commit/ please?\n> \n> That's not written by us, but it's a close summary of how we like to see\n> commit messages formed for the project.\n> \n> \n> \n> Quoting Nicholas Roth via libcamera-devel (2022-10-24 06:55:33)\n> > From: Nicholas Roth <nicholas@rothemail.net>\n> > \n> \n\nOoops, I didn't come back up to finish this:\n> So for this patch, I would propose a subject line / commit message of:\n\nipa: workaround libcxx duration limitation\n \nA bug in libcxx used by clang version 11.0.2 is prevalent when building\nlibcamera for Android SDK30. This has been fixed and integrated upstream\nwith [0].\n\nAs a workaround, directly cast the affected chrono types to prevent\noperations of Chrono or Duration being divided.\n\n[0] https://github.com/llvm/llvm-project/commit/efa6d803c624f9251d0ab7881122501bb9d27368\nBug: https://bugs.libcamera.org/show_bug.cgi?id=156\n\nSigned-off-by: Nicholas Roth <nicholas@rothemail.net>\n\n\n(Adapt, expand, correct the above of course)\n--\nKieran","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 71846BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Oct 2022 10:43:44 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8777E62F12;\n\tMon, 24 Oct 2022 12:43:43 +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 725B162EC6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Oct 2022 12:43:41 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E555D471;\n\tMon, 24 Oct 2022 12:43:40 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666608223;\n\tbh=+AkfUhBbd5ZM7IRDYjVRjnGZROi986z7wfMn8xUkivE=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=3JCT8cLLpd9VctO2Sy3GpHJf8uKmY4n01024y1MrYvXKmFrmPDXs/ifzilf/sg86Y\n\t+rkNPQQSDMYbrhUmgdsx1r/9FWjHJqFPXfjdcUXZxZ1dQTXDUL8QoWpv3Lqzt41aok\n\t7W79GjjzAx0pa6AEkV0uBXa7OtFJP4n4FiUnmfy/NKRUinbvcSCG1nkMN3OfpirGXK\n\t/rt3QJYYaise0T6LsYphNh+AheXYAwha5OrvExO3i+fodRWrdR5bOnub65+gHJu9s5\n\t+fGscFZ1ifcRsKiKza3F0AaZWXFHoAyX0uqYa2KNl1mdtWThCp8narOb0ldbaSEHGx\n\tAjvtDMUDgWI2Q==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666608221;\n\tbh=+AkfUhBbd5ZM7IRDYjVRjnGZROi986z7wfMn8xUkivE=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=Si/ylxAdfaCcGOEfCJ2PJUtX2uok2niocvKdFdbzoNUDlT1HFHU4KPpoUQpGDeOEr\n\tjgRKQV0zugdvnYSybO2BOEQGavE5kHrpL5Q8L1GByIBhEWjfubmCEd3lO5JpkVC7m/\n\t2nyLjR9jh5lJWJyn2yhSg5jUx2eiYpbqLWyxHy1s="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"Si/ylxAd\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<166660807272.2560709.18376612569572892760@Monstersaurus>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<166660807272.2560709.18376612569572892760@Monstersaurus>","To":"libcamera-devel@lists.libcamera.org","Date":"Mon, 24 Oct 2022 11:43:38 +0100","Message-ID":"<166660821851.2560709.15197334109665152747@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"nicholas@rothemail.net","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25541,"web_url":"https://patchwork.libcamera.org/comment/25541/","msgid":"<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>","date":"2022-10-24T10:50:53","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Nicholas,\n\nThank you for your patch.\n\nAs you've already noted, this removes much of the niceness of using\nstd::chrono\ntypes, and impacts code readability.\n\nI wonder if it would be possible to overload \"operator /\" for the\nutils::Duration type\nto work-around this bug instead? That way majority of the code need not\nchange\nand the fix only lives in one place in the codebase making it easier to\nrevert when\nthe time comes.\n\nRegards,\nNaush\n\nOn Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel <\nlibcamera-devel@lists.libcamera.org> wrote:\n\n> From: Nicholas Roth <nicholas@rothemail.net>\n>\n> ---\n>  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n>  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n>  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n>  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n>  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n>  src/ipa/rkisp1/algorithms/agc.cpp          | 22 ++++++++++++++++++----\n>  6 files changed, 60 insertions(+), 17 deletions(-)\n>\n> diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n> b/src/ipa/ipu3/algorithms/agc.cpp\n> index a1a3c38f..80c551bb 100644\n> --- a/src/ipa/ipu3/algorithms/agc.cpp\n> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n>\n>         /* Configure the default exposure and gain. */\n>         activeState.agc.gain = std::max(minAnalogueGain_,\n> kMinAnalogueGain);\n> -       activeState.agc.exposure = 10ms /\n> configuration.sensor.lineDuration;\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> +       activeState.agc.exposure = ten_millis /\n> +               configuration.sensor.lineDuration.get<std::nano>();\n>\n>         frameCount_ = 0;\n>         return 0;\n> @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n>          *\n>          * Push the shutter time up to the maximum first, and only then\n>          * increase the gain.\n> +        *\n> +        * TODO(Bug 156): Workaround for LLVM bug.\n>          */\n> +       double exposureValueDouble = exposureValue.get<std::nano>();\n> +       utils::Duration shutterTimeRaw(exposureValueDouble /\n> minAnalogueGain_);\n>         utils::Duration shutterTime =\n> -               std::clamp<utils::Duration>(exposureValue /\n> minAnalogueGain_,\n> +               std::clamp<utils::Duration>(shutterTimeRaw,\n>                                             minShutterSpeed_,\n> maxShutterSpeed_);\n> -       double stepGain = std::clamp(exposureValue / shutterTime,\n> +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> +       double stepGain = std::clamp(exposureValueDouble /\n> shutterTimeDouble,\n>                                      minAnalogueGain_, maxAnalogueGain_);\n>         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n>                             << shutterTime << \" and \"\n> @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n>\n>         IPAActiveState &activeState = context.activeState;\n>         /* Update the estimated exposure and gain. */\n> -       activeState.agc.exposure = shutterTime /\n> configuration.sensor.lineDuration;\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +       double lineDurationDouble =\n> configuration.sensor.lineDuration.get<std::nano>();\n> +       activeState.agc.exposure = shutterTimeDouble / lineDurationDouble;\n>         activeState.agc.gain = stepGain;\n>  }\n>\n> diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n> b/src/ipa/raspberrypi/cam_helper.cpp\n> index d90ac1de..31a9a1ef 100644\n> --- a/src/ipa/raspberrypi/cam_helper.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr\n> &stats,\n>\n>  uint32_t CamHelper::exposureLines(const Duration exposure, const Duration\n> lineLength) const\n>  {\n> -       return exposure / lineLength;\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +       return exposure.get<std::nano>() / lineLength.get<std::nano>();\n>  }\n>\n>  Duration CamHelper::exposure(uint32_t exposureLines, const Duration\n> lineLength) const\n> @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t>\n> CamHelper::getBlanking(Duration &exposure,\n>          *\n>          * frameLengthMax gets calculated on the smallest line length as\n> we do\n>          * not want to extend that unless absolutely necessary.\n> +        *\n> +        * TODO(Bug 156): Workaround for LLVM bug.\n>          */\n> -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> +       frameLengthMin = minFrameDuration.get<std::nano>() /\n> mode_.minLineLength.get<std::nano>();\n> +       frameLengthMax = maxFrameDuration.get<std::nano>() /\n> mode_.minLineLength.get<std::nano>();\n>\n>         /*\n>          * Watch out for (exposureLines + frameIntegrationDiff_)\n> overflowing a\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> index ecb845e7..e48f5cf2 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n>  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n>                                         [[maybe_unused]] const Duration\n> lineLength) const\n>  {\n> -       return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) /\n> timePerLine);\n> +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> +       double exposureTime = Duration(exposure -\n> 14.26us).get<std::nano>();\n> +       double timePerLineNano = timePerLine.get<std::nano>();\n> +       return std::max<uint32_t>(minExposureLines, exposureTime /\n> timePerLineNano);\n>  }\n>\n>  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> index bd54a639..720ba788 100644\n> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n>                         Duration actualExposure =\n> deviceStatus.shutterSpeed *\n>\n> deviceStatus.analogueGain;\n>                         if (actualExposure) {\n> -                               status_.digitalGain =\n> status_.totalExposureValue / actualExposure;\n> +                               /* TODO(Bug 156): Workaround for LLVM bug.\n> */\n> +                               double totalExposureDouble =\n> status_.totalExposureValue.get<std::nano>();\n> +                               double actualExposureDouble =\n> actualExposure.get<std::nano>();\n> +                               status_.digitalGain = totalExposureDouble\n> / actualExposureDouble;\n>                                 LOG(RPiAgc, Debug) << \"Want total exposure\n> \" << status_.totalExposureValue;\n>                                 /*\n>                                  * Never ask for a gain < 1.0, and also\n> impose\n> @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n>                         }\n>                         if (status_.fixedAnalogueGain == 0.0) {\n>                                 if (exposureMode_->gain[stage] *\n> shutterTime >= exposureValue) {\n> -                                       analogueGain = exposureValue /\n> shutterTime;\n> +                                       /* TODO(Bug 156): Workaround for\n> LLVM bug. */\n> +                                       double exposureDouble =\n> exposureValue.get<std::nano>();\n> +                                       double shutterTimeDouble =\n> shutterTime.get<std::nano>();\n> +                                       analogueGain = exposureDouble /\n> shutterTimeDouble;\n>                                         break;\n>                                 }\n>                                 analogueGain = exposureMode_->gain[stage];\n> @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n>          */\n>         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n>             status_.flickerPeriod) {\n> -               int flickerPeriods = shutterTime / status_.flickerPeriod;\n> +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> +               double shutterTimeDouble = shutterTime.get<std::nano>();\n> +               double flickerPeriod =\n> status_.flickerPeriod.get<std::nano>();\n> +               int flickerPeriods = shutterTimeDouble / flickerPeriod;\n>                 if (flickerPeriods) {\n>                         Duration newShutterTime = flickerPeriods *\n> status_.flickerPeriod;\n> -                       analogueGain *= shutterTime / newShutterTime;\n> +                       double newShutterTimeDouble =\n> newShutterTime.get<std::nano>();\n> +                       analogueGain *= shutterTimeDouble /\n> newShutterTimeDouble;\n>                         /*\n>                          * We should still not allow the ag to go over the\n>                          * largest value in the exposure mode. Note that\n> this\n> diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> index 9759186a..49303409 100644\n> --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata\n> *imageMetadata)\n>                 /* add .5 to reflect the mid-points of bins */\n>                 double currentY = sum / (double)num + .5;\n>                 double gainRatio = referenceGain_ / currentGain;\n> +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> +               double referenceShutterSpeedDouble =\n> referenceShutterSpeed_.get<std::nano>();\n> +               double deviceShutterSpeed =\n> deviceStatus.shutterSpeed.get<std::nano>();\n>                 double shutterSpeedRatio =\n> -                       referenceShutterSpeed_ / deviceStatus.shutterSpeed;\n> +                       referenceShutterSpeedDouble / deviceShutterSpeed;\n>                 double apertureRatio = referenceAperture_ /\n> currentAperture;\n>                 double yRatio = currentY * (65536 / numBins) / referenceY_;\n>                 double estimatedLux = shutterSpeedRatio * gainRatio *\n> diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n> b/src/ipa/rkisp1/algorithms/agc.cpp\n> index 04062a36..3ea0b732 100644\n> --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const\n> IPACameraSensorInfo &configInfo)\n>  {\n>         /* Configure the default exposure and gain. */\n>         context.activeState.agc.gain =\n> std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> -       context.activeState.agc.exposure = 10ms /\n> context.configuration.sensor.lineDuration;\n> +       /* TODO(Bug 156): Explicit division of ticks (e.g.,\n> `x.get<std::nano>() /\n> +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> +        * LLVM bug 41130 and should be reverted once we no longer target\n> +        * Android 11 / sdk30 since it compromises unit safety and\n> readability. */\n> +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> +       long double exposure = ten_millis.get<std::nano>() /\n> context.configuration.sensor.lineDuration.get<std::nano>();\n> +       context.activeState.agc.exposure = uint32_t(exposure);\n>\n>         /*\n>          * According to the RkISP1 documentation:\n> @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n>         /*\n>          * Push the shutter time up to the maximum first, and only then\n>          * increase the gain.\n> +        *\n> +        * TODO(Bug 156): Explicit division of ticks (e.g.,\n> `x.get<std::nano>() /\n> +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> +        * LLVM bug 41130 and should be reverted once we no longer target\n> +        * Android 11 / sdk30 since it compromises unit safety and\n> readability.\n>          */\n> -       utils::Duration shutterTime =\n> std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> +       utils::Duration\n> shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> +       utils::Duration shutterTime =\n> std::clamp<utils::Duration>(shutterTimeUnclamped,\n>\n> minShutterSpeed, maxShutterSpeed);\n> -       double stepGain = std::clamp(exposureValue / shutterTime,\n> +       double stepGainUnclamped = exposureValue.get<std::nano>() /\n> shutterTime.get<std::nano>();\n> +       double stepGain = std::clamp(stepGainUnclamped,\n>                                      minAnalogueGain, maxAnalogueGain);\n>         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n>                               << shutterTime << \" and \"\n>                               << stepGain;\n>\n>         /* Update the estimated exposure and gain. */\n> -       activeState.agc.exposure = shutterTime /\n> configuration.sensor.lineDuration;\n> +       activeState.agc.exposure = uint32_t(shutterTime.get<std::nano>() /\n> +               configuration.sensor.lineDuration.get<std::nano>());\n>         activeState.agc.gain = stepGain;\n>  }\n>\n> --\n> 2.34.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 DC086BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Oct 2022 10:51:11 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3A50162F14;\n\tMon, 24 Oct 2022 12:51:11 +0200 (CEST)","from mail-qv1-xf33.google.com (mail-qv1-xf33.google.com\n\t[IPv6:2607:f8b0:4864:20::f33])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9867162EC6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Oct 2022 12:51:09 +0200 (CEST)","by mail-qv1-xf33.google.com with SMTP id t16so6228316qvm.9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Oct 2022 03:51:09 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666608671;\n\tbh=NGTRnvR58Wd23qFBuPcX7vsFF3RwyX2NX5TYvarAWrA=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=PIzh0kis30IvIjVR0v1OHAZfjK5Dt1E+AHX/FTe9BFrkX7XqENIiuwdSP+owuKBGx\n\tzxPmFZuGA5RyqBEoKaxV+vY7J7cATYy0KFskxTrRLv0JEqLAIfdODzVDZnH1dnh0pm\n\tEHYkK+SD8iSFXbqefNiLUm+fQ3Z4ySVyjDYRF96iHh6rT/xcz9GrmWvv5mmHMdt+sq\n\tnUJ9PgzoqJAPuBkSY8UM1+V7cgy/eSzmDTDb7yKElE7uSp8p9q3seghdMsFu9w/iU6\n\typPVAVnEklqPvYja7TSSMi7EXoNce9XBhB/kRWOjc8Tx6we21Bp8vSkZ1ogD4TdpcE\n\t943Ass3yzyvrw==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=vOcVNXY1HlOClE5GaW/7vqpuZKigqImEHrSVIbe9Z3I=;\n\tb=jnfO6kwFqyBKJJ6KUiObBKnUZlPXKsNWRUb4/h3s7FhHydMvXUsyR6JJ0A8vw5Vsa4\n\t4UdusbzpKRcdmVdZN5rD5xOrSfQq1HByl90MK8MOXcz4siiOTRWYZecE+miheQ1fUTKf\n\tm1APiCeLBsLdPymNXcbmT/UP24+EZTn3WtKajYEQ20v0OWq1H7OYWSABXRRacfU9RlsI\n\t5Lbj76Fcjtl2lDeTYlraL0jrD/Z/WmwfvwIxzIRnBimQYyan3pbp7quQcrjfNN6qx7VP\n\tyTynTnxZ34ye8wDbHOkLFaxTKZBlUBJ6wUmdnet3ISftkTSbmdGdsiJjw2/NUASfkAg2\n\tmlNQ=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"jnfO6kwF\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=vOcVNXY1HlOClE5GaW/7vqpuZKigqImEHrSVIbe9Z3I=;\n\tb=wau4Dwxp2OjbwqXfG33CKhbLzkgb+8pUMH32HZnGDMk/rjhMH9KJFy3XUH2UoFiXb5\n\trZprM3+LbYV77GVXkMSaeJOfo5g9LmAHETftFN+bYJkhcEbxZiqZQAO1dcAEfNCy6GtJ\n\tMmqYjeyCeRXmCWiNb+vZvU6CiGIETHueuFUGcvveVFSg7kRN1SyADkrgGFzjPzXlActV\n\tp8oAZT2QGQJzrZgltyvnS8tBbmUMF9Cs5A5puKEg6gMjAHXx4gGAh3ILMwieWJJRrJwu\n\tf3EB66z9rS3x97PhT0A/a21uyPHToQdaiaH7WiKeyDxS8etBoekRQkiq+/0PG2x6psss\n\t/teQ==","X-Gm-Message-State":"ACrzQf174rPLLvgK6VsVAIBBl/oEbph+r9vl0L1ZGsZOrH0qTVDUDrnN\n\tAAE3xOtwTMjwJqLAT34G0U9Zua61UzWIPs7KnBgqIePXgIU=","X-Google-Smtp-Source":"AMsMyM7mRcRTNxwGvxZi8VD6CKaSYEpBMFylVDdjWd6iKapecD/wIqUVGpfmEMtnU7WQMQub7rwmQzbVKFkyRFa/QhY=","X-Received":"by 2002:ad4:5f0b:0:b0:4b1:7a60:399a with SMTP id\n\tfo11-20020ad45f0b000000b004b17a60399amr27503410qvb.101.1666608668194;\n\tMon, 24 Oct 2022 03:51:08 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>","In-Reply-To":"<20221024055543.116040-2-nicholas@rothemail.net>","Date":"Mon, 24 Oct 2022 11:50:53 +0100","Message-ID":"<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>","To":"libcamera-devel@lists.libcamera.org","Content-Type":"multipart/alternative; boundary=\"000000000000a5ca9e05ebc591cd\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Naushir Patuck via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Naushir Patuck <naush@raspberrypi.com>","Cc":"nicholas@rothemail.net","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25542,"web_url":"https://patchwork.libcamera.org/comment/25542/","msgid":"<166661159419.2560709.7567992482096428177@Monstersaurus>","date":"2022-10-24T11:39:54","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Naushir Patuck via libcamera-devel (2022-10-24 11:50:53)\n> Hi Nicholas,\n> \n> Thank you for your patch.\n> \n> As you've already noted, this removes much of the niceness of using\n> std::chrono\n> types, and impacts code readability.\n> \n> I wonder if it would be possible to overload \"operator /\" for the\n> utils::Duration type\n> to work-around this bug instead? That way majority of the code need not\n> change\n> and the fix only lives in one place in the codebase making it easier to\n> revert when\n> the time comes.\n\nSeconded here too (and in\nhttps://bugs.libcamera.org/show_bug.cgi?id=156#c2), but I haven't yet\nlooked into what the underlying bug is.\n\nIf we can't tackle this with utils::Duration, I'm weary that we'll end\nup rapidly introducing more breakage :-S\n--\nKieran\n\n\n> \n> Regards,\n> Naush\n> \n> On Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel <\n> libcamera-devel@lists.libcamera.org> wrote:\n> \n> > From: Nicholas Roth <nicholas@rothemail.net>\n> >\n> > ---\n> >  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n> >  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n> >  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n> >  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n> >  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n> >  src/ipa/rkisp1/algorithms/agc.cpp          | 22 ++++++++++++++++++----\n> >  6 files changed, 60 insertions(+), 17 deletions(-)\n> >\n> > diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n> > b/src/ipa/ipu3/algorithms/agc.cpp\n> > index a1a3c38f..80c551bb 100644\n> > --- a/src/ipa/ipu3/algorithms/agc.cpp\n> > +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> > @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n> >\n> >         /* Configure the default exposure and gain. */\n> >         activeState.agc.gain = std::max(minAnalogueGain_,\n> > kMinAnalogueGain);\n> > -       activeState.agc.exposure = 10ms /\n> > configuration.sensor.lineDuration;\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> > +       activeState.agc.exposure = ten_millis /\n> > +               configuration.sensor.lineDuration.get<std::nano>();\n> >\n> >         frameCount_ = 0;\n> >         return 0;\n> > @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext &context,\n> > IPAFrameContext &frameContext,\n> >          *\n> >          * Push the shutter time up to the maximum first, and only then\n> >          * increase the gain.\n> > +        *\n> > +        * TODO(Bug 156): Workaround for LLVM bug.\n> >          */\n> > +       double exposureValueDouble = exposureValue.get<std::nano>();\n> > +       utils::Duration shutterTimeRaw(exposureValueDouble /\n> > minAnalogueGain_);\n> >         utils::Duration shutterTime =\n> > -               std::clamp<utils::Duration>(exposureValue /\n> > minAnalogueGain_,\n> > +               std::clamp<utils::Duration>(shutterTimeRaw,\n> >                                             minShutterSpeed_,\n> > maxShutterSpeed_);\n> > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> > +       double stepGain = std::clamp(exposureValueDouble /\n> > shutterTimeDouble,\n> >                                      minAnalogueGain_, maxAnalogueGain_);\n> >         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n> >                             << shutterTime << \" and \"\n> > @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context,\n> > IPAFrameContext &frameContext,\n> >\n> >         IPAActiveState &activeState = context.activeState;\n> >         /* Update the estimated exposure and gain. */\n> > -       activeState.agc.exposure = shutterTime /\n> > configuration.sensor.lineDuration;\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       double lineDurationDouble =\n> > configuration.sensor.lineDuration.get<std::nano>();\n> > +       activeState.agc.exposure = shutterTimeDouble / lineDurationDouble;\n> >         activeState.agc.gain = stepGain;\n> >  }\n> >\n> > diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n> > b/src/ipa/raspberrypi/cam_helper.cpp\n> > index d90ac1de..31a9a1ef 100644\n> > --- a/src/ipa/raspberrypi/cam_helper.cpp\n> > +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> > @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr\n> > &stats,\n> >\n> >  uint32_t CamHelper::exposureLines(const Duration exposure, const Duration\n> > lineLength) const\n> >  {\n> > -       return exposure / lineLength;\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       return exposure.get<std::nano>() / lineLength.get<std::nano>();\n> >  }\n> >\n> >  Duration CamHelper::exposure(uint32_t exposureLines, const Duration\n> > lineLength) const\n> > @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t>\n> > CamHelper::getBlanking(Duration &exposure,\n> >          *\n> >          * frameLengthMax gets calculated on the smallest line length as\n> > we do\n> >          * not want to extend that unless absolutely necessary.\n> > +        *\n> > +        * TODO(Bug 156): Workaround for LLVM bug.\n> >          */\n> > -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> > -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> > +       frameLengthMin = minFrameDuration.get<std::nano>() /\n> > mode_.minLineLength.get<std::nano>();\n> > +       frameLengthMax = maxFrameDuration.get<std::nano>() /\n> > mode_.minLineLength.get<std::nano>();\n> >\n> >         /*\n> >          * Watch out for (exposureLines + frameIntegrationDiff_)\n> > overflowing a\n> > diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > index ecb845e7..e48f5cf2 100644\n> > --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n> >  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n> >                                         [[maybe_unused]] const Duration\n> > lineLength) const\n> >  {\n> > -       return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) /\n> > timePerLine);\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       double exposureTime = Duration(exposure -\n> > 14.26us).get<std::nano>();\n> > +       double timePerLineNano = timePerLine.get<std::nano>();\n> > +       return std::max<uint32_t>(minExposureLines, exposureTime /\n> > timePerLineNano);\n> >  }\n> >\n> >  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > index bd54a639..720ba788 100644\n> > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n> >                         Duration actualExposure =\n> > deviceStatus.shutterSpeed *\n> >\n> > deviceStatus.analogueGain;\n> >                         if (actualExposure) {\n> > -                               status_.digitalGain =\n> > status_.totalExposureValue / actualExposure;\n> > +                               /* TODO(Bug 156): Workaround for LLVM bug.\n> > */\n> > +                               double totalExposureDouble =\n> > status_.totalExposureValue.get<std::nano>();\n> > +                               double actualExposureDouble =\n> > actualExposure.get<std::nano>();\n> > +                               status_.digitalGain = totalExposureDouble\n> > / actualExposureDouble;\n> >                                 LOG(RPiAgc, Debug) << \"Want total exposure\n> > \" << status_.totalExposureValue;\n> >                                 /*\n> >                                  * Never ask for a gain < 1.0, and also\n> > impose\n> > @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n> >                         }\n> >                         if (status_.fixedAnalogueGain == 0.0) {\n> >                                 if (exposureMode_->gain[stage] *\n> > shutterTime >= exposureValue) {\n> > -                                       analogueGain = exposureValue /\n> > shutterTime;\n> > +                                       /* TODO(Bug 156): Workaround for\n> > LLVM bug. */\n> > +                                       double exposureDouble =\n> > exposureValue.get<std::nano>();\n> > +                                       double shutterTimeDouble =\n> > shutterTime.get<std::nano>();\n> > +                                       analogueGain = exposureDouble /\n> > shutterTimeDouble;\n> >                                         break;\n> >                                 }\n> >                                 analogueGain = exposureMode_->gain[stage];\n> > @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n> >          */\n> >         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n> >             status_.flickerPeriod) {\n> > -               int flickerPeriods = shutterTime / status_.flickerPeriod;\n> > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +               double shutterTimeDouble = shutterTime.get<std::nano>();\n> > +               double flickerPeriod =\n> > status_.flickerPeriod.get<std::nano>();\n> > +               int flickerPeriods = shutterTimeDouble / flickerPeriod;\n> >                 if (flickerPeriods) {\n> >                         Duration newShutterTime = flickerPeriods *\n> > status_.flickerPeriod;\n> > -                       analogueGain *= shutterTime / newShutterTime;\n> > +                       double newShutterTimeDouble =\n> > newShutterTime.get<std::nano>();\n> > +                       analogueGain *= shutterTimeDouble /\n> > newShutterTimeDouble;\n> >                         /*\n> >                          * We should still not allow the ag to go over the\n> >                          * largest value in the exposure mode. Note that\n> > this\n> > diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > index 9759186a..49303409 100644\n> > --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata\n> > *imageMetadata)\n> >                 /* add .5 to reflect the mid-points of bins */\n> >                 double currentY = sum / (double)num + .5;\n> >                 double gainRatio = referenceGain_ / currentGain;\n> > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +               double referenceShutterSpeedDouble =\n> > referenceShutterSpeed_.get<std::nano>();\n> > +               double deviceShutterSpeed =\n> > deviceStatus.shutterSpeed.get<std::nano>();\n> >                 double shutterSpeedRatio =\n> > -                       referenceShutterSpeed_ / deviceStatus.shutterSpeed;\n> > +                       referenceShutterSpeedDouble / deviceShutterSpeed;\n> >                 double apertureRatio = referenceAperture_ /\n> > currentAperture;\n> >                 double yRatio = currentY * (65536 / numBins) / referenceY_;\n> >                 double estimatedLux = shutterSpeedRatio * gainRatio *\n> > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n> > b/src/ipa/rkisp1/algorithms/agc.cpp\n> > index 04062a36..3ea0b732 100644\n> > --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> > +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> > @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const\n> > IPACameraSensorInfo &configInfo)\n> >  {\n> >         /* Configure the default exposure and gain. */\n> >         context.activeState.agc.gain =\n> > std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> > -       context.activeState.agc.exposure = 10ms /\n> > context.configuration.sensor.lineDuration;\n> > +       /* TODO(Bug 156): Explicit division of ticks (e.g.,\n> > `x.get<std::nano>() /\n> > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> > +        * LLVM bug 41130 and should be reverted once we no longer target\n> > +        * Android 11 / sdk30 since it compromises unit safety and\n> > readability. */\n> > +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> > +       long double exposure = ten_millis.get<std::nano>() /\n> > context.configuration.sensor.lineDuration.get<std::nano>();\n> > +       context.activeState.agc.exposure = uint32_t(exposure);\n> >\n> >         /*\n> >          * According to the RkISP1 documentation:\n> > @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext &context,\n> > IPAFrameContext &frameContext,\n> >         /*\n> >          * Push the shutter time up to the maximum first, and only then\n> >          * increase the gain.\n> > +        *\n> > +        * TODO(Bug 156): Explicit division of ticks (e.g.,\n> > `x.get<std::nano>() /\n> > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> > +        * LLVM bug 41130 and should be reverted once we no longer target\n> > +        * Android 11 / sdk30 since it compromises unit safety and\n> > readability.\n> >          */\n> > -       utils::Duration shutterTime =\n> > std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> > +       utils::Duration\n> > shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> > +       utils::Duration shutterTime =\n> > std::clamp<utils::Duration>(shutterTimeUnclamped,\n> >\n> > minShutterSpeed, maxShutterSpeed);\n> > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > +       double stepGainUnclamped = exposureValue.get<std::nano>() /\n> > shutterTime.get<std::nano>();\n> > +       double stepGain = std::clamp(stepGainUnclamped,\n> >                                      minAnalogueGain, maxAnalogueGain);\n> >         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n> >                               << shutterTime << \" and \"\n> >                               << stepGain;\n> >\n> >         /* Update the estimated exposure and gain. */\n> > -       activeState.agc.exposure = shutterTime /\n> > configuration.sensor.lineDuration;\n> > +       activeState.agc.exposure = uint32_t(shutterTime.get<std::nano>() /\n> > +               configuration.sensor.lineDuration.get<std::nano>());\n> >         activeState.agc.gain = stepGain;\n> >  }\n> >\n> > --\n> > 2.34.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 CCB99BDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Oct 2022 11:39:59 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3063F62F15;\n\tMon, 24 Oct 2022 13:39:59 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A056862EC6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Oct 2022 13:39:57 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 29C37471;\n\tMon, 24 Oct 2022 13:39:57 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666611599;\n\tbh=L0yMAyc321oHayAbsF3v9X0RXGCaFhPnj3tqlXKI0BI=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=FN6JMK4eKWYIMZDo9h7Q/qTYKvHz9AemVOjjiaz63uL13pkLDOX9dfw6X8zNHXsid\n\th6k6zREMotrBTNQ3N1ZeMIFv8jbRyR/xHm9KmeWVKxZnaF9HS8XzKnsBhag9GcgMCg\n\tQ9I9bRF7B9thkpsUb4edPdpLKurCPPQD+q632kRnvKLHz3AIsiSTabGUQAXGG0D6Y2\n\tQcdVACa5i+Dzqp3PrpRGzLvCsXIABJNMKxVm4tGNALomnuleMGL2H1uI0RN859/+6w\n\tjgYnNvdqzU4ZNPOyTHbJbhc7O9xa5MDhA5pRso5E+IkITFDe0f8HGgUyg83AWlUdwv\n\tYxFsiIsWthw+A==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666611597;\n\tbh=L0yMAyc321oHayAbsF3v9X0RXGCaFhPnj3tqlXKI0BI=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=GqK4HxkhYAfePfMqRraSRYsjvsdvSldB7m5rRqCqp6RbJ+kbeRtXy7O5yTjjfOAbE\n\tbfPUYCmu8blEMrc+R7UGWyEErYRwVuGNqrN4J1G1nGWRf7aOzKYJEHOO8eWIt4YY4Y\n\tjTb2RX+sN5jwRAcjEE3hp1GWkwsTpSUk22bwbgo4="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"GqK4Hxkh\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>","To":"Naushir Patuck <naush@raspberrypi.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 24 Oct 2022 12:39:54 +0100","Message-ID":"<166661159419.2560709.7567992482096428177@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"nicholas@rothemail.net","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25545,"web_url":"https://patchwork.libcamera.org/comment/25545/","msgid":"<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>","date":"2022-10-24T13:30:09","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Mon, Oct 24, 2022 at 11:50:53AM +0100, Naushir Patuck via libcamera-devel wrote:\n> Hi Nicholas,\n> \n> Thank you for your patch.\n> \n> As you've already noted, this removes much of the niceness of using\n> std::chrono\n> types, and impacts code readability.\n> \n> I wonder if it would be possible to overload \"operator /\" for the utils::Duration type\n> to work-around this bug instead? That way majority of the code need not change\n> and the fix only lives in one place in the codebase making it easier to revert when\n> the time comes.\n\nOr, if that can't be done for the Duration type only, somehow override\nthe std::chrono::duration::operator/() globally, with a version that\nfixes the bug. I think this change is fairly intrusive, I'd like a more\ncentralized solution that will not require patching every division.\n\n> On Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel wrote:\n> \n> > From: Nicholas Roth <nicholas@rothemail.net>\n> >\n> > ---\n> >  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n> >  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n> >  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n> >  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n> >  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n> >  src/ipa/rkisp1/algorithms/agc.cpp          | 22 ++++++++++++++++++----\n> >  6 files changed, 60 insertions(+), 17 deletions(-)\n> >\n> > diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\n> > index a1a3c38f..80c551bb 100644\n> > --- a/src/ipa/ipu3/algorithms/agc.cpp\n> > +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> > @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n> >\n> >         /* Configure the default exposure and gain. */\n> >         activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n> > -       activeState.agc.exposure = 10ms / configuration.sensor.lineDuration;\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> > +       activeState.agc.exposure = ten_millis /\n> > +               configuration.sensor.lineDuration.get<std::nano>();\n> >\n> >         frameCount_ = 0;\n> >         return 0;\n> > @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n> >          *\n> >          * Push the shutter time up to the maximum first, and only then\n> >          * increase the gain.\n> > +        *\n> > +        * TODO(Bug 156): Workaround for LLVM bug.\n> >          */\n> > +       double exposureValueDouble = exposureValue.get<std::nano>();\n> > +       utils::Duration shutterTimeRaw(exposureValueDouble / minAnalogueGain_);\n> >         utils::Duration shutterTime =\n> > -               std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,\n> > +               std::clamp<utils::Duration>(shutterTimeRaw,\n> >                                             minShutterSpeed_, maxShutterSpeed_);\n> > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> > +       double stepGain = std::clamp(exposureValueDouble / shutterTimeDouble,\n> >                                      minAnalogueGain_, maxAnalogueGain_);\n> >         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n> >                             << shutterTime << \" and \"\n> > @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n> >\n> >         IPAActiveState &activeState = context.activeState;\n> >         /* Update the estimated exposure and gain. */\n> > -       activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       double lineDurationDouble = configuration.sensor.lineDuration.get<std::nano>();\n> > +       activeState.agc.exposure = shutterTimeDouble / lineDurationDouble;\n> >         activeState.agc.gain = stepGain;\n> >  }\n> >\n> > diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp\n> > index d90ac1de..31a9a1ef 100644\n> > --- a/src/ipa/raspberrypi/cam_helper.cpp\n> > +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> > @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr\n> > &stats,\n> >\n> >  uint32_t CamHelper::exposureLines(const Duration exposure, const Duration\n> > lineLength) const\n> >  {\n> > -       return exposure / lineLength;\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       return exposure.get<std::nano>() / lineLength.get<std::nano>();\n> >  }\n> >\n> >  Duration CamHelper::exposure(uint32_t exposureLines, const Duration lineLength) const\n> > @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t> CamHelper::getBlanking(Duration &exposure,\n> >          *\n> >          * frameLengthMax gets calculated on the smallest line length as we do\n> >          * not want to extend that unless absolutely necessary.\n> > +        *\n> > +        * TODO(Bug 156): Workaround for LLVM bug.\n> >          */\n> > -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> > -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> > +       frameLengthMin = minFrameDuration.get<std::nano>() / mode_.minLineLength.get<std::nano>();\n> > +       frameLengthMax = maxFrameDuration.get<std::nano>() / mode_.minLineLength.get<std::nano>();\n> >\n> >         /*\n> >          * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a\n> > diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > index ecb845e7..e48f5cf2 100644\n> > --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n> >  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n> >                                         [[maybe_unused]] const Duration lineLength) const\n> >  {\n> > -       return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) / timePerLine);\n> > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +       double exposureTime = Duration(exposure - 14.26us).get<std::nano>();\n> > +       double timePerLineNano = timePerLine.get<std::nano>();\n> > +       return std::max<uint32_t>(minExposureLines, exposureTime / timePerLineNano);\n> >  }\n> >\n> >  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > index bd54a639..720ba788 100644\n> > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n> >                         Duration actualExposure = deviceStatus.shutterSpeed *\n> >                                                   deviceStatus.analogueGain;\n> >                         if (actualExposure) {\n> > -                               status_.digitalGain = status_.totalExposureValue / actualExposure;\n> > +                               /* TODO(Bug 156): Workaround for LLVM bug.\n> > */\n> > +                               double totalExposureDouble = status_.totalExposureValue.get<std::nano>();\n> > +                               double actualExposureDouble = actualExposure.get<std::nano>();\n> > +                               status_.digitalGain = totalExposureDouble / actualExposureDouble;\n> >                                 LOG(RPiAgc, Debug) << \"Want total exposure \" << status_.totalExposureValue;\n> >                                 /*\n> >                                  * Never ask for a gain < 1.0, and also impose\n> > @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n> >                         }\n> >                         if (status_.fixedAnalogueGain == 0.0) {\n> >                                 if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {\n> > -                                       analogueGain = exposureValue / shutterTime;\n> > +                                       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +                                       double exposureDouble = exposureValue.get<std::nano>();\n> > +                                       double shutterTimeDouble = shutterTime.get<std::nano>();\n> > +                                       analogueGain = exposureDouble / shutterTimeDouble;\n> >                                         break;\n> >                                 }\n> >                                 analogueGain = exposureMode_->gain[stage];\n> > @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n> >          */\n> >         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n> >             status_.flickerPeriod) {\n> > -               int flickerPeriods = shutterTime / status_.flickerPeriod;\n> > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +               double shutterTimeDouble = shutterTime.get<std::nano>();\n> > +               double flickerPeriod = status_.flickerPeriod.get<std::nano>();\n> > +               int flickerPeriods = shutterTimeDouble / flickerPeriod;\n> >                 if (flickerPeriods) {\n> >                         Duration newShutterTime = flickerPeriods * status_.flickerPeriod;\n> > -                       analogueGain *= shutterTime / newShutterTime;\n> > +                       double newShutterTimeDouble = newShutterTime.get<std::nano>();\n> > +                       analogueGain *= shutterTimeDouble / newShutterTimeDouble;\n> >                         /*\n> >                          * We should still not allow the ag to go over the\n> >                          * largest value in the exposure mode. Note that this\n> > diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > index 9759186a..49303409 100644\n> > --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata)\n> >                 /* add .5 to reflect the mid-points of bins */\n> >                 double currentY = sum / (double)num + .5;\n> >                 double gainRatio = referenceGain_ / currentGain;\n> > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > +               double referenceShutterSpeedDouble = referenceShutterSpeed_.get<std::nano>();\n> > +               double deviceShutterSpeed = deviceStatus.shutterSpeed.get<std::nano>();\n> >                 double shutterSpeedRatio =\n> > -                       referenceShutterSpeed_ / deviceStatus.shutterSpeed;\n> > +                       referenceShutterSpeedDouble / deviceShutterSpeed;\n> >                 double apertureRatio = referenceAperture_ / currentAperture;\n> >                 double yRatio = currentY * (65536 / numBins) / referenceY_;\n> >                 double estimatedLux = shutterSpeedRatio * gainRatio *\n> > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\n> > index 04062a36..3ea0b732 100644\n> > --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> > +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> > @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)\n> >  {\n> >         /* Configure the default exposure and gain. */\n> >         context.activeState.agc.gain = std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> > -       context.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration;\n> > +       /* TODO(Bug 156): Explicit division of ticks (e.g., `x.get<std::nano>() /\n> > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> > +        * LLVM bug 41130 and should be reverted once we no longer target\n> > +        * Android 11 / sdk30 since it compromises unit safety and readability. */\n> > +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> > +       long double exposure = ten_millis.get<std::nano>() / context.configuration.sensor.lineDuration.get<std::nano>();\n> > +       context.activeState.agc.exposure = uint32_t(exposure);\n> >\n> >         /*\n> >          * According to the RkISP1 documentation:\n> > @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n> >         /*\n> >          * Push the shutter time up to the maximum first, and only then\n> >          * increase the gain.\n> > +        *\n> > +        * TODO(Bug 156): Explicit division of ticks (e.g., `x.get<std::nano>() /\n> > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround for\n> > +        * LLVM bug 41130 and should be reverted once we no longer target\n> > +        * Android 11 / sdk30 since it compromises unit safety and readability.\n> >          */\n> > -       utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> > +       utils::Duration shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> > +       utils::Duration shutterTime = std::clamp<utils::Duration>(shutterTimeUnclamped,\n> >                                                                   minShutterSpeed, maxShutterSpeed);\n> > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > +       double stepGainUnclamped = exposureValue.get<std::nano>() / shutterTime.get<std::nano>();\n> > +       double stepGain = std::clamp(stepGainUnclamped,\n> >                                      minAnalogueGain, maxAnalogueGain);\n> >         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n> >                               << shutterTime << \" and \"\n> >                               << stepGain;\n> >\n> >         /* Update the estimated exposure and gain. */\n> > -       activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;\n> > +       activeState.agc.exposure = uint32_t(shutterTime.get<std::nano>() /\n> > +               configuration.sensor.lineDuration.get<std::nano>());\n> >         activeState.agc.gain = stepGain;\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 846F1BDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Oct 2022 13:30:37 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B4AE562F18;\n\tMon, 24 Oct 2022 15:30:36 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 520D762EC6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Oct 2022 15:30:35 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8E2C08BF;\n\tMon, 24 Oct 2022 15:30:34 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666618236;\n\tbh=4x69xtivXNI1ThmPk+H9yrTlM5R37wSd3yTwKiOH6gM=;\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=KDZzE5VUq69JwgC7QZQUX5p4eFW8Lflg7+NZciagTAYQqJ+oBZSY3reOCvd6picJV\n\tjD6gUxrF6w/SXDXS2r17ipYqf38lyi18jTprqHr5nVLQudunrI8FWi5pXySABOylNC\n\tjOOVmRjgKyoJ2GHu4+p6i7MvQQ7R6FiNyYUa/B0/wk8lAZm501p83HzVtILKfCyOPA\n\tUgy/SMk2WIQD6P2JqW7eMbI1HiTGGjAjgZNZm+3jfUkVoquErw1IvJ/TBTuVrRqns8\n\tfpHH08CVEEUlMhkRYKP+MlsFe8iu6cHlWCDMOw3eBCweaL+BcNRmoNA17Bw1fD4JyD\n\tXElUM1gIncR7A==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666618234;\n\tbh=4x69xtivXNI1ThmPk+H9yrTlM5R37wSd3yTwKiOH6gM=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=bsGQumi6YEE5dGafuPHpilnYAOe7qs1YELhp45+4nKhM1ebP23CoEZ7z+uasCeNh7\n\tOf5LLZLxhcQkE8OQJoes6NHmymDS+gQDzBKy5YClcM629pOeIo/sM3DNESzYIdu6OD\n\tc8N5wxJM8xitxbrgy5tYfZ7SUVMGHM2kvyBvKmho="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"bsGQumi6\"; dkim-atps=neutral","Date":"Mon, 24 Oct 2022 16:30:09 +0300","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"nicholas@rothemail.net, libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25567,"web_url":"https://patchwork.libcamera.org/comment/25567/","msgid":"<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>","date":"2022-10-25T03:15:36","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":137,"url":"https://patchwork.libcamera.org/api/people/137/","name":"Nicholas Roth","email":"nicholas@rothemail.net"},"content":"> Could I ask you to read https://cbea.ms/git-commit/ please?\nRead. I thought that was quite informative. I noticed some differences\nbetween the style suggested in the blog post and the commit messages you\nsuggest. Indeed, I have generally foregone good history in favor of\nconvenience in git projects, and I hope it will be interesting to\nexperience the advantages of clear history and educational to learn how\nthis looks in a Git project.\n\nThis might also be a good place to ask about a style guide for your code.\nI've done my best to be consistent with surrounding code, but it would be\nhelpful to have something more concrete, maybe even someone's .vimrc if\nthat's available.\n\n> I wonder if it would be possible to overload \"operator /\" for the\nutils::Duration type\nGives an error: multiple definitions.\n> Or, if that can't be done for the Duration type only, somehow override\nthe std::chrono::duration::operator/() globally\nIn global namespace: compiler error\nIn the class itself: read on\n\nMy power is out but I’ll follow up with the actual compiler errors sometime\ntomorrow.\n\nI’ve come up with a centralized solution that might work, but it’s not\nideal either. I’d like to get your thoughts here before going further:\n* Make the chrono baseclass private to resolve ambiguity\n* Implement all of the usual operators i.e. +, -, /, * inside the class\n(even friend functions can’t see private base classes, oddly enough)\n\nThis might also involve some template metaprogramming but I’m trying hard\nto do without it.\n\n-Nicholas\n\n\nOn Mon, Oct 24, 2022 at 8:30 AM Laurent Pinchart <\nlaurent.pinchart@ideasonboard.com> wrote:\n\n> On Mon, Oct 24, 2022 at 11:50:53AM +0100, Naushir Patuck via\n> libcamera-devel wrote:\n> > Hi Nicholas,\n> >\n> > Thank you for your patch.\n> >\n> > As you've already noted, this removes much of the niceness of using\n> > std::chrono\n> > types, and impacts code readability.\n> >\n> > I wonder if it would be possible to overload \"operator /\" for the\n> utils::Duration type\n> > to work-around this bug instead? That way majority of the code need not\n> change\n> > and the fix only lives in one place in the codebase making it easier to\n> revert when\n> > the time comes.\n>\n> Or, if that can't be done for the Duration type only, somehow override\n> the std::chrono::duration::operator/() globally, with a version that\n> fixes the bug. I think this change is fairly intrusive, I'd like a more\n> centralized solution that will not require patching every division.\n>\n> > On Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel wrote:\n> >\n> > > From: Nicholas Roth <nicholas@rothemail.net>\n> > >\n> > > ---\n> > >  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n> > >  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n> > >  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n> > >  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n> > >  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n> > >  src/ipa/rkisp1/algorithms/agc.cpp          | 22 ++++++++++++++++++----\n> > >  6 files changed, 60 insertions(+), 17 deletions(-)\n> > >\n> > > diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n> b/src/ipa/ipu3/algorithms/agc.cpp\n> > > index a1a3c38f..80c551bb 100644\n> > > --- a/src/ipa/ipu3/algorithms/agc.cpp\n> > > +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> > > @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n> > >\n> > >         /* Configure the default exposure and gain. */\n> > >         activeState.agc.gain = std::max(minAnalogueGain_,\n> kMinAnalogueGain);\n> > > -       activeState.agc.exposure = 10ms /\n> configuration.sensor.lineDuration;\n> > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> > > +       activeState.agc.exposure = ten_millis /\n> > > +               configuration.sensor.lineDuration.get<std::nano>();\n> > >\n> > >         frameCount_ = 0;\n> > >         return 0;\n> > > @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n> > >          *\n> > >          * Push the shutter time up to the maximum first, and only then\n> > >          * increase the gain.\n> > > +        *\n> > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > >          */\n> > > +       double exposureValueDouble = exposureValue.get<std::nano>();\n> > > +       utils::Duration shutterTimeRaw(exposureValueDouble /\n> minAnalogueGain_);\n> > >         utils::Duration shutterTime =\n> > > -               std::clamp<utils::Duration>(exposureValue /\n> minAnalogueGain_,\n> > > +               std::clamp<utils::Duration>(shutterTimeRaw,\n> > >                                             minShutterSpeed_,\n> maxShutterSpeed_);\n> > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> > > +       double stepGain = std::clamp(exposureValueDouble /\n> shutterTimeDouble,\n> > >                                      minAnalogueGain_,\n> maxAnalogueGain_);\n> > >         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n> > >                             << shutterTime << \" and \"\n> > > @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n> > >\n> > >         IPAActiveState &activeState = context.activeState;\n> > >         /* Update the estimated exposure and gain. */\n> > > -       activeState.agc.exposure = shutterTime /\n> configuration.sensor.lineDuration;\n> > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > +       double lineDurationDouble =\n> configuration.sensor.lineDuration.get<std::nano>();\n> > > +       activeState.agc.exposure = shutterTimeDouble /\n> lineDurationDouble;\n> > >         activeState.agc.gain = stepGain;\n> > >  }\n> > >\n> > > diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n> b/src/ipa/raspberrypi/cam_helper.cpp\n> > > index d90ac1de..31a9a1ef 100644\n> > > --- a/src/ipa/raspberrypi/cam_helper.cpp\n> > > +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> > > @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]]\n> StatisticsPtr\n> > > &stats,\n> > >\n> > >  uint32_t CamHelper::exposureLines(const Duration exposure, const\n> Duration\n> > > lineLength) const\n> > >  {\n> > > -       return exposure / lineLength;\n> > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > +       return exposure.get<std::nano>() / lineLength.get<std::nano>();\n> > >  }\n> > >\n> > >  Duration CamHelper::exposure(uint32_t exposureLines, const Duration\n> lineLength) const\n> > > @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t>\n> CamHelper::getBlanking(Duration &exposure,\n> > >          *\n> > >          * frameLengthMax gets calculated on the smallest line length\n> as we do\n> > >          * not want to extend that unless absolutely necessary.\n> > > +        *\n> > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > >          */\n> > > -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> > > -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> > > +       frameLengthMin = minFrameDuration.get<std::nano>() /\n> mode_.minLineLength.get<std::nano>();\n> > > +       frameLengthMax = maxFrameDuration.get<std::nano>() /\n> mode_.minLineLength.get<std::nano>();\n> > >\n> > >         /*\n> > >          * Watch out for (exposureLines + frameIntegrationDiff_)\n> overflowing a\n> > > diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > index ecb845e7..e48f5cf2 100644\n> > > --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode)\n> const\n> > >  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n> > >                                         [[maybe_unused]] const\n> Duration lineLength) const\n> > >  {\n> > > -       return std::max<uint32_t>(minExposureLines, (exposure -\n> 14.26us) / timePerLine);\n> > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > +       double exposureTime = Duration(exposure -\n> 14.26us).get<std::nano>();\n> > > +       double timePerLineNano = timePerLine.get<std::nano>();\n> > > +       return std::max<uint32_t>(minExposureLines, exposureTime /\n> timePerLineNano);\n> > >  }\n> > >\n> > >  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> > > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > index bd54a639..720ba788 100644\n> > > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n> > >                         Duration actualExposure =\n> deviceStatus.shutterSpeed *\n> > >\n>  deviceStatus.analogueGain;\n> > >                         if (actualExposure) {\n> > > -                               status_.digitalGain =\n> status_.totalExposureValue / actualExposure;\n> > > +                               /* TODO(Bug 156): Workaround for LLVM\n> bug.\n> > > */\n> > > +                               double totalExposureDouble =\n> status_.totalExposureValue.get<std::nano>();\n> > > +                               double actualExposureDouble =\n> actualExposure.get<std::nano>();\n> > > +                               status_.digitalGain =\n> totalExposureDouble / actualExposureDouble;\n> > >                                 LOG(RPiAgc, Debug) << \"Want total\n> exposure \" << status_.totalExposureValue;\n> > >                                 /*\n> > >                                  * Never ask for a gain < 1.0, and\n> also impose\n> > > @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n> > >                         }\n> > >                         if (status_.fixedAnalogueGain == 0.0) {\n> > >                                 if (exposureMode_->gain[stage] *\n> shutterTime >= exposureValue) {\n> > > -                                       analogueGain = exposureValue /\n> shutterTime;\n> > > +                                       /* TODO(Bug 156): Workaround\n> for LLVM bug. */\n> > > +                                       double exposureDouble =\n> exposureValue.get<std::nano>();\n> > > +                                       double shutterTimeDouble =\n> shutterTime.get<std::nano>();\n> > > +                                       analogueGain = exposureDouble\n> / shutterTimeDouble;\n> > >                                         break;\n> > >                                 }\n> > >                                 analogueGain =\n> exposureMode_->gain[stage];\n> > > @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n> > >          */\n> > >         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n> > >             status_.flickerPeriod) {\n> > > -               int flickerPeriods = shutterTime /\n> status_.flickerPeriod;\n> > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > +               double shutterTimeDouble =\n> shutterTime.get<std::nano>();\n> > > +               double flickerPeriod =\n> status_.flickerPeriod.get<std::nano>();\n> > > +               int flickerPeriods = shutterTimeDouble / flickerPeriod;\n> > >                 if (flickerPeriods) {\n> > >                         Duration newShutterTime = flickerPeriods *\n> status_.flickerPeriod;\n> > > -                       analogueGain *= shutterTime / newShutterTime;\n> > > +                       double newShutterTimeDouble =\n> newShutterTime.get<std::nano>();\n> > > +                       analogueGain *= shutterTimeDouble /\n> newShutterTimeDouble;\n> > >                         /*\n> > >                          * We should still not allow the ag to go over\n> the\n> > >                          * largest value in the exposure mode. Note\n> that this\n> > > diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > index 9759186a..49303409 100644\n> > > --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata\n> *imageMetadata)\n> > >                 /* add .5 to reflect the mid-points of bins */\n> > >                 double currentY = sum / (double)num + .5;\n> > >                 double gainRatio = referenceGain_ / currentGain;\n> > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > +               double referenceShutterSpeedDouble =\n> referenceShutterSpeed_.get<std::nano>();\n> > > +               double deviceShutterSpeed =\n> deviceStatus.shutterSpeed.get<std::nano>();\n> > >                 double shutterSpeedRatio =\n> > > -                       referenceShutterSpeed_ /\n> deviceStatus.shutterSpeed;\n> > > +                       referenceShutterSpeedDouble /\n> deviceShutterSpeed;\n> > >                 double apertureRatio = referenceAperture_ /\n> currentAperture;\n> > >                 double yRatio = currentY * (65536 / numBins) /\n> referenceY_;\n> > >                 double estimatedLux = shutterSpeedRatio * gainRatio *\n> > > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n> b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > index 04062a36..3ea0b732 100644\n> > > --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> > > +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const\n> IPACameraSensorInfo &configInfo)\n> > >  {\n> > >         /* Configure the default exposure and gain. */\n> > >         context.activeState.agc.gain =\n> std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> > > -       context.activeState.agc.exposure = 10ms /\n> context.configuration.sensor.lineDuration;\n> > > +       /* TODO(Bug 156): Explicit division of ticks (e.g.,\n> `x.get<std::nano>() /\n> > > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround\n> for\n> > > +        * LLVM bug 41130 and should be reverted once we no longer\n> target\n> > > +        * Android 11 / sdk30 since it compromises unit safety and\n> readability. */\n> > > +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> > > +       long double exposure = ten_millis.get<std::nano>() /\n> context.configuration.sensor.lineDuration.get<std::nano>();\n> > > +       context.activeState.agc.exposure = uint32_t(exposure);\n> > >\n> > >         /*\n> > >          * According to the RkISP1 documentation:\n> > > @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n> > >         /*\n> > >          * Push the shutter time up to the maximum first, and only then\n> > >          * increase the gain.\n> > > +        *\n> > > +        * TODO(Bug 156): Explicit division of ticks (e.g.,\n> `x.get<std::nano>() /\n> > > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround\n> for\n> > > +        * LLVM bug 41130 and should be reverted once we no longer\n> target\n> > > +        * Android 11 / sdk30 since it compromises unit safety and\n> readability.\n> > >          */\n> > > -       utils::Duration shutterTime =\n> std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> > > +       utils::Duration\n> shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> > > +       utils::Duration shutterTime =\n> std::clamp<utils::Duration>(shutterTimeUnclamped,\n> > >\n>  minShutterSpeed, maxShutterSpeed);\n> > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > +       double stepGainUnclamped = exposureValue.get<std::nano>() /\n> shutterTime.get<std::nano>();\n> > > +       double stepGain = std::clamp(stepGainUnclamped,\n> > >                                      minAnalogueGain, maxAnalogueGain);\n> > >         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n> > >                               << shutterTime << \" and \"\n> > >                               << stepGain;\n> > >\n> > >         /* Update the estimated exposure and gain. */\n> > > -       activeState.agc.exposure = shutterTime /\n> configuration.sensor.lineDuration;\n> > > +       activeState.agc.exposure =\n> uint32_t(shutterTime.get<std::nano>() /\n> > > +               configuration.sensor.lineDuration.get<std::nano>());\n> > >         activeState.agc.gain = stepGain;\n> > >  }\n> > >\n>\n> --\n> Regards,\n>\n> Laurent Pinchart\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 1BEBABDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 25 Oct 2022 03:15:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2799962F31;\n\tTue, 25 Oct 2022 05:15:51 +0200 (CEST)","from mail-io1-xd29.google.com (mail-io1-xd29.google.com\n\t[IPv6:2607:f8b0:4864:20::d29])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1689761F4B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 25 Oct 2022 05:15:49 +0200 (CEST)","by mail-io1-xd29.google.com with SMTP id b79so9347754iof.5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Oct 2022 20:15:49 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666667751;\n\tbh=kGT/ztbe/g0tXOtP3CPrG5Gf98+ADaOqWPBoMDqysac=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=Nlyjpc5oNrotJcC1ri7QP30rUM08NnvCWwNTLsQCSD7vWf108cxkYuvSy+GUNzipi\n\t7Mh/b6m6uTDoYOcitaXteSAXfYh357RY2J5LcitG9kZtC9jKwrmsmuA2qjBRpwd1YW\n\tD1LWAWQiIsI3MDBwIOGHuHYErUewLKD7/bE3ubzfwATNy1zY/WTuJX2rgaAh5Qbd8N\n\tGieE+jhSP7ybQtbZ3fXo98NeXtPo5DwewmQek+213z7C9buOgoF8C8vRWH8Qtlfvbu\n\tLHe85ZT3mdyb2nBlSp2M8vY0H6o60oVH32rLttRfAytf6gDqnr47t5zw1NdOHy9x7d\n\ttNwzdMsP2bw6A==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=rothemail-net.20210112.gappssmtp.com; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=JtLr9sabVK7FhN1COL2zkCvCzqchvBENIHtiSxGLQqs=;\n\tb=RkmhdVvUJiRzTpjkT9Ozir8+qsoOTg9asVLOPc7Zpqx8mgED9/+/EnjMasoj2MNMPM\n\tnp+9jM3Xs9neAiv85a0f6V5j/cIC6zYmP8U6kgsoR291PIb8jtsrcPymLtnYlr5m9Mz3\n\tZbdSQTYipjte9z1rzGCvFhbo7oJu7Tpg+LB1196Eg1oj6TjxxVoLJLBXs3fBA2s+dyal\n\tR7g70Zv45eFYTTdUYqey2eGluENtZOiqBUickv8Qyz8ffi19cgSM4T0iDNnwX7RPGyes\n\tPKZPeVeMVtHi2QH9p6cMyx0b8u6i4eTDBtZfVGg7KJhdVKftrIeB5SZ1w50vMK7Pxkjc\n\t3nfg=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=rothemail-net.20210112.gappssmtp.com\n\theader.i=@rothemail-net.20210112.gappssmtp.com header.b=\"RkmhdVvU\"; \n\tdkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=JtLr9sabVK7FhN1COL2zkCvCzqchvBENIHtiSxGLQqs=;\n\tb=GopcaGqYdWGJe0FID4lTsdwWwGF4lNBV8IMIKp/NiLt1NqOCtDf57Zr9B3aE/QL8Ie\n\tWPdd3TPywplw9YxOlanz/6hr1XAiQNH+EqEZYeOMmOkx27RLYq+I2aIGY/Nk3J1dlBFL\n\t9sTejQFVNNBs82gWa7NzbN2XSXTAx8i3Rrq7C0m2omWcPdB0a2J+JWP2gGn7zAx/OE0Z\n\t1eFUFzwQK0snDl/2D9tgqY0weWDsodGkESHvC7cRzj4gLJZsiktxAAAYFW9NBZW6kMJh\n\tTFX+wP+DIYyx9f9Hg9/erstmNVBU6XTeQdQZA9nznZ7UXHHTGMZfWqGoMiiSqdY/rBpb\n\tZ3OQ==","X-Gm-Message-State":"ACrzQf0x/g8Y6MMbND947doCT+ads/kGZDsi0BpwsJrDInlHf/1mAr1h\n\ttIFJcFfzgJ5yv5hkcRLfc07zON3MjUCqDs7k8W0VEg==","X-Google-Smtp-Source":"AMsMyM6vPqaAE0YFxii1BoPsdh1KDgMZRFxT0BHKsaNN6jtZHr6fzKoID4JjDsb8LhSYuDiEYX4NsD+yQ8XnkZanVos=","X-Received":"by 2002:a02:9982:0:b0:364:6be:dbd6 with SMTP id\n\ta2-20020a029982000000b0036406bedbd6mr23890081jal.311.1666667747395;\n\tMon, 24 Oct 2022 20:15:47 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>","In-Reply-To":"<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>","Date":"Mon, 24 Oct 2022 22:15:36 -0500","Message-ID":"<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Content-Type":"multipart/alternative; boundary=\"0000000000000add4f05ebd3531c\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Nicholas Roth <nicholas@rothemail.net>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25576,"web_url":"https://patchwork.libcamera.org/comment/25576/","msgid":"<166669644142.2560709.8792080139352113364@Monstersaurus>","date":"2022-10-25T11:14:01","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Nicholas Roth via libcamera-devel (2022-10-25 04:15:36)\n> > Could I ask you to read https://cbea.ms/git-commit/ please?\n> Read. I thought that was quite informative. I noticed some differences\n> between the style suggested in the blog post and the commit messages you\n> suggest. Indeed, I have generally foregone good history in favor of\n\nStyle differences are fine. Content is King. We won't merge patches that\nsay \"Latest code\" or \"fixes foo\". I like to break things down to cover\nthree points, but it doesn't always apply. Capturing rationale is the\nimportant part.\n\n\nprefix: of: components: Clear subject\n\n - What is wrong\n - What this patch does\n - Why it does it (the way it does)\n\nSigned-off-by: <author>\n\n\n\n Subject: ships: argo: Increase sailers on the Argo\n\n The Argo is insuffienctly staffed and incapable of slaying any\n dragons, (or managing any other adventures accordingly).\n\n To avoid mortal peril beyond expectations, staff the Argo with at\n least 50 of the finest Heroes available.\n\n The target of 50 has been reached according to the size of the vessel,\n and the number of beds available for resting during the journey, as\n well as examining the food supplies that are expected to last over the\n extended travel period.\n\n The return Journey may have a reduced staffing level, but this is not\n desired. Staffing levels should be kept as close to the maximum level\n as possible at all times.\n\n Signed-off-by: Jason of Aeson <jason@argonauts.org>\n ---\n diff --git a/ships/argo b/ships/argo\n index c9a40e8788e7..e257b2e257b4 100644\n --- a/ships/argo\n +++ b/ships/argo\n @@ -1 +1 @@\n -staff-level: 0\n +staff-level: 50\n\n\n\nWhy do I have a sudden urge to write an anthology of mythological\nstories in patch form ?\n \n\n> convenience in git projects, and I hope it will be interesting to\n> experience the advantages of clear history and educational to learn how\n> this looks in a Git project.\n\nPlease feel free to look through the commit history of libcamera. We're\nover 4000 commits now, and I would really hope that a vast majority\nwould be considered as good examples of commits. (we do allow some slack\nat times... - justifying a typo is usually quite short :D )\n\n - https://git.libcamera.org/libcamera/libcamera.git/log/\n\nWe mostly come with a background (and continuation) in Linux Kernel\ndevelopment, where keeping this history is cruicial due to the scale of\nthe kernel. It could be argued that it's not crucial to the same level\nat libcamera, but I believe it's good development practice to maintain\nclear commits throughout.\n\nThe commit messages usually come into their own when bisecting failures,\nor looking through git-blame to see /why/ a line of code is the way it\nis.\n\nAh yes, also we expect bisectability - so each commit should compile and\nbe functional as an independent task, while aiming to do one thing per\npatch.\n\n\n> This might also be a good place to ask about a style guide for your code.\n> I've done my best to be consistent with surrounding code, but it would be\n> helpful to have something more concrete, maybe even someone's .vimrc if\n> that's available.\n\nWe have tooling in place to help already.\n - https://git.libcamera.org/libcamera/libcamera.git/tree/utils/hooks/post-commit\n\nTo utilise this hook, install this file with:\n  cp utils/hooks/post-commit .git/hooks/post-commit\n\nThat will run our commit style checks on every commit.\nI prefer doing it as a post-commit so you can still commit with\nfailures. pre-commit is usually too 'harsh'.\n\nBeyond that, we have some documentation on the subject at:\n - https://libcamera.org/contributing.html\nand\n - https://libcamera.org/coding-style.html\n\nBut I'm sure this is always something that needs more work on\ndocumenting, or making it easier to read/find.\n\n\n\n> > I wonder if it would be possible to overload \"operator /\" for the\n> utils::Duration type\n> Gives an error: multiple definitions.\n> > Or, if that can't be done for the Duration type only, somehow override\n> the std::chrono::duration::operator/() globally\n> In global namespace: compiler error\n\nWhat's the compiler error here ?\n\n\n> In the class itself: read on\n> \n> My power is out but I’ll follow up with the actual compiler errors sometime\n> tomorrow.\n> \n> I’ve come up with a centralized solution that might work, but it’s not\n> ideal either. I’d like to get your thoughts here before going further:\n> * Make the chrono baseclass private to resolve ambiguity\n> * Implement all of the usual operators i.e. +, -, /, * inside the class\n> (even friend functions can’t see private base classes, oddly enough)\n> \n> This might also involve some template metaprogramming but I’m trying hard\n> to do without it.\n\nAyee, this sounds like more work ... which is painful. I'd be interested\nto see what the compiler error is for the operator/() is to see if\nthat's a shorter solution.\n\n--\nKieran\n\n\n> \n> -Nicholas\n> \n> \n> On Mon, Oct 24, 2022 at 8:30 AM Laurent Pinchart <\n> laurent.pinchart@ideasonboard.com> wrote:\n> \n> > On Mon, Oct 24, 2022 at 11:50:53AM +0100, Naushir Patuck via\n> > libcamera-devel wrote:\n> > > Hi Nicholas,\n> > >\n> > > Thank you for your patch.\n> > >\n> > > As you've already noted, this removes much of the niceness of using\n> > > std::chrono\n> > > types, and impacts code readability.\n> > >\n> > > I wonder if it would be possible to overload \"operator /\" for the\n> > utils::Duration type\n> > > to work-around this bug instead? That way majority of the code need not\n> > change\n> > > and the fix only lives in one place in the codebase making it easier to\n> > revert when\n> > > the time comes.\n> >\n> > Or, if that can't be done for the Duration type only, somehow override\n> > the std::chrono::duration::operator/() globally, with a version that\n> > fixes the bug. I think this change is fairly intrusive, I'd like a more\n> > centralized solution that will not require patching every division.\n> >\n> > > On Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel wrote:\n> > >\n> > > > From: Nicholas Roth <nicholas@rothemail.net>\n> > > >\n> > > > ---\n> > > >  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n> > > >  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n> > > >  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n> > > >  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n> > > >  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n> > > >  src/ipa/rkisp1/algorithms/agc.cpp          | 22 ++++++++++++++++++----\n> > > >  6 files changed, 60 insertions(+), 17 deletions(-)\n> > > >\n> > > > diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n> > b/src/ipa/ipu3/algorithms/agc.cpp\n> > > > index a1a3c38f..80c551bb 100644\n> > > > --- a/src/ipa/ipu3/algorithms/agc.cpp\n> > > > +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> > > > @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n> > > >\n> > > >         /* Configure the default exposure and gain. */\n> > > >         activeState.agc.gain = std::max(minAnalogueGain_,\n> > kMinAnalogueGain);\n> > > > -       activeState.agc.exposure = 10ms /\n> > configuration.sensor.lineDuration;\n> > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> > > > +       activeState.agc.exposure = ten_millis /\n> > > > +               configuration.sensor.lineDuration.get<std::nano>();\n> > > >\n> > > >         frameCount_ = 0;\n> > > >         return 0;\n> > > > @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext &context,\n> > IPAFrameContext &frameContext,\n> > > >          *\n> > > >          * Push the shutter time up to the maximum first, and only then\n> > > >          * increase the gain.\n> > > > +        *\n> > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > > >          */\n> > > > +       double exposureValueDouble = exposureValue.get<std::nano>();\n> > > > +       utils::Duration shutterTimeRaw(exposureValueDouble /\n> > minAnalogueGain_);\n> > > >         utils::Duration shutterTime =\n> > > > -               std::clamp<utils::Duration>(exposureValue /\n> > minAnalogueGain_,\n> > > > +               std::clamp<utils::Duration>(shutterTimeRaw,\n> > > >                                             minShutterSpeed_,\n> > maxShutterSpeed_);\n> > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > > +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> > > > +       double stepGain = std::clamp(exposureValueDouble /\n> > shutterTimeDouble,\n> > > >                                      minAnalogueGain_,\n> > maxAnalogueGain_);\n> > > >         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n> > > >                             << shutterTime << \" and \"\n> > > > @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context,\n> > IPAFrameContext &frameContext,\n> > > >\n> > > >         IPAActiveState &activeState = context.activeState;\n> > > >         /* Update the estimated exposure and gain. */\n> > > > -       activeState.agc.exposure = shutterTime /\n> > configuration.sensor.lineDuration;\n> > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > +       double lineDurationDouble =\n> > configuration.sensor.lineDuration.get<std::nano>();\n> > > > +       activeState.agc.exposure = shutterTimeDouble /\n> > lineDurationDouble;\n> > > >         activeState.agc.gain = stepGain;\n> > > >  }\n> > > >\n> > > > diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n> > b/src/ipa/raspberrypi/cam_helper.cpp\n> > > > index d90ac1de..31a9a1ef 100644\n> > > > --- a/src/ipa/raspberrypi/cam_helper.cpp\n> > > > +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> > > > @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]]\n> > StatisticsPtr\n> > > > &stats,\n> > > >\n> > > >  uint32_t CamHelper::exposureLines(const Duration exposure, const\n> > Duration\n> > > > lineLength) const\n> > > >  {\n> > > > -       return exposure / lineLength;\n> > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > +       return exposure.get<std::nano>() / lineLength.get<std::nano>();\n> > > >  }\n> > > >\n> > > >  Duration CamHelper::exposure(uint32_t exposureLines, const Duration\n> > lineLength) const\n> > > > @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t>\n> > CamHelper::getBlanking(Duration &exposure,\n> > > >          *\n> > > >          * frameLengthMax gets calculated on the smallest line length\n> > as we do\n> > > >          * not want to extend that unless absolutely necessary.\n> > > > +        *\n> > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > > >          */\n> > > > -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> > > > -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> > > > +       frameLengthMin = minFrameDuration.get<std::nano>() /\n> > mode_.minLineLength.get<std::nano>();\n> > > > +       frameLengthMax = maxFrameDuration.get<std::nano>() /\n> > mode_.minLineLength.get<std::nano>();\n> > > >\n> > > >         /*\n> > > >          * Watch out for (exposureLines + frameIntegrationDiff_)\n> > overflowing a\n> > > > diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > index ecb845e7..e48f5cf2 100644\n> > > > --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode)\n> > const\n> > > >  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n> > > >                                         [[maybe_unused]] const\n> > Duration lineLength) const\n> > > >  {\n> > > > -       return std::max<uint32_t>(minExposureLines, (exposure -\n> > 14.26us) / timePerLine);\n> > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > +       double exposureTime = Duration(exposure -\n> > 14.26us).get<std::nano>();\n> > > > +       double timePerLineNano = timePerLine.get<std::nano>();\n> > > > +       return std::max<uint32_t>(minExposureLines, exposureTime /\n> > timePerLineNano);\n> > > >  }\n> > > >\n> > > >  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> > > > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > index bd54a639..720ba788 100644\n> > > > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n> > > >                         Duration actualExposure =\n> > deviceStatus.shutterSpeed *\n> > > >\n> >  deviceStatus.analogueGain;\n> > > >                         if (actualExposure) {\n> > > > -                               status_.digitalGain =\n> > status_.totalExposureValue / actualExposure;\n> > > > +                               /* TODO(Bug 156): Workaround for LLVM\n> > bug.\n> > > > */\n> > > > +                               double totalExposureDouble =\n> > status_.totalExposureValue.get<std::nano>();\n> > > > +                               double actualExposureDouble =\n> > actualExposure.get<std::nano>();\n> > > > +                               status_.digitalGain =\n> > totalExposureDouble / actualExposureDouble;\n> > > >                                 LOG(RPiAgc, Debug) << \"Want total\n> > exposure \" << status_.totalExposureValue;\n> > > >                                 /*\n> > > >                                  * Never ask for a gain < 1.0, and\n> > also impose\n> > > > @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n> > > >                         }\n> > > >                         if (status_.fixedAnalogueGain == 0.0) {\n> > > >                                 if (exposureMode_->gain[stage] *\n> > shutterTime >= exposureValue) {\n> > > > -                                       analogueGain = exposureValue /\n> > shutterTime;\n> > > > +                                       /* TODO(Bug 156): Workaround\n> > for LLVM bug. */\n> > > > +                                       double exposureDouble =\n> > exposureValue.get<std::nano>();\n> > > > +                                       double shutterTimeDouble =\n> > shutterTime.get<std::nano>();\n> > > > +                                       analogueGain = exposureDouble\n> > / shutterTimeDouble;\n> > > >                                         break;\n> > > >                                 }\n> > > >                                 analogueGain =\n> > exposureMode_->gain[stage];\n> > > > @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n> > > >          */\n> > > >         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n> > > >             status_.flickerPeriod) {\n> > > > -               int flickerPeriods = shutterTime /\n> > status_.flickerPeriod;\n> > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > +               double shutterTimeDouble =\n> > shutterTime.get<std::nano>();\n> > > > +               double flickerPeriod =\n> > status_.flickerPeriod.get<std::nano>();\n> > > > +               int flickerPeriods = shutterTimeDouble / flickerPeriod;\n> > > >                 if (flickerPeriods) {\n> > > >                         Duration newShutterTime = flickerPeriods *\n> > status_.flickerPeriod;\n> > > > -                       analogueGain *= shutterTime / newShutterTime;\n> > > > +                       double newShutterTimeDouble =\n> > newShutterTime.get<std::nano>();\n> > > > +                       analogueGain *= shutterTimeDouble /\n> > newShutterTimeDouble;\n> > > >                         /*\n> > > >                          * We should still not allow the ag to go over\n> > the\n> > > >                          * largest value in the exposure mode. Note\n> > that this\n> > > > diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > index 9759186a..49303409 100644\n> > > > --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata\n> > *imageMetadata)\n> > > >                 /* add .5 to reflect the mid-points of bins */\n> > > >                 double currentY = sum / (double)num + .5;\n> > > >                 double gainRatio = referenceGain_ / currentGain;\n> > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > +               double referenceShutterSpeedDouble =\n> > referenceShutterSpeed_.get<std::nano>();\n> > > > +               double deviceShutterSpeed =\n> > deviceStatus.shutterSpeed.get<std::nano>();\n> > > >                 double shutterSpeedRatio =\n> > > > -                       referenceShutterSpeed_ /\n> > deviceStatus.shutterSpeed;\n> > > > +                       referenceShutterSpeedDouble /\n> > deviceShutterSpeed;\n> > > >                 double apertureRatio = referenceAperture_ /\n> > currentAperture;\n> > > >                 double yRatio = currentY * (65536 / numBins) /\n> > referenceY_;\n> > > >                 double estimatedLux = shutterSpeedRatio * gainRatio *\n> > > > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n> > b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > index 04062a36..3ea0b732 100644\n> > > > --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const\n> > IPACameraSensorInfo &configInfo)\n> > > >  {\n> > > >         /* Configure the default exposure and gain. */\n> > > >         context.activeState.agc.gain =\n> > std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> > > > -       context.activeState.agc.exposure = 10ms /\n> > context.configuration.sensor.lineDuration;\n> > > > +       /* TODO(Bug 156): Explicit division of ticks (e.g.,\n> > `x.get<std::nano>() /\n> > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround\n> > for\n> > > > +        * LLVM bug 41130 and should be reverted once we no longer\n> > target\n> > > > +        * Android 11 / sdk30 since it compromises unit safety and\n> > readability. */\n> > > > +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> > > > +       long double exposure = ten_millis.get<std::nano>() /\n> > context.configuration.sensor.lineDuration.get<std::nano>();\n> > > > +       context.activeState.agc.exposure = uint32_t(exposure);\n> > > >\n> > > >         /*\n> > > >          * According to the RkISP1 documentation:\n> > > > @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext &context,\n> > IPAFrameContext &frameContext,\n> > > >         /*\n> > > >          * Push the shutter time up to the maximum first, and only then\n> > > >          * increase the gain.\n> > > > +        *\n> > > > +        * TODO(Bug 156): Explicit division of ticks (e.g.,\n> > `x.get<std::nano>() /\n> > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a workaround\n> > for\n> > > > +        * LLVM bug 41130 and should be reverted once we no longer\n> > target\n> > > > +        * Android 11 / sdk30 since it compromises unit safety and\n> > readability.\n> > > >          */\n> > > > -       utils::Duration shutterTime =\n> > std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> > > > +       utils::Duration\n> > shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> > > > +       utils::Duration shutterTime =\n> > std::clamp<utils::Duration>(shutterTimeUnclamped,\n> > > >\n> >  minShutterSpeed, maxShutterSpeed);\n> > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > > +       double stepGainUnclamped = exposureValue.get<std::nano>() /\n> > shutterTime.get<std::nano>();\n> > > > +       double stepGain = std::clamp(stepGainUnclamped,\n> > > >                                      minAnalogueGain, maxAnalogueGain);\n> > > >         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n> > > >                               << shutterTime << \" and \"\n> > > >                               << stepGain;\n> > > >\n> > > >         /* Update the estimated exposure and gain. */\n> > > > -       activeState.agc.exposure = shutterTime /\n> > configuration.sensor.lineDuration;\n> > > > +       activeState.agc.exposure =\n> > uint32_t(shutterTime.get<std::nano>() /\n> > > > +               configuration.sensor.lineDuration.get<std::nano>());\n> > > >         activeState.agc.gain = stepGain;\n> > > >  }\n> > > >\n> >\n> > --\n> > Regards,\n> >\n> > Laurent Pinchart\n> >\n> -- \n> *Nicholas Roth*\n> *Software Engineer, Machine Learning*\n> *Google <https://www.google.com/> *\n> C: (512) 944-0747\n> \n> *This footer provides context about my professional background. I am not\n> acting on behalf of Google. My words and opinions are my own, and not those\n> of Google.*","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 A6445BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 25 Oct 2022 11:14:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5C92362F3B;\n\tTue, 25 Oct 2022 13:14:06 +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 A84E361F4C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 25 Oct 2022 13:14:04 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4FA548BF;\n\tTue, 25 Oct 2022 13:14:04 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666696446;\n\tbh=h0OOeqyqrmi+/8abnXIQhG9Lvmd4vGZOg5IAepC5chU=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=sCV5BmRBlHbOeESHxfOgnwKqzLCFeB7BkxsnwDzPGtyX4reMT3k8hwDnwpmoje4BJ\n\tD76DpnRulasbb63aH28a7uFezqvZO7IZLqgdGA2vbpw0Cfe4YoWCS6NC2N2t/WEUfV\n\t3dqGUnqoPllaLYpg+ixXK3Hipal8+lVdzzEMFjuQren7zxiW8s7zn+VmJP9KyfTuVl\n\tqaG5hcx/E+Zv4Z/dlDbWyzqE3wGM5yas9SH+Tv+ywXArQchtznEf1lp+3y9rfN2rKD\n\tuZYvkLrUPRGxfuDnPc4C6ZEzytOG6dLQ2yhYMstI9kPLrgNbBhxLL+/heltpkBsRId\n\tdAq6Lpy9eQyUg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666696444;\n\tbh=h0OOeqyqrmi+/8abnXIQhG9Lvmd4vGZOg5IAepC5chU=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=VucVj86QnueDyADskChiIb68K+j3m/rO6yb8aF2dkbpaJ2HtVm7Xr8va5isimXChE\n\tmp+wLXcPjVq9n+LFuz+UmuTKamFYvIDpTXqPmPmnGbQX5gbiWeet44YWWSZK1P01AK\n\tvpvIow7Jx61efCAY2SrHun0aJrf9X/t8OhRJ2F8A="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"VucVj86Q\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tNicholas Roth <nicholas@rothemail.net>, Nicholas Roth via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Date":"Tue, 25 Oct 2022 12:14:01 +0100","Message-ID":"<166669644142.2560709.8792080139352113364@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@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":25582,"web_url":"https://patchwork.libcamera.org/comment/25582/","msgid":"<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>","date":"2022-10-26T01:50:34","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":137,"url":"https://patchwork.libcamera.org/api/people/137/","name":"Nicholas Roth","email":"nicholas@rothemail.net"},"content":"Another possible fix is to cast libcamera::utils::Duration to\nstd::chrono::duration before performing division. I've tested that and it\nworks. Would folks be amenable to that instead?\n\n> Ayee, this sounds like more work ... which is painful.\nYep\n\n> What's the compiler error here?\n\nEnable public inheritance of std::chrono::duration and override operator/\nin the class:\n/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1273:81:\nerror: no type named 'type' in 'std::__1::common_type<double,\nlibcamera::utils::Duration>'\n                          typename common_type<typename _Duration::rep,\n_Rep2>::type>::value>\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~\n/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1286:7:\nnote: in instantiation of default argument for\n'__duration_divide_imp<std::__1::chrono::duration<double,\nstd::__1::ratio<1, 1000000000> >, libcamera::utils::Duration>' required here\n    : __duration_divide_imp<duration<_Rep1, _Period>, _Rep2>\n      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1293:10:\nnote: in instantiation of template class\n'std::__1::chrono::__duration_divide_result<std::__1::chrono::duration<double,\nstd::__1::ratio<1, 1000000000> >, libcamera::utils::Duration, false>'\nrequested here\ntypename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type\n         ^\n../src/ipa/raspberrypi/cam_helper.cpp:136:39: note: while substituting\ndeduced template arguments into function template 'operator/' [with _Rep1 =\ndouble, _Period = std::__1::ratio<1, 1000000000>, _Rep2 =\nlibcamera::utils::Duration]\n        return (lineLength * mode_.pixelRate / Duration(1.0s)) -\nmode_.width;\n                                             ^\n1 error generated.\n\nEnable public inheritance of std::chrono::duration and override operator/\nat the namespace level:\nld.lld: error: duplicate symbol:\nlibcamera::operator/(libcamera::utils::Duration const&,\nlibcamera::utils::Duration const&)\n>>> defined at chrono:1068\n(/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n>>>\n src/libcamera/base/libcamera-base.so.0.0.1.p/backtrace.cpp.o:(libcamera::operator/(libcamera::utils::Duration\nconst&, libcamera::utils::Duration const&))\n>>> defined at chrono:1068\n(/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n>>>\n src/libcamera/base/libcamera-base.so.0.0.1.p/unique_fd.cpp.o:(.text._ZN9libcameradvERKNS_5utils8DurationES3_+0x0)\n\nld.lld: error: duplicate symbol:\nlibcamera::operator/(libcamera::utils::Duration const&,\nlibcamera::utils::Duration const&)\n>>> defined at chrono:1068\n(/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n>>>\n src/libcamera/base/libcamera-base.so.0.0.1.p/backtrace.cpp.o:(libcamera::operator/(libcamera::utils::Duration\nconst&, libcamera::utils::Duration const&))\n>>> defined at chrono:1068\n(/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n>>>\n src/libcamera/base/libcamera-base.so.0.0.1.p/utils.cpp.o:(.text._ZN9libcameradvERKNS_5utils8DurationES3_+0x0)\n...\n\nOn Tue, Oct 25, 2022 at 6:14 AM Kieran Bingham <\nkieran.bingham@ideasonboard.com> wrote:\n\n> Quoting Nicholas Roth via libcamera-devel (2022-10-25 04:15:36)\n> > > Could I ask you to read https://cbea.ms/git-commit/ please?\n> > Read. I thought that was quite informative. I noticed some differences\n> > between the style suggested in the blog post and the commit messages you\n> > suggest. Indeed, I have generally foregone good history in favor of\n>\n> Style differences are fine. Content is King. We won't merge patches that\n> say \"Latest code\" or \"fixes foo\". I like to break things down to cover\n> three points, but it doesn't always apply. Capturing rationale is the\n> important part.\n>\n>\n> prefix: of: components: Clear subject\n>\n>  - What is wrong\n>  - What this patch does\n>  - Why it does it (the way it does)\n>\n> Signed-off-by: <author>\n>\n>\n>\n>  Subject: ships: argo: Increase sailers on the Argo\n>\n>  The Argo is insuffienctly staffed and incapable of slaying any\n>  dragons, (or managing any other adventures accordingly).\n>\n>  To avoid mortal peril beyond expectations, staff the Argo with at\n>  least 50 of the finest Heroes available.\n>\n>  The target of 50 has been reached according to the size of the vessel,\n>  and the number of beds available for resting during the journey, as\n>  well as examining the food supplies that are expected to last over the\n>  extended travel period.\n>\n>  The return Journey may have a reduced staffing level, but this is not\n>  desired. Staffing levels should be kept as close to the maximum level\n>  as possible at all times.\n>\n>  Signed-off-by: Jason of Aeson <jason@argonauts.org>\n>  ---\n>  diff --git a/ships/argo b/ships/argo\n>  index c9a40e8788e7..e257b2e257b4 100644\n>  --- a/ships/argo\n>  +++ b/ships/argo\n>  @@ -1 +1 @@\n>  -staff-level: 0\n>  +staff-level: 50\n>\n>\n>\n> Why do I have a sudden urge to write an anthology of mythological\n> stories in patch form ?\n>\n>\n> > convenience in git projects, and I hope it will be interesting to\n> > experience the advantages of clear history and educational to learn how\n> > this looks in a Git project.\n>\n> Please feel free to look through the commit history of libcamera. We're\n> over 4000 commits now, and I would really hope that a vast majority\n> would be considered as good examples of commits. (we do allow some slack\n> at times... - justifying a typo is usually quite short :D )\n>\n>  - https://git.libcamera.org/libcamera/libcamera.git/log/\n>\n> We mostly come with a background (and continuation) in Linux Kernel\n> development, where keeping this history is cruicial due to the scale of\n> the kernel. It could be argued that it's not crucial to the same level\n> at libcamera, but I believe it's good development practice to maintain\n> clear commits throughout.\n>\n> The commit messages usually come into their own when bisecting failures,\n> or looking through git-blame to see /why/ a line of code is the way it\n> is.\n>\n> Ah yes, also we expect bisectability - so each commit should compile and\n> be functional as an independent task, while aiming to do one thing per\n> patch.\n>\n>\n> > This might also be a good place to ask about a style guide for your code.\n> > I've done my best to be consistent with surrounding code, but it would be\n> > helpful to have something more concrete, maybe even someone's .vimrc if\n> > that's available.\n>\n> We have tooling in place to help already.\n>  -\n> https://git.libcamera.org/libcamera/libcamera.git/tree/utils/hooks/post-commit\n>\n> To utilise this hook, install this file with:\n>   cp utils/hooks/post-commit .git/hooks/post-commit\n>\n> That will run our commit style checks on every commit.\n> I prefer doing it as a post-commit so you can still commit with\n> failures. pre-commit is usually too 'harsh'.\n>\n> Beyond that, we have some documentation on the subject at:\n>  - https://libcamera.org/contributing.html\n> and\n>  - https://libcamera.org/coding-style.html\n>\n> But I'm sure this is always something that needs more work on\n> documenting, or making it easier to read/find.\n>\n>\n>\n> > > I wonder if it would be possible to overload \"operator /\" for the\n> > utils::Duration type\n> > Gives an error: multiple definitions.\n> > > Or, if that can't be done for the Duration type only, somehow override\n> > the std::chrono::duration::operator/() globally\n> > In global namespace: compiler error\n>\n> What's the compiler error here ?\n>\n>\n> > In the class itself: read on\n> >\n> > My power is out but I’ll follow up with the actual compiler errors\n> sometime\n> > tomorrow.\n> >\n> > I’ve come up with a centralized solution that might work, but it’s not\n> > ideal either. I’d like to get your thoughts here before going further:\n> > * Make the chrono baseclass private to resolve ambiguity\n> > * Implement all of the usual operators i.e. +, -, /, * inside the class\n> > (even friend functions can’t see private base classes, oddly enough)\n> >\n> > This might also involve some template metaprogramming but I’m trying hard\n> > to do without it.\n>\n> Ayee, this sounds like more work ... which is painful. I'd be interested\n> to see what the compiler error is for the operator/() is to see if\n> that's a shorter solution.\n>\n> --\n> Kieran\n>\n>\n> >\n> > -Nicholas\n> >\n> >\n> > On Mon, Oct 24, 2022 at 8:30 AM Laurent Pinchart <\n> > laurent.pinchart@ideasonboard.com> wrote:\n> >\n> > > On Mon, Oct 24, 2022 at 11:50:53AM +0100, Naushir Patuck via\n> > > libcamera-devel wrote:\n> > > > Hi Nicholas,\n> > > >\n> > > > Thank you for your patch.\n> > > >\n> > > > As you've already noted, this removes much of the niceness of using\n> > > > std::chrono\n> > > > types, and impacts code readability.\n> > > >\n> > > > I wonder if it would be possible to overload \"operator /\" for the\n> > > utils::Duration type\n> > > > to work-around this bug instead? That way majority of the code need\n> not\n> > > change\n> > > > and the fix only lives in one place in the codebase making it easier\n> to\n> > > revert when\n> > > > the time comes.\n> > >\n> > > Or, if that can't be done for the Duration type only, somehow override\n> > > the std::chrono::duration::operator/() globally, with a version that\n> > > fixes the bug. I think this change is fairly intrusive, I'd like a more\n> > > centralized solution that will not require patching every division.\n> > >\n> > > > On Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel\n> wrote:\n> > > >\n> > > > > From: Nicholas Roth <nicholas@rothemail.net>\n> > > > >\n> > > > > ---\n> > > > >  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n> > > > >  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n> > > > >  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n> > > > >  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n> > > > >  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n> > > > >  src/ipa/rkisp1/algorithms/agc.cpp          | 22\n> ++++++++++++++++++----\n> > > > >  6 files changed, 60 insertions(+), 17 deletions(-)\n> > > > >\n> > > > > diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n> > > b/src/ipa/ipu3/algorithms/agc.cpp\n> > > > > index a1a3c38f..80c551bb 100644\n> > > > > --- a/src/ipa/ipu3/algorithms/agc.cpp\n> > > > > +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> > > > > @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n> > > > >\n> > > > >         /* Configure the default exposure and gain. */\n> > > > >         activeState.agc.gain = std::max(minAnalogueGain_,\n> > > kMinAnalogueGain);\n> > > > > -       activeState.agc.exposure = 10ms /\n> > > configuration.sensor.lineDuration;\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> > > > > +       activeState.agc.exposure = ten_millis /\n> > > > > +               configuration.sensor.lineDuration.get<std::nano>();\n> > > > >\n> > > > >         frameCount_ = 0;\n> > > > >         return 0;\n> > > > > @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext\n> &context,\n> > > IPAFrameContext &frameContext,\n> > > > >          *\n> > > > >          * Push the shutter time up to the maximum first, and only\n> then\n> > > > >          * increase the gain.\n> > > > > +        *\n> > > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > > > >          */\n> > > > > +       double exposureValueDouble =\n> exposureValue.get<std::nano>();\n> > > > > +       utils::Duration shutterTimeRaw(exposureValueDouble /\n> > > minAnalogueGain_);\n> > > > >         utils::Duration shutterTime =\n> > > > > -               std::clamp<utils::Duration>(exposureValue /\n> > > minAnalogueGain_,\n> > > > > +               std::clamp<utils::Duration>(shutterTimeRaw,\n> > > > >                                             minShutterSpeed_,\n> > > maxShutterSpeed_);\n> > > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > > > +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> > > > > +       double stepGain = std::clamp(exposureValueDouble /\n> > > shutterTimeDouble,\n> > > > >                                      minAnalogueGain_,\n> > > maxAnalogueGain_);\n> > > > >         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n> > > > >                             << shutterTime << \" and \"\n> > > > > @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context,\n> > > IPAFrameContext &frameContext,\n> > > > >\n> > > > >         IPAActiveState &activeState = context.activeState;\n> > > > >         /* Update the estimated exposure and gain. */\n> > > > > -       activeState.agc.exposure = shutterTime /\n> > > configuration.sensor.lineDuration;\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       double lineDurationDouble =\n> > > configuration.sensor.lineDuration.get<std::nano>();\n> > > > > +       activeState.agc.exposure = shutterTimeDouble /\n> > > lineDurationDouble;\n> > > > >         activeState.agc.gain = stepGain;\n> > > > >  }\n> > > > >\n> > > > > diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n> > > b/src/ipa/raspberrypi/cam_helper.cpp\n> > > > > index d90ac1de..31a9a1ef 100644\n> > > > > --- a/src/ipa/raspberrypi/cam_helper.cpp\n> > > > > +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> > > > > @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]]\n> > > StatisticsPtr\n> > > > > &stats,\n> > > > >\n> > > > >  uint32_t CamHelper::exposureLines(const Duration exposure, const\n> > > Duration\n> > > > > lineLength) const\n> > > > >  {\n> > > > > -       return exposure / lineLength;\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       return exposure.get<std::nano>() /\n> lineLength.get<std::nano>();\n> > > > >  }\n> > > > >\n> > > > >  Duration CamHelper::exposure(uint32_t exposureLines, const\n> Duration\n> > > lineLength) const\n> > > > > @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t>\n> > > CamHelper::getBlanking(Duration &exposure,\n> > > > >          *\n> > > > >          * frameLengthMax gets calculated on the smallest line\n> length\n> > > as we do\n> > > > >          * not want to extend that unless absolutely necessary.\n> > > > > +        *\n> > > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > > > >          */\n> > > > > -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> > > > > -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> > > > > +       frameLengthMin = minFrameDuration.get<std::nano>() /\n> > > mode_.minLineLength.get<std::nano>();\n> > > > > +       frameLengthMax = maxFrameDuration.get<std::nano>() /\n> > > mode_.minLineLength.get<std::nano>();\n> > > > >\n> > > > >         /*\n> > > > >          * Watch out for (exposureLines + frameIntegrationDiff_)\n> > > overflowing a\n> > > > > diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > > index ecb845e7..e48f5cf2 100644\n> > > > > --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > > +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > > @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode)\n> > > const\n> > > > >  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n> > > > >                                         [[maybe_unused]] const\n> > > Duration lineLength) const\n> > > > >  {\n> > > > > -       return std::max<uint32_t>(minExposureLines, (exposure -\n> > > 14.26us) / timePerLine);\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       double exposureTime = Duration(exposure -\n> > > 14.26us).get<std::nano>();\n> > > > > +       double timePerLineNano = timePerLine.get<std::nano>();\n> > > > > +       return std::max<uint32_t>(minExposureLines, exposureTime /\n> > > timePerLineNano);\n> > > > >  }\n> > > > >\n> > > > >  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> > > > > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > > index bd54a639..720ba788 100644\n> > > > > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > > @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n> > > > >                         Duration actualExposure =\n> > > deviceStatus.shutterSpeed *\n> > > > >\n> > >  deviceStatus.analogueGain;\n> > > > >                         if (actualExposure) {\n> > > > > -                               status_.digitalGain =\n> > > status_.totalExposureValue / actualExposure;\n> > > > > +                               /* TODO(Bug 156): Workaround for\n> LLVM\n> > > bug.\n> > > > > */\n> > > > > +                               double totalExposureDouble =\n> > > status_.totalExposureValue.get<std::nano>();\n> > > > > +                               double actualExposureDouble =\n> > > actualExposure.get<std::nano>();\n> > > > > +                               status_.digitalGain =\n> > > totalExposureDouble / actualExposureDouble;\n> > > > >                                 LOG(RPiAgc, Debug) << \"Want total\n> > > exposure \" << status_.totalExposureValue;\n> > > > >                                 /*\n> > > > >                                  * Never ask for a gain < 1.0, and\n> > > also impose\n> > > > > @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n> > > > >                         }\n> > > > >                         if (status_.fixedAnalogueGain == 0.0) {\n> > > > >                                 if (exposureMode_->gain[stage] *\n> > > shutterTime >= exposureValue) {\n> > > > > -                                       analogueGain =\n> exposureValue /\n> > > shutterTime;\n> > > > > +                                       /* TODO(Bug 156):\n> Workaround\n> > > for LLVM bug. */\n> > > > > +                                       double exposureDouble =\n> > > exposureValue.get<std::nano>();\n> > > > > +                                       double shutterTimeDouble =\n> > > shutterTime.get<std::nano>();\n> > > > > +                                       analogueGain =\n> exposureDouble\n> > > / shutterTimeDouble;\n> > > > >                                         break;\n> > > > >                                 }\n> > > > >                                 analogueGain =\n> > > exposureMode_->gain[stage];\n> > > > > @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n> > > > >          */\n> > > > >         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n> > > > >             status_.flickerPeriod) {\n> > > > > -               int flickerPeriods = shutterTime /\n> > > status_.flickerPeriod;\n> > > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +               double shutterTimeDouble =\n> > > shutterTime.get<std::nano>();\n> > > > > +               double flickerPeriod =\n> > > status_.flickerPeriod.get<std::nano>();\n> > > > > +               int flickerPeriods = shutterTimeDouble /\n> flickerPeriod;\n> > > > >                 if (flickerPeriods) {\n> > > > >                         Duration newShutterTime = flickerPeriods *\n> > > status_.flickerPeriod;\n> > > > > -                       analogueGain *= shutterTime /\n> newShutterTime;\n> > > > > +                       double newShutterTimeDouble =\n> > > newShutterTime.get<std::nano>();\n> > > > > +                       analogueGain *= shutterTimeDouble /\n> > > newShutterTimeDouble;\n> > > > >                         /*\n> > > > >                          * We should still not allow the ag to go\n> over\n> > > the\n> > > > >                          * largest value in the exposure mode. Note\n> > > that this\n> > > > > diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > > index 9759186a..49303409 100644\n> > > > > --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > > +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > > @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata\n> > > *imageMetadata)\n> > > > >                 /* add .5 to reflect the mid-points of bins */\n> > > > >                 double currentY = sum / (double)num + .5;\n> > > > >                 double gainRatio = referenceGain_ / currentGain;\n> > > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +               double referenceShutterSpeedDouble =\n> > > referenceShutterSpeed_.get<std::nano>();\n> > > > > +               double deviceShutterSpeed =\n> > > deviceStatus.shutterSpeed.get<std::nano>();\n> > > > >                 double shutterSpeedRatio =\n> > > > > -                       referenceShutterSpeed_ /\n> > > deviceStatus.shutterSpeed;\n> > > > > +                       referenceShutterSpeedDouble /\n> > > deviceShutterSpeed;\n> > > > >                 double apertureRatio = referenceAperture_ /\n> > > currentAperture;\n> > > > >                 double yRatio = currentY * (65536 / numBins) /\n> > > referenceY_;\n> > > > >                 double estimatedLux = shutterSpeedRatio *\n> gainRatio *\n> > > > > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n> > > b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > > index 04062a36..3ea0b732 100644\n> > > > > --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > > +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > > @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const\n> > > IPACameraSensorInfo &configInfo)\n> > > > >  {\n> > > > >         /* Configure the default exposure and gain. */\n> > > > >         context.activeState.agc.gain =\n> > > std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> > > > > -       context.activeState.agc.exposure = 10ms /\n> > > context.configuration.sensor.lineDuration;\n> > > > > +       /* TODO(Bug 156): Explicit division of ticks (e.g.,\n> > > `x.get<std::nano>() /\n> > > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a\n> workaround\n> > > for\n> > > > > +        * LLVM bug 41130 and should be reverted once we no longer\n> > > target\n> > > > > +        * Android 11 / sdk30 since it compromises unit safety and\n> > > readability. */\n> > > > > +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> > > > > +       long double exposure = ten_millis.get<std::nano>() /\n> > > context.configuration.sensor.lineDuration.get<std::nano>();\n> > > > > +       context.activeState.agc.exposure = uint32_t(exposure);\n> > > > >\n> > > > >         /*\n> > > > >          * According to the RkISP1 documentation:\n> > > > > @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext\n> &context,\n> > > IPAFrameContext &frameContext,\n> > > > >         /*\n> > > > >          * Push the shutter time up to the maximum first, and only\n> then\n> > > > >          * increase the gain.\n> > > > > +        *\n> > > > > +        * TODO(Bug 156): Explicit division of ticks (e.g.,\n> > > `x.get<std::nano>() /\n> > > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a\n> workaround\n> > > for\n> > > > > +        * LLVM bug 41130 and should be reverted once we no longer\n> > > target\n> > > > > +        * Android 11 / sdk30 since it compromises unit safety and\n> > > readability.\n> > > > >          */\n> > > > > -       utils::Duration shutterTime =\n> > > std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> > > > > +       utils::Duration\n> > > shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> > > > > +       utils::Duration shutterTime =\n> > > std::clamp<utils::Duration>(shutterTimeUnclamped,\n> > > > >\n> > >  minShutterSpeed, maxShutterSpeed);\n> > > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > > > +       double stepGainUnclamped = exposureValue.get<std::nano>() /\n> > > shutterTime.get<std::nano>();\n> > > > > +       double stepGain = std::clamp(stepGainUnclamped,\n> > > > >                                      minAnalogueGain,\n> maxAnalogueGain);\n> > > > >         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n> > > > >                               << shutterTime << \" and \"\n> > > > >                               << stepGain;\n> > > > >\n> > > > >         /* Update the estimated exposure and gain. */\n> > > > > -       activeState.agc.exposure = shutterTime /\n> > > configuration.sensor.lineDuration;\n> > > > > +       activeState.agc.exposure =\n> > > uint32_t(shutterTime.get<std::nano>() /\n> > > > > +\n>  configuration.sensor.lineDuration.get<std::nano>());\n> > > > >         activeState.agc.gain = stepGain;\n> > > > >  }\n> > > > >\n> > >\n> > > --\n> > > Regards,\n> > >\n> > > Laurent Pinchart\n> > >\n> > --\n> > *Nicholas Roth*\n> > *Software Engineer, Machine Learning*\n> > *Google <https://www.google.com/> *\n> > C: (512) 944-0747\n> >\n> > *This footer provides context about my professional background. I am not\n> > acting on behalf of Google. My words and opinions are my own, and not\n> those\n> > of Google.*\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 39800BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Oct 2022 01:50:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5C40662F40;\n\tWed, 26 Oct 2022 03:50:49 +0200 (CEST)","from mail-il1-x130.google.com (mail-il1-x130.google.com\n\t[IPv6:2607:f8b0:4864:20::130])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 49FDA62EC6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 03:50:47 +0200 (CEST)","by mail-il1-x130.google.com with SMTP id s9so4034054ilu.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 25 Oct 2022 18:50:47 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666749049;\n\tbh=aTjlpZWa+bSR7it0zGyfsyZ/RuZj8YWVWL8pRnzzKTE=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=QqEbO5TxZc3vOri0rnQ8vJCN7GT1VREMNe/sYe93u8ZoEXxbrb5X2YqUdV3ZIuj0A\n\tMyyf8Ac5ZQc22FvwuwUdmnqw2ZN9SJr9bk48MrdZePijFvenZ6DMLsHCMS16nf9tpM\n\tYO61sdxNqs/GZpl0YSodsKjuoWyq6fsHy6EFeAUm693Z6JFhR1UZUp21cxCgrMtlR1\n\tgw4N2Zuojc/LzVZ1D7+58D3bSM4/kQG3t2H7gaSxTtuU/ZPCez9R7HpYYYmrnjBDQa\n\tkFJE6goKkXYUCGvYIA6LgcrqdYNulU8vIOoWVu/j8O4a8DkdLD1IaCvRyUZqke/o4B\n\tLhnuWcHzcvwcw==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=rothemail-net.20210112.gappssmtp.com; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=ikP1DIQ/zzohGD2GJWmRzXeyHY8FWQAqg4FvjHDAo+0=;\n\tb=JVlL4fhMdaaKgkOqSdMmylGQnTsiVDXGa3eTkhp5MEAXKu1s/CT9Hf2Lk53ueY9WLL\n\tQ8bj679yMWmvDuiTY3c72anHVn7LC61o7zSZefg8fgCNCyT9+NBY9GD6Bp6AY/FH4Ho+\n\ty+DOpVnNSqr+qQgjmofPab6pGEgrdkbMwEPK6raFcLPjgGF1ZYZGRsD0x3HBKdNP6lgw\n\t8BcDLFOomWRJYriTJv9pdEDzjMY/KTdHBDKJT2ZLufpuzkDLBlzG4BC6mYZgLzbWxwf+\n\tJYEzBHKexoGpkFD3z4O7fb4zz7sOv1eSZffIcCScpBhxK1bc6Go5GOK4SjO2WakezCkS\n\t36mw=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=rothemail-net.20210112.gappssmtp.com\n\theader.i=@rothemail-net.20210112.gappssmtp.com header.b=\"JVlL4fhM\"; \n\tdkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=ikP1DIQ/zzohGD2GJWmRzXeyHY8FWQAqg4FvjHDAo+0=;\n\tb=VS6/+5hEDEo7XGh5X0ayOPF5b5246jISD+63ayZud5Ex5Cn787eF3mBpUs87AEDNlu\n\tBkB9VtpuBdqAaq6xgTB4mZV8MP/cXaX8wXlwTgZ35J4TAYbV7OwCStYPsUSXWp+8ssN7\n\tmZX6Lx33ljm8zuWH9NLmbhpEFJT8s3pnTCoHAgu0A3d9rZRa2xhsvA6PNGrvmj1b+RBr\n\tvuU9/oryxpnYxWXmx1VgVojWiqxzkcIdHjk8M7Oh4ha7A+Y5mQlNjoNug0JZA7VhWWb1\n\tIf/UKACdvH+sxh5Cb8CLqHZxSel6cvd28qW9PkmA3OIz6PTEAnDEGdkIuSKsI381c3nT\n\tnMrQ==","X-Gm-Message-State":"ACrzQf0tc0b1LHxyk2C1MZp8SyifpSchuWpKKJ1hvNkl+SdI/GZzYaG7\n\tNy2cCbTaYjYBmJHclGeMPR3CpHROsB1QhCMfieLFmA==","X-Google-Smtp-Source":"AMsMyM5urNnFihtoKtjJf+ye8+joo0hmA4M6IyRI7WJUmpPfA+Nvbit8EowO0DILiCeHtIexy5RGz/7VZcjgoDfQc8M=","X-Received":"by 2002:a05:6e02:1545:b0:2ff:6ab3:dab1 with SMTP id\n\tj5-20020a056e02154500b002ff6ab3dab1mr15379663ilu.285.1666749045449;\n\tTue, 25 Oct 2022 18:50:45 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>","In-Reply-To":"<166669644142.2560709.8792080139352113364@Monstersaurus>","Date":"Tue, 25 Oct 2022 20:50:34 -0500","Message-ID":"<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Content-Type":"multipart/alternative; boundary=\"000000000000c8e8df05ebe6404b\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Nicholas Roth <nicholas@rothemail.net>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25588,"web_url":"https://patchwork.libcamera.org/comment/25588/","msgid":"<CAEmqJPpxjko2LurhR1KKto8XrUc1uoROUZRcFVX=oDSvHi0=tA@mail.gmail.com>","date":"2022-10-26T08:01:05","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Nicholas,\n\nOn Wed, 26 Oct 2022 at 02:50, Nicholas Roth via libcamera-devel <\nlibcamera-devel@lists.libcamera.org> wrote:\n\n> Another possible fix is to cast libcamera::utils::Duration to\n> std::chrono::duration before performing division. I've tested that and it\n> works. Would folks be amenable to that instead?\n>\n\n> > Ayee, this sounds like more work ... which is painful.\n> Yep\n>\n> > What's the compiler error here?\n>\n\nIs this the compile error you get from overloading \"operator /()\" in\nutils::Duration?\nIf so, could you possibly share the code snippet of code for this\nimplementation?\n\nThanks,\nNaush\n\n\n\n>\n> Enable public inheritance of std::chrono::duration and override operator/\n> in the class:\n> /media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1273:81:\n> error: no type named 'type' in 'std::__1::common_type<double,\n> libcamera::utils::Duration>'\n>                           typename common_type<typename _Duration::rep,\n> _Rep2>::type>::value>\n>\n> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~\n> /media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1286:7:\n> note: in instantiation of default argument for\n> '__duration_divide_imp<std::__1::chrono::duration<double,\n> std::__1::ratio<1, 1000000000> >, libcamera::utils::Duration>' required here\n>     : __duration_divide_imp<duration<_Rep1, _Period>, _Rep2>\n>       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n> /media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1293:10:\n> note: in instantiation of template class\n> 'std::__1::chrono::__duration_divide_result<std::__1::chrono::duration<double,\n> std::__1::ratio<1, 1000000000> >, libcamera::utils::Duration, false>'\n> requested here\n> typename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type\n>          ^\n> ../src/ipa/raspberrypi/cam_helper.cpp:136:39: note: while substituting\n> deduced template arguments into function template 'operator/' [with _Rep1 =\n> double, _Period = std::__1::ratio<1, 1000000000>, _Rep2 =\n> libcamera::utils::Duration]\n>         return (lineLength * mode_.pixelRate / Duration(1.0s)) -\n> mode_.width;\n>                                              ^\n> 1 error generated.\n>\n> Enable public inheritance of std::chrono::duration and override operator/\n> at the namespace level:\n> ld.lld: error: duplicate symbol:\n> libcamera::operator/(libcamera::utils::Duration const&,\n> libcamera::utils::Duration const&)\n> >>> defined at chrono:1068\n> (/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n> >>>\n>  src/libcamera/base/libcamera-base.so.0.0.1.p/backtrace.cpp.o:(libcamera::operator/(libcamera::utils::Duration\n> const&, libcamera::utils::Duration const&))\n> >>> defined at chrono:1068\n> (/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n> >>>\n>  src/libcamera/base/libcamera-base.so.0.0.1.p/unique_fd.cpp.o:(.text._ZN9libcameradvERKNS_5utils8DurationES3_+0x0)\n>\n> ld.lld: error: duplicate symbol:\n> libcamera::operator/(libcamera::utils::Duration const&,\n> libcamera::utils::Duration const&)\n> >>> defined at chrono:1068\n> (/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n> >>>\n>  src/libcamera/base/libcamera-base.so.0.0.1.p/backtrace.cpp.o:(libcamera::operator/(libcamera::utils::Duration\n> const&, libcamera::utils::Duration const&))\n> >>> defined at chrono:1068\n> (/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1068)\n> >>>\n>  src/libcamera/base/libcamera-base.so.0.0.1.p/utils.cpp.o:(.text._ZN9libcameradvERKNS_5utils8DurationES3_+0x0)\n> ...\n>\n> On Tue, Oct 25, 2022 at 6:14 AM Kieran Bingham <\n> kieran.bingham@ideasonboard.com> wrote:\n>\n>> Quoting Nicholas Roth via libcamera-devel (2022-10-25 04:15:36)\n>> > > Could I ask you to read https://cbea.ms/git-commit/ please?\n>> > Read. I thought that was quite informative. I noticed some differences\n>> > between the style suggested in the blog post and the commit messages you\n>> > suggest. Indeed, I have generally foregone good history in favor of\n>>\n>> Style differences are fine. Content is King. We won't merge patches that\n>> say \"Latest code\" or \"fixes foo\". I like to break things down to cover\n>> three points, but it doesn't always apply. Capturing rationale is the\n>> important part.\n>>\n>>\n>> prefix: of: components: Clear subject\n>>\n>>  - What is wrong\n>>  - What this patch does\n>>  - Why it does it (the way it does)\n>>\n>> Signed-off-by: <author>\n>>\n>>\n>>\n>>  Subject: ships: argo: Increase sailers on the Argo\n>>\n>>  The Argo is insuffienctly staffed and incapable of slaying any\n>>  dragons, (or managing any other adventures accordingly).\n>>\n>>  To avoid mortal peril beyond expectations, staff the Argo with at\n>>  least 50 of the finest Heroes available.\n>>\n>>  The target of 50 has been reached according to the size of the vessel,\n>>  and the number of beds available for resting during the journey, as\n>>  well as examining the food supplies that are expected to last over the\n>>  extended travel period.\n>>\n>>  The return Journey may have a reduced staffing level, but this is not\n>>  desired. Staffing levels should be kept as close to the maximum level\n>>  as possible at all times.\n>>\n>>  Signed-off-by: Jason of Aeson <jason@argonauts.org>\n>>  ---\n>>  diff --git a/ships/argo b/ships/argo\n>>  index c9a40e8788e7..e257b2e257b4 100644\n>>  --- a/ships/argo\n>>  +++ b/ships/argo\n>>  @@ -1 +1 @@\n>>  -staff-level: 0\n>>  +staff-level: 50\n>>\n>>\n>>\n>> Why do I have a sudden urge to write an anthology of mythological\n>> stories in patch form ?\n>>\n>>\n>> > convenience in git projects, and I hope it will be interesting to\n>> > experience the advantages of clear history and educational to learn how\n>> > this looks in a Git project.\n>>\n>> Please feel free to look through the commit history of libcamera. We're\n>> over 4000 commits now, and I would really hope that a vast majority\n>> would be considered as good examples of commits. (we do allow some slack\n>> at times... - justifying a typo is usually quite short :D )\n>>\n>>  - https://git.libcamera.org/libcamera/libcamera.git/log/\n>>\n>> We mostly come with a background (and continuation) in Linux Kernel\n>> development, where keeping this history is cruicial due to the scale of\n>> the kernel. It could be argued that it's not crucial to the same level\n>> at libcamera, but I believe it's good development practice to maintain\n>> clear commits throughout.\n>>\n>> The commit messages usually come into their own when bisecting failures,\n>> or looking through git-blame to see /why/ a line of code is the way it\n>> is.\n>>\n>> Ah yes, also we expect bisectability - so each commit should compile and\n>> be functional as an independent task, while aiming to do one thing per\n>> patch.\n>>\n>>\n>> > This might also be a good place to ask about a style guide for your\n>> code.\n>> > I've done my best to be consistent with surrounding code, but it would\n>> be\n>> > helpful to have something more concrete, maybe even someone's .vimrc if\n>> > that's available.\n>>\n>> We have tooling in place to help already.\n>>  -\n>> https://git.libcamera.org/libcamera/libcamera.git/tree/utils/hooks/post-commit\n>>\n>> To utilise this hook, install this file with:\n>>   cp utils/hooks/post-commit .git/hooks/post-commit\n>>\n>> That will run our commit style checks on every commit.\n>> I prefer doing it as a post-commit so you can still commit with\n>> failures. pre-commit is usually too 'harsh'.\n>>\n>> Beyond that, we have some documentation on the subject at:\n>>  - https://libcamera.org/contributing.html\n>> and\n>>  - https://libcamera.org/coding-style.html\n>>\n>> But I'm sure this is always something that needs more work on\n>> documenting, or making it easier to read/find.\n>>\n>>\n>>\n>> > > I wonder if it would be possible to overload \"operator /\" for the\n>> > utils::Duration type\n>> > Gives an error: multiple definitions.\n>> > > Or, if that can't be done for the Duration type only, somehow override\n>> > the std::chrono::duration::operator/() globally\n>> > In global namespace: compiler error\n>>\n>> What's the compiler error here ?\n>>\n>>\n>> > In the class itself: read on\n>> >\n>> > My power is out but I’ll follow up with the actual compiler errors\n>> sometime\n>> > tomorrow.\n>> >\n>> > I’ve come up with a centralized solution that might work, but it’s not\n>> > ideal either. I’d like to get your thoughts here before going further:\n>> > * Make the chrono baseclass private to resolve ambiguity\n>> > * Implement all of the usual operators i.e. +, -, /, * inside the class\n>> > (even friend functions can’t see private base classes, oddly enough)\n>> >\n>> > This might also involve some template metaprogramming but I’m trying\n>> hard\n>> > to do without it.\n>>\n>> Ayee, this sounds like more work ... which is painful. I'd be interested\n>> to see what the compiler error is for the operator/() is to see if\n>> that's a shorter solution.\n>>\n>> --\n>> Kieran\n>>\n>>\n>> >\n>> > -Nicholas\n>> >\n>> >\n>> > On Mon, Oct 24, 2022 at 8:30 AM Laurent Pinchart <\n>> > laurent.pinchart@ideasonboard.com> wrote:\n>> >\n>> > > On Mon, Oct 24, 2022 at 11:50:53AM +0100, Naushir Patuck via\n>> > > libcamera-devel wrote:\n>> > > > Hi Nicholas,\n>> > > >\n>> > > > Thank you for your patch.\n>> > > >\n>> > > > As you've already noted, this removes much of the niceness of using\n>> > > > std::chrono\n>> > > > types, and impacts code readability.\n>> > > >\n>> > > > I wonder if it would be possible to overload \"operator /\" for the\n>> > > utils::Duration type\n>> > > > to work-around this bug instead? That way majority of the code need\n>> not\n>> > > change\n>> > > > and the fix only lives in one place in the codebase making it\n>> easier to\n>> > > revert when\n>> > > > the time comes.\n>> > >\n>> > > Or, if that can't be done for the Duration type only, somehow override\n>> > > the std::chrono::duration::operator/() globally, with a version that\n>> > > fixes the bug. I think this change is fairly intrusive, I'd like a\n>> more\n>> > > centralized solution that will not require patching every division.\n>> > >\n>> > > > On Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel\n>> wrote:\n>> > > >\n>> > > > > From: Nicholas Roth <nicholas@rothemail.net>\n>> > > > >\n>> > > > > ---\n>> > > > >  src/ipa/ipu3/algorithms/agc.cpp            | 18\n>> ++++++++++++++----\n>> > > > >  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n>> > > > >  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n>> > > > >  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18\n>> ++++++++++++++----\n>> > > > >  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n>> > > > >  src/ipa/rkisp1/algorithms/agc.cpp          | 22\n>> ++++++++++++++++++----\n>> > > > >  6 files changed, 60 insertions(+), 17 deletions(-)\n>> > > > >\n>> > > > > diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n>> > > b/src/ipa/ipu3/algorithms/agc.cpp\n>> > > > > index a1a3c38f..80c551bb 100644\n>> > > > > --- a/src/ipa/ipu3/algorithms/agc.cpp\n>> > > > > +++ b/src/ipa/ipu3/algorithms/agc.cpp\n>> > > > > @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n>> > > > >\n>> > > > >         /* Configure the default exposure and gain. */\n>> > > > >         activeState.agc.gain = std::max(minAnalogueGain_,\n>> > > kMinAnalogueGain);\n>> > > > > -       activeState.agc.exposure = 10ms /\n>> > > configuration.sensor.lineDuration;\n>> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n>> > > > > +       double ten_millis =\n>> utils::Duration(10ms).get<std::nano>();\n>> > > > > +       activeState.agc.exposure = ten_millis /\n>> > > > > +\n>>  configuration.sensor.lineDuration.get<std::nano>();\n>> > > > >\n>> > > > >         frameCount_ = 0;\n>> > > > >         return 0;\n>> > > > > @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext\n>> &context,\n>> > > IPAFrameContext &frameContext,\n>> > > > >          *\n>> > > > >          * Push the shutter time up to the maximum first, and\n>> only then\n>> > > > >          * increase the gain.\n>> > > > > +        *\n>> > > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n>> > > > >          */\n>> > > > > +       double exposureValueDouble =\n>> exposureValue.get<std::nano>();\n>> > > > > +       utils::Duration shutterTimeRaw(exposureValueDouble /\n>> > > minAnalogueGain_);\n>> > > > >         utils::Duration shutterTime =\n>> > > > > -               std::clamp<utils::Duration>(exposureValue /\n>> > > minAnalogueGain_,\n>> > > > > +               std::clamp<utils::Duration>(shutterTimeRaw,\n>> > > > >                                             minShutterSpeed_,\n>> > > maxShutterSpeed_);\n>> > > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n>> > > > > +       double shutterTimeDouble = shutterTime.get<std::nano>();\n>> > > > > +       double stepGain = std::clamp(exposureValueDouble /\n>> > > shutterTimeDouble,\n>> > > > >                                      minAnalogueGain_,\n>> > > maxAnalogueGain_);\n>> > > > >         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n>> > > > >                             << shutterTime << \" and \"\n>> > > > > @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context,\n>> > > IPAFrameContext &frameContext,\n>> > > > >\n>> > > > >         IPAActiveState &activeState = context.activeState;\n>> > > > >         /* Update the estimated exposure and gain. */\n>> > > > > -       activeState.agc.exposure = shutterTime /\n>> > > configuration.sensor.lineDuration;\n>> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n>> > > > > +       double lineDurationDouble =\n>> > > configuration.sensor.lineDuration.get<std::nano>();\n>> > > > > +       activeState.agc.exposure = shutterTimeDouble /\n>> > > lineDurationDouble;\n>> > > > >         activeState.agc.gain = stepGain;\n>> > > > >  }\n>> > > > >\n>> > > > > diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n>> > > b/src/ipa/raspberrypi/cam_helper.cpp\n>> > > > > index d90ac1de..31a9a1ef 100644\n>> > > > > --- a/src/ipa/raspberrypi/cam_helper.cpp\n>> > > > > +++ b/src/ipa/raspberrypi/cam_helper.cpp\n>> > > > > @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]]\n>> > > StatisticsPtr\n>> > > > > &stats,\n>> > > > >\n>> > > > >  uint32_t CamHelper::exposureLines(const Duration exposure, const\n>> > > Duration\n>> > > > > lineLength) const\n>> > > > >  {\n>> > > > > -       return exposure / lineLength;\n>> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n>> > > > > +       return exposure.get<std::nano>() /\n>> lineLength.get<std::nano>();\n>> > > > >  }\n>> > > > >\n>> > > > >  Duration CamHelper::exposure(uint32_t exposureLines, const\n>> Duration\n>> > > lineLength) const\n>> > > > > @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t>\n>> > > CamHelper::getBlanking(Duration &exposure,\n>> > > > >          *\n>> > > > >          * frameLengthMax gets calculated on the smallest line\n>> length\n>> > > as we do\n>> > > > >          * not want to extend that unless absolutely necessary.\n>> > > > > +        *\n>> > > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n>> > > > >          */\n>> > > > > -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n>> > > > > -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n>> > > > > +       frameLengthMin = minFrameDuration.get<std::nano>() /\n>> > > mode_.minLineLength.get<std::nano>();\n>> > > > > +       frameLengthMax = maxFrameDuration.get<std::nano>() /\n>> > > mode_.minLineLength.get<std::nano>();\n>> > > > >\n>> > > > >         /*\n>> > > > >          * Watch out for (exposureLines + frameIntegrationDiff_)\n>> > > overflowing a\n>> > > > > diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> > > b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> > > > > index ecb845e7..e48f5cf2 100644\n>> > > > > --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> > > > > +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> > > > > @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode)\n>> > > const\n>> > > > >  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n>> > > > >                                         [[maybe_unused]] const\n>> > > Duration lineLength) const\n>> > > > >  {\n>> > > > > -       return std::max<uint32_t>(minExposureLines, (exposure -\n>> > > 14.26us) / timePerLine);\n>> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n>> > > > > +       double exposureTime = Duration(exposure -\n>> > > 14.26us).get<std::nano>();\n>> > > > > +       double timePerLineNano = timePerLine.get<std::nano>();\n>> > > > > +       return std::max<uint32_t>(minExposureLines, exposureTime /\n>> > > timePerLineNano);\n>> > > > >  }\n>> > > > >\n>> > > > >  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n>> > > > > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> > > b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> > > > > index bd54a639..720ba788 100644\n>> > > > > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> > > > > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> > > > > @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n>> > > > >                         Duration actualExposure =\n>> > > deviceStatus.shutterSpeed *\n>> > > > >\n>> > >  deviceStatus.analogueGain;\n>> > > > >                         if (actualExposure) {\n>> > > > > -                               status_.digitalGain =\n>> > > status_.totalExposureValue / actualExposure;\n>> > > > > +                               /* TODO(Bug 156): Workaround for\n>> LLVM\n>> > > bug.\n>> > > > > */\n>> > > > > +                               double totalExposureDouble =\n>> > > status_.totalExposureValue.get<std::nano>();\n>> > > > > +                               double actualExposureDouble =\n>> > > actualExposure.get<std::nano>();\n>> > > > > +                               status_.digitalGain =\n>> > > totalExposureDouble / actualExposureDouble;\n>> > > > >                                 LOG(RPiAgc, Debug) << \"Want total\n>> > > exposure \" << status_.totalExposureValue;\n>> > > > >                                 /*\n>> > > > >                                  * Never ask for a gain < 1.0, and\n>> > > also impose\n>> > > > > @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n>> > > > >                         }\n>> > > > >                         if (status_.fixedAnalogueGain == 0.0) {\n>> > > > >                                 if (exposureMode_->gain[stage] *\n>> > > shutterTime >= exposureValue) {\n>> > > > > -                                       analogueGain =\n>> exposureValue /\n>> > > shutterTime;\n>> > > > > +                                       /* TODO(Bug 156):\n>> Workaround\n>> > > for LLVM bug. */\n>> > > > > +                                       double exposureDouble =\n>> > > exposureValue.get<std::nano>();\n>> > > > > +                                       double shutterTimeDouble =\n>> > > shutterTime.get<std::nano>();\n>> > > > > +                                       analogueGain =\n>> exposureDouble\n>> > > / shutterTimeDouble;\n>> > > > >                                         break;\n>> > > > >                                 }\n>> > > > >                                 analogueGain =\n>> > > exposureMode_->gain[stage];\n>> > > > > @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n>> > > > >          */\n>> > > > >         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n>> > > > >             status_.flickerPeriod) {\n>> > > > > -               int flickerPeriods = shutterTime /\n>> > > status_.flickerPeriod;\n>> > > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n>> > > > > +               double shutterTimeDouble =\n>> > > shutterTime.get<std::nano>();\n>> > > > > +               double flickerPeriod =\n>> > > status_.flickerPeriod.get<std::nano>();\n>> > > > > +               int flickerPeriods = shutterTimeDouble /\n>> flickerPeriod;\n>> > > > >                 if (flickerPeriods) {\n>> > > > >                         Duration newShutterTime = flickerPeriods *\n>> > > status_.flickerPeriod;\n>> > > > > -                       analogueGain *= shutterTime /\n>> newShutterTime;\n>> > > > > +                       double newShutterTimeDouble =\n>> > > newShutterTime.get<std::nano>();\n>> > > > > +                       analogueGain *= shutterTimeDouble /\n>> > > newShutterTimeDouble;\n>> > > > >                         /*\n>> > > > >                          * We should still not allow the ag to go\n>> over\n>> > > the\n>> > > > >                          * largest value in the exposure mode.\n>> Note\n>> > > that this\n>> > > > > diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> > > b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> > > > > index 9759186a..49303409 100644\n>> > > > > --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> > > > > +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> > > > > @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats,\n>> Metadata\n>> > > *imageMetadata)\n>> > > > >                 /* add .5 to reflect the mid-points of bins */\n>> > > > >                 double currentY = sum / (double)num + .5;\n>> > > > >                 double gainRatio = referenceGain_ / currentGain;\n>> > > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n>> > > > > +               double referenceShutterSpeedDouble =\n>> > > referenceShutterSpeed_.get<std::nano>();\n>> > > > > +               double deviceShutterSpeed =\n>> > > deviceStatus.shutterSpeed.get<std::nano>();\n>> > > > >                 double shutterSpeedRatio =\n>> > > > > -                       referenceShutterSpeed_ /\n>> > > deviceStatus.shutterSpeed;\n>> > > > > +                       referenceShutterSpeedDouble /\n>> > > deviceShutterSpeed;\n>> > > > >                 double apertureRatio = referenceAperture_ /\n>> > > currentAperture;\n>> > > > >                 double yRatio = currentY * (65536 / numBins) /\n>> > > referenceY_;\n>> > > > >                 double estimatedLux = shutterSpeedRatio *\n>> gainRatio *\n>> > > > > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n>> > > b/src/ipa/rkisp1/algorithms/agc.cpp\n>> > > > > index 04062a36..3ea0b732 100644\n>> > > > > --- a/src/ipa/rkisp1/algorithms/agc.cpp\n>> > > > > +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n>> > > > > @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const\n>> > > IPACameraSensorInfo &configInfo)\n>> > > > >  {\n>> > > > >         /* Configure the default exposure and gain. */\n>> > > > >         context.activeState.agc.gain =\n>> > > std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n>> > > > > -       context.activeState.agc.exposure = 10ms /\n>> > > context.configuration.sensor.lineDuration;\n>> > > > > +       /* TODO(Bug 156): Explicit division of ticks (e.g.,\n>> > > `x.get<std::nano>() /\n>> > > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a\n>> workaround\n>> > > for\n>> > > > > +        * LLVM bug 41130 and should be reverted once we no longer\n>> > > target\n>> > > > > +        * Android 11 / sdk30 since it compromises unit safety and\n>> > > readability. */\n>> > > > > +       constexpr libcamera::utils::Duration ten_millis(10ms);\n>> > > > > +       long double exposure = ten_millis.get<std::nano>() /\n>> > > context.configuration.sensor.lineDuration.get<std::nano>();\n>> > > > > +       context.activeState.agc.exposure = uint32_t(exposure);\n>> > > > >\n>> > > > >         /*\n>> > > > >          * According to the RkISP1 documentation:\n>> > > > > @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext\n>> &context,\n>> > > IPAFrameContext &frameContext,\n>> > > > >         /*\n>> > > > >          * Push the shutter time up to the maximum first, and\n>> only then\n>> > > > >          * increase the gain.\n>> > > > > +        *\n>> > > > > +        * TODO(Bug 156): Explicit division of ticks (e.g.,\n>> > > `x.get<std::nano>() /\n>> > > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a\n>> workaround\n>> > > for\n>> > > > > +        * LLVM bug 41130 and should be reverted once we no longer\n>> > > target\n>> > > > > +        * Android 11 / sdk30 since it compromises unit safety and\n>> > > readability.\n>> > > > >          */\n>> > > > > -       utils::Duration shutterTime =\n>> > > std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n>> > > > > +       utils::Duration\n>> > > shutterTimeUnclamped(exposureValue.get<std::nano>() /\n>> minAnalogueGain);\n>> > > > > +       utils::Duration shutterTime =\n>> > > std::clamp<utils::Duration>(shutterTimeUnclamped,\n>> > > > >\n>> > >  minShutterSpeed, maxShutterSpeed);\n>> > > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n>> > > > > +       double stepGainUnclamped = exposureValue.get<std::nano>()\n>> /\n>> > > shutterTime.get<std::nano>();\n>> > > > > +       double stepGain = std::clamp(stepGainUnclamped,\n>> > > > >                                      minAnalogueGain,\n>> maxAnalogueGain);\n>> > > > >         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are\n>> \"\n>> > > > >                               << shutterTime << \" and \"\n>> > > > >                               << stepGain;\n>> > > > >\n>> > > > >         /* Update the estimated exposure and gain. */\n>> > > > > -       activeState.agc.exposure = shutterTime /\n>> > > configuration.sensor.lineDuration;\n>> > > > > +       activeState.agc.exposure =\n>> > > uint32_t(shutterTime.get<std::nano>() /\n>> > > > > +\n>>  configuration.sensor.lineDuration.get<std::nano>());\n>> > > > >         activeState.agc.gain = stepGain;\n>> > > > >  }\n>> > > > >\n>> > >\n>> > > --\n>> > > Regards,\n>> > >\n>> > > Laurent Pinchart\n>> > >\n>> > --\n>> > *Nicholas Roth*\n>> > *Software Engineer, Machine Learning*\n>> > *Google <https://www.google.com/> *\n>> > C: (512) 944-0747\n>> >\n>> > *This footer provides context about my professional background. I am not\n>> > acting on behalf of Google. My words and opinions are my own, and not\n>> those\n>> > of Google.*\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 668B3BDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Oct 2022 08:01:26 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 57A4662F4B;\n\tWed, 26 Oct 2022 10:01:25 +0200 (CEST)","from mail-qv1-xf2f.google.com (mail-qv1-xf2f.google.com\n\t[IPv6:2607:f8b0:4864:20::f2f])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D489562ED0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 10:01:22 +0200 (CEST)","by mail-qv1-xf2f.google.com with SMTP id e15so10705398qvo.4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 01:01:22 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666771285;\n\tbh=44Q210btbR5cwNm7uAUythU+CZw8xH/KltEgv7IxguE=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=bW73u0yBquqvuInJZ1x096cDJfOND0syv7hzh+WgMSafVPYXQFjtqhj0QRDMAPrmm\n\tI8DCsUjoTJsN0MCEwaWBPcZyWm6ZnLxDOyWbm/lEO6W00j9CB75GMV8+zsmMt6zWEd\n\t6NSCBwXMDipJuhZ/0Omx/mmlb3s2AJn9fDA85wixRM38gFaEgspqvZ3+b4+ItupGfB\n\tab2GjYiedc5MtyD1t503qKNRXoqTzeKXaWnLMS0A0IU9/aMvojosdUzIjuIJr6RdJa\n\t+o2WWls8iMdq0T/vYK1BNFTmowNUjH8+79kkbZ6jptVQeJFHg6W6eOKpoNU62HYWsJ\n\trsgaVX4ZQ7Mfg==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=5YQ+lqj7vNPUcKYPZqPHXTWuUQKcRcGJaMhYwvHjkTI=;\n\tb=HcQvgpbRxLENkmhEREBy7Kju+mo5MuDFriH6upclDJ73D1JMQLXKW05fN9WLfJ+YE6\n\tOUSZa5BAgODyDH9+EYjSbiK/Ve0sCT1DOEkfZEYepb4a+ygUPrsM+vsn2MgDkI3JP1gw\n\tfXKeOnS+KUkfUJj4m286rsIQp0zFW3QSW5IISj3gUSxcjtw6Nh9dNDaKRktFj8Q73JCS\n\tVdInUsl7DjnfcO/tlfklYqJ4o6RtQrwHJmbXf7QReHoIjgvtYhQo3q4P78gL6Xya2Vow\n\t5DUQcOE6ups5pASK0OAJwZIsBJAYGz/Hh4+w/GWR2H1nEXud9qOn6xND4Al0yTCA4+OS\n\t/efw=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"HcQvgpbR\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=5YQ+lqj7vNPUcKYPZqPHXTWuUQKcRcGJaMhYwvHjkTI=;\n\tb=mvDijwP967Ic+y4XJnINnH5V3vQLXCj9FvwZS/AVBwn3jeOaj55zILOsHS7sP+gqUO\n\tOulC9rulC1bLf0nVYpIZlmyqmUIYlXZzO309p7GNNeUX42CDP56UeSJZstWIWCoN4emN\n\tLD6M7kP86SEF3A1jNqXbamtU5CYBUw5TpjDt74rJ+F5MpPVxrCvg3zhaKRKsBZ/OQpeh\n\tMSJbb7zsvA/MqrfuwOfvhKfkGGRriTC4T8mR9etptXWxHKeedlCbTD5/rI+I4YoSI7Kg\n\tatbc4oHzHTAvvhqYYbB8dXGnif/zfNRMopaSKSozx6wmIfbd+1d/y5qZ65KvtJkgwCG/\n\twOnA==","X-Gm-Message-State":"ACrzQf2bCMTCNQZcT9RphwvsZ2FnFpfbBRdgiyj9Ui1vyPfG7GkvmwhD\n\tTygkZvjKkoEsF16um0PpqeNN/S1s0QGze6uZV9AbXef2NIg=","X-Google-Smtp-Source":"AMsMyM7PcVy8PJVJv3ViaMHjmI2Ey0Ecn/TtRj3p5HFODLbRQtdVWWxgA+qzesbN7zwZkYL8Uq/7Es2vC+6IokB+HpA=","X-Received":"by 2002:a05:6214:d87:b0:4bb:942b:f5f9 with SMTP id\n\te7-20020a0562140d8700b004bb942bf5f9mr1692839qve.126.1666771281540;\n\tWed, 26 Oct 2022 01:01:21 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>","In-Reply-To":"<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>","Date":"Wed, 26 Oct 2022 09:01:05 +0100","Message-ID":"<CAEmqJPpxjko2LurhR1KKto8XrUc1uoROUZRcFVX=oDSvHi0=tA@mail.gmail.com>","To":"Nicholas Roth <nicholas@rothemail.net>","Content-Type":"multipart/alternative; boundary=\"000000000000288c5005ebeb6e87\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Naushir Patuck via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Naushir Patuck <naush@raspberrypi.com>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25589,"web_url":"https://patchwork.libcamera.org/comment/25589/","msgid":"<166677268158.3974115.15111815458042537047@Monstersaurus>","date":"2022-10-26T08:24:41","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Nicholas Roth (2022-10-26 02:50:34)\n> Another possible fix is to cast libcamera::utils::Duration to\n> std::chrono::duration before performing division. I've tested that and it\n> works. Would folks be amenable to that instead?\n\nThat sounds like we still have to make global updates. Are any of those\nlocations where we should store a libcamera::utils::Duration instead of\na std::chrono::duration to prevent having to cast?\n\nIf casting works around the issue, is it sufficient / possible to\nprovide an explicit casting operator? (I've never done this to more than\nthe POD types, but it 'looks' like you can specify specific target\nclasses as an operator?)\n\n  https://en.cppreference.com/w/cpp/language/cast_operator\n\nSomething like (I have no idea if this is something that can work, or if\nit helps the compiler as it should already know the type?!)...:\n\nclass Duration : public std::chrono::duration<double, std::nano>\n{\n...\n\n\texplicit operator std::chrono::duration() {\n\t\treturn std::chrono::duration_cast<BaseDuration>>(*this);\n\t}\n\nor perhaps 'worse' ? (but at least isolated to here in the class?)...\n\n\tconstexpr explicit operator double() {\n\t\treturn get<std::nano>();\n\t}\n\n...\n}\n\n--\nKieran","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 6FE1BBD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Oct 2022 08:24:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C1AF062F4B;\n\tWed, 26 Oct 2022 10:24:45 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E426662ED0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 10:24:43 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 7E5444F8;\n\tWed, 26 Oct 2022 10:24:43 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666772685;\n\tbh=rklXJtZ2egdzn2FK8yUp26P03btB0dsm8hiby0xXhOE=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=bpNUQKikTCe89OeubC7y41B78c2pL0cgzY9Z7jGByx1C7vjCVzozwuSiYDQ80Ch85\n\tSS0oxF0AG7cimfLRHRjNG2gSLYEqIGCFSCs1N/KdxWdcwgZh6afcB8uXBfFsTg6eNh\n\tS+dW3pWYUPi82Ue5CyUJFR2idLmjka27zRgbmC8PXd+FxGG7tr3azGIKHrj0KpKiCi\n\t5Kkd4Nka1VkDk5g84p3gzbWBNmhwK4m85I23q6lcbAqWVm9Km1DGfIWo5vcJLP9aBo\n\tBv6FF4xUToqsxl4OZOl0Og8gFcM0H/qTDm10SHS5JHZ1lpyzwXl+pXXcp8T8JqszdG\n\tygEshg+/bvPoQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666772683;\n\tbh=rklXJtZ2egdzn2FK8yUp26P03btB0dsm8hiby0xXhOE=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=dKSrL2wt/1LtThF5a0Szi1LJZFp9gew4sv8aDyFyboaPINANNjRNy3cSN9jcHxhNi\n\tMRKpXfoutn5VZyvshNnvRS5+Mx0TJ5mXcq+PzRY9/IcBD9yw3q3dwblmInlRM/iR7U\n\t6ugaHVYotLSIduwFO5kDIcOTxeTnc+cUXy9Vm9Zg="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"dKSrL2wt\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>","To":"Nicholas Roth <nicholas@rothemail.net>","Date":"Wed, 26 Oct 2022 09:24:41 +0100","Message-ID":"<166677268158.3974115.15111815458042537047@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25590,"web_url":"https://patchwork.libcamera.org/comment/25590/","msgid":"<CAEmqJPpZBckB1gRr25UsmDp623J3Fzj7LXxJZmHKj_YSBiqDnQ@mail.gmail.com>","date":"2022-10-26T08:46:51","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi,\n\nOn Wed, 26 Oct 2022 at 09:24, Kieran Bingham via libcamera-devel <\nlibcamera-devel@lists.libcamera.org> wrote:\n\n> Quoting Nicholas Roth (2022-10-26 02:50:34)\n> > Another possible fix is to cast libcamera::utils::Duration to\n> > std::chrono::duration before performing division. I've tested that and it\n> > works. Would folks be amenable to that instead?\n>\n> That sounds like we still have to make global updates. Are any of those\n> locations where we should store a libcamera::utils::Duration instead of\n> a std::chrono::duration to prevent having to cast?\n>\n> If casting works around the issue, is it sufficient / possible to\n> provide an explicit casting operator? (I've never done this to more than\n> the POD types, but it 'looks' like you can specify specific target\n> classes as an operator?)\n>\n>   https://en.cppreference.com/w/cpp/language/cast_operator\n\n\nCasting like this is indeed possible, but even then, the changes required\nare spread across the codebase.  IMO this is undesirable for readability,\nand error prone as any future developers must know to do this cast\nif they were to do computations with utils::Duration.\n\nI hope there is a centralized solution with operator / overloading, but\nif there's no choice...\n\nNaush\n\n\n>\n> Something like (I have no idea if this is something that can work, or if\n> it helps the compiler as it should already know the type?!)...:\n>\n> class Duration : public std::chrono::duration<double, std::nano>\n> {\n> ...\n>\n>         explicit operator std::chrono::duration() {\n>                 return std::chrono::duration_cast<BaseDuration>>(*this);\n>         }\n>\n> or perhaps 'worse' ? (but at least isolated to here in the class?)...\n>\n>         constexpr explicit operator double() {\n>                 return get<std::nano>();\n>         }\n>\n> ...\n> }\n>\n> --\n> Kieran\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 94ECDBDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Oct 2022 08:47:10 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D7B2C62F4C;\n\tWed, 26 Oct 2022 10:47:09 +0200 (CEST)","from mail-qt1-x836.google.com (mail-qt1-x836.google.com\n\t[IPv6:2607:f8b0:4864:20::836])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 830D662ED0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 10:47:08 +0200 (CEST)","by mail-qt1-x836.google.com with SMTP id g11so9435655qts.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 01:47:08 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666774029;\n\tbh=oUs3YCeRx0qKtJLwkz+bqywHWb/YeBZKCSQCG80N2E4=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=keo+fIIkYn/3NABBsD0S5x/lGzaNhahFG9XP9U69R6zAkbTrRphs4GzwefUVAsWuZ\n\tgKvNUDRFZBsCAWdPqf1GEFT+o2q6gsCdG79BepPdWq5EEtw8H/hYPppMJjQ+m5qTXx\n\tC+R+dfIo3wTfe8Kmk7SoFAoIP9V8/FRkEClise86/IiLbp5FFCAr7GDnW83EiVt8Ur\n\tvlvJ4mSfjxYkSTOzQ8ii0CMHnWeUHw+jQzNQpNsFBILCDcVXB/8jA+5RkrICBmiYc5\n\tJRepIKkSpHDS5x+357O26iDhLUbRDMINoJLTfozukievaMpdhI3NpVxYTcjTz2wsBv\n\tJg4BNPjxSD5jQ==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=yviHDQeTgAgNxXLu+mlrkRkTS3df+Xp+Rx9xgyfrvrA=;\n\tb=NBkxCSwvq3XZAWSRvPmyCkIrF66Fiuqc9H2DAj5muedRTm97u5nXC0yuHAXvpI8C03\n\tImrMUuR4B1I2ZNDNc7yfGt+Sh9HeKRfhWBeo9lbH0GdQXnLW8LT/dbJpDpn0UeMzBtZn\n\tcWnTXZrL6HwXbP8Cwq1e8DehJN9DqnOCYjg1UId+f3clEjAmxRX+yjRzE91hG9kFhRSu\n\tvWaXGVng4QpvzJLo0oevJ/JEd6fu0Lc1l7J0GzzonxVMTax4ZC6jzX40BMGt5oM3I1o2\n\tLqeJ8s/XxMppBetQ9CqzNRvuyEZhUkEbGvoMuL61/5Zldy4LYrwL07lICr/9Ji7tIuGP\n\to8Rg=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"NBkxCSwv\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=yviHDQeTgAgNxXLu+mlrkRkTS3df+Xp+Rx9xgyfrvrA=;\n\tb=xgB2xX1+fl+BqNNaKANK6drsqIiotP4ztsgRfEF/IKpdGyReAWPKmYVXnQQxygv6dm\n\t+qQ/KaejdfrfhWtfKdiWaZ472jprlxirIiqv7R1Ewl5yZ/rRjBFl+0XJ7bSTC1LtDf8l\n\tFXHzIKj8/y7zUEeOvvo18UGrWKPX/MbyqesQpFsp6g5bKjMkCOYKFHdzPfZBN/vyJKQa\n\tWhE9HtHRldeVbvIR0wxkA6x5RUZqfyk+DfhUCC6SYKL5GG1wdiYEWC7J+hx3C+WZw/S+\n\t0R6XYCvpMROm85OIFjLmxjfjpoc94ofIAKeYqOAYJ6Y+sojuH/ozMDSQWnTcZxSZEHWV\n\tlOOA==","X-Gm-Message-State":"ACrzQf09ej+9pODYdiSQRhqSk50uWjGKTI4po6FUuM73OkVCtJQftD9n\n\tXi7r2YfhrVjnScAR9JmI3xoX2t2QGBJvgCeAgfUuWFuAezE=","X-Google-Smtp-Source":"AMsMyM7KmFx+8fe6Xyt/VjebJfVhw4Vx8h1yFrvfe+5ZGErQ9MQ0OOotiej08iq61J0DO2GS6v6L9btmlmyZJf4vrKQ=","X-Received":"by 2002:a05:622a:1a02:b0:39c:b9f9:36d0 with SMTP id\n\tf2-20020a05622a1a0200b0039cb9f936d0mr36135424qtb.174.1666774027392;\n\tWed, 26 Oct 2022 01:47:07 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>\n\t<166677268158.3974115.15111815458042537047@Monstersaurus>","In-Reply-To":"<166677268158.3974115.15111815458042537047@Monstersaurus>","Date":"Wed, 26 Oct 2022 09:46:51 +0100","Message-ID":"<CAEmqJPpZBckB1gRr25UsmDp623J3Fzj7LXxJZmHKj_YSBiqDnQ@mail.gmail.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Content-Type":"multipart/alternative; boundary=\"000000000000d2f33b05ebec1148\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Naushir Patuck via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Naushir Patuck <naush@raspberrypi.com>","Cc":"Nicholas Roth <nicholas@rothemail.net>, Nicholas Roth via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25591,"web_url":"https://patchwork.libcamera.org/comment/25591/","msgid":"<166677431137.3974115.16374594371777153094@Monstersaurus>","date":"2022-10-26T08:51:51","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Naushir Patuck (2022-10-26 09:46:51)\n> Hi,\n> \n> On Wed, 26 Oct 2022 at 09:24, Kieran Bingham via libcamera-devel <\n> libcamera-devel@lists.libcamera.org> wrote:\n> \n> > Quoting Nicholas Roth (2022-10-26 02:50:34)\n> > > Another possible fix is to cast libcamera::utils::Duration to\n> > > std::chrono::duration before performing division. I've tested that and it\n> > > works. Would folks be amenable to that instead?\n> >\n> > That sounds like we still have to make global updates. Are any of those\n> > locations where we should store a libcamera::utils::Duration instead of\n> > a std::chrono::duration to prevent having to cast?\n> >\n> > If casting works around the issue, is it sufficient / possible to\n> > provide an explicit casting operator? (I've never done this to more than\n> > the POD types, but it 'looks' like you can specify specific target\n> > classes as an operator?)\n> >\n> >   https://en.cppreference.com/w/cpp/language/cast_operator\n> \n> \n> Casting like this is indeed possible, but even then, the changes required\n> are spread across the codebase.  IMO this is undesirable for readability,\n> and error prone as any future developers must know to do this cast\n> if they were to do computations with utils::Duration.\n> \n> I hope there is a centralized solution with operator / overloading, but\n> if there's no choice...\n\nahh, I thought that would allow the compiler to do the implicit casting,\nif the type was defined.\n\nBut perhaps the clue is in the name \"cast_operator\"\n\n--\nKieran\n\n> \n> Naush\n> \n> \n> >\n> > Something like (I have no idea if this is something that can work, or if\n> > it helps the compiler as it should already know the type?!)...:\n> >\n> > class Duration : public std::chrono::duration<double, std::nano>\n> > {\n> > ...\n> >\n> >         explicit operator std::chrono::duration() {\n> >                 return std::chrono::duration_cast<BaseDuration>>(*this);\n> >         }\n> >\n> > or perhaps 'worse' ? (but at least isolated to here in the class?)...\n> >\n> >         constexpr explicit operator double() {\n> >                 return get<std::nano>();\n> >         }\n> >\n> > ...\n> > }\n> >\n> > --\n> > Kieran\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 6E8C4BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Oct 2022 08:51:57 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A9A7462F4E;\n\tWed, 26 Oct 2022 10:51:56 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A0D5762ED0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 10:51:54 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 31DA74F8;\n\tWed, 26 Oct 2022 10:51:54 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666774316;\n\tbh=53pvAA0j+2T3/gnN4EcICO5wa2IGG073ohkO+anPjKM=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=2D3T2qn8xWMjNszudZrHiR70E7olNOrnhFNuH+/LSWxMYXjDyLNzZrhFJNWr/ngME\n\tudUBv7/WaHJOMQmSgIICdIsIAh976f1QhnvbeIV0NnJhZCb0YAAtRUtg/LPfouozVa\n\tmM//+mUNgQfO7GPr0K5YAXKJrjbMb8PxBSGuaL5XKkJq3PW/fy4JqYrn0QeDAZhIRD\n\txOmOen5+IovKq+7F/NjsBwGbvg4W09cQYOLvVjQXMHyCzJL7qOaUHxcMP5wJOVUCBr\n\tI0rmabRNC23jb4BfR0GSTErWgTsYpLHfGSnPJMNEjUnh+4LIE2okxIrsY9LQfHvbvs\n\tQJgIy+1021/Pg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666774314;\n\tbh=53pvAA0j+2T3/gnN4EcICO5wa2IGG073ohkO+anPjKM=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=TDmAoJum+Dt4UqDZQMsQeO6Ef+TF6XDpL6/mPfHMXGyTXCMix3MaLKy+vA+HVw1Rk\n\tFxnJ3nXyxpbb9FqN3SyiuSdd47GR+OmJ6Fc2WMYcOokXCds96vG1xeRwywKBHW1dgE\n\t0sKKzHzqz0Jq19FSiAvdFog93IEMObp9x5aqhYA0="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"TDmAoJum\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<CAEmqJPpZBckB1gRr25UsmDp623J3Fzj7LXxJZmHKj_YSBiqDnQ@mail.gmail.com>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>\n\t<166677268158.3974115.15111815458042537047@Monstersaurus>\n\t<CAEmqJPpZBckB1gRr25UsmDp623J3Fzj7LXxJZmHKj_YSBiqDnQ@mail.gmail.com>","To":"Naushir Patuck <naush@raspberrypi.com>","Date":"Wed, 26 Oct 2022 09:51:51 +0100","Message-ID":"<166677431137.3974115.16374594371777153094@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Nicholas Roth <nicholas@rothemail.net>, Nicholas Roth via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25595,"web_url":"https://patchwork.libcamera.org/comment/25595/","msgid":"<CAD2rFCo5NDktCzmmEOXQmrxsuAvCA8q8tms48hYWA+eYvkfPJA@mail.gmail.com>","date":"2022-10-26T13:28:10","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":137,"url":"https://patchwork.libcamera.org/api/people/137/","name":"Nicholas Roth","email":"nicholas@rothemail.net"},"content":"Naushir,\n> I hope there is a centralized solution with operator / overloading, but\n> if there's no choice...\n\nThe only centralized solution I've been able to find with operator/ that\n*might* work has some major limitations. Namely, it only really works when\nthe LHS is a libcamera::utils::Duration and you get weird errors when it's\non the RHS. I can't overload at the namespace level because then it causes\nambiguity with (sometimes even linker errors with) existing std::chrono\noverloads.\n\nKieran,\n> That sounds like we still have to make global updates. Are any of those\n> locations where we should store a libcamera::utils::Duration instead of\n> a std::chrono::duration to prevent having to cast?\nDid you mean vice versa (store a std::chrono::duration instead of\nlibcamera::utils::Duration)? That would fix it, but from my understanding\nthat would miss the point of standardizing around a double-width floating\npoint representation at std::nano timebase.\n\n> If casting works around the issue, is it sufficient / possible to\n> provide an explicit casting operator? (I've never done this to more than\n> the POD types, but it 'looks' like you can specify specific target\n> classes as an operator?)\n\nI'm not sure what this would accomplish. I've been able to upcast\nlibcamera::utils::Duration to std::chrono::duration with just\n`std::chrono::duration(x)` without adding an operator. Note that this seems\nto have nuked my <TAB>s, which I used instead of spaces for indentation to\nbe consistent with surrounding code.\n\nI'm also appending the proposed v2 of this patch below to add clarity to\nwhat I propose:\nFrom 4efd469a63288b89c65be45ea1724ccde4ec486f Mon Sep 17 00:00:00 2001\nFrom: Nicholas Roth <nicholas@rothemail.net>\nDate: Mon, 24 Oct 2022 00:03:25 -0500\nSubject: [PATCH 1/3] ipa: workaround libcxx duration limitation\n\nA bug in libcxx [0] used by clang version 11.0.2 is prevalent when\nbuilding libcamera for Android SDK30. This has been fixed and\nintegrated upstream with [1].\n\nAs a workaround, directly cast libcamera::utils::Duration objects to\nstd::chrono::duration when dividing.\n\nAlternatives evaluated:\nConsidered: Enable public inheritance of std::chrono::duration and\noverride operator/ in the class.\nOutcome: Does not fix the original compiler error.\n\nConsidered: Enable public inheritance of std::chrono::duration and\noverride operator/ in the libcamera namespace.\nOutcome: new compiler error:\nld.lld: error: duplicate symbol: libcamera::operator/\n(libcamera::utils::Duration const&, libcamera::utils::Duration const&)\n\nConsidered: Use private inheritance of std::chrono::duration and\nre-implement a pass-through version of each std::chrono::duration\noperator within libcamera::utils::Duration and use template\nmetaprogramming to fix the division operator.\nOutcome: Testing shows that this would introduce substantial\nlimitations, i.e. requring the Duration object to be on the LHS of any\narithmetic operation with other numeric types. This also substantially\nincreases implementation complexity.\n\nConsidered: Extract double values from libcamera::utils::Duration\nobjects and use those to divide.\nOutcome: This creates substantial readability and unit-safety issues.\n\n[0] https://github.com/llvm/llvm-project/issues/40475\n[1]\nhttps://github.com/llvm/llvm-project/commit/efa6d803c624f9251d0ab7881122501bb9d27368\nBug: https://bugs.libcamera.org/show_bug.cgi?id=156\n\nSigned-off-by: Nicholas Roth <nicholas@rothemail.net>\n---\n src/ipa/ipu3/algorithms/agc.cpp            | 17 +++++++++++------\n src/ipa/raspberrypi/cam_helper.cpp         |  6 +++---\n src/ipa/raspberrypi/cam_helper_imx296.cpp  |  3 ++-\n src/ipa/raspberrypi/controller/rpi/agc.cpp | 12 ++++++++----\n src/ipa/raspberrypi/controller/rpi/lux.cpp |  3 ++-\n src/ipa/rkisp1/algorithms/agc.cpp          | 12 ++++++++----\n 6 files changed, 34 insertions(+), 19 deletions(-)\n\ndiff --git a/src/ipa/ipu3/algorithms/agc.cpp\nb/src/ipa/ipu3/algorithms/agc.cpp\nindex a1a3c38f..1d8518da 100644\n--- a/src/ipa/ipu3/algorithms/agc.cpp\n+++ b/src/ipa/ipu3/algorithms/agc.cpp\n@@ -100,7 +100,8 @@ int Agc::configure(IPAContext &context,\n\n  /* Configure the default exposure and gain. */\n  activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n- activeState.agc.exposure = 10ms / configuration.sensor.lineDuration;\n+ activeState.agc.exposure = 10ms /\n+ std::chrono::duration(configuration.sensor.lineDuration);\n\n  frameCount_ = 0;\n  return 0;\n@@ -240,17 +241,21 @@ void Agc::computeExposure(IPAContext &context,\nIPAFrameContext &frameContext,\n  * increase the gain.\n  */\n  utils::Duration shutterTime =\n- std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,\n-    minShutterSpeed_, maxShutterSpeed_);\n- double stepGain = std::clamp(exposureValue / shutterTime,\n-     minAnalogueGain_, maxAnalogueGain_);\n+ std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n+ std::chrono::duration(minAnalogueGain_),\n+    minShutterSpeed_, maxShutterSpeed_);\n+ double stepGain = std::clamp(std::chrono::duration(exposureValue) /\n+ std::chrono::duration(shutterTime),\n+ minAnalogueGain_, maxAnalogueGain_);\n  LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n     << shutterTime << \" and \"\n     << stepGain;\n\n  IPAActiveState &activeState = context.activeState;\n  /* Update the estimated exposure and gain. */\n- activeState.agc.exposure = shutterTime /\nconfiguration.sensor.lineDuration;\n+ double lineDurationDouble = .get<std::nano>();\n+ activeState.agc.exposure = std::chrono::duration(shutterTimeDouble) /\n+ std::chrono::duration(configuration.sensor.lineDuration);\n  activeState.agc.gain = stepGain;\n }\n\ndiff --git a/src/ipa/raspberrypi/cam_helper.cpp\nb/src/ipa/raspberrypi/cam_helper.cpp\nindex d90ac1de..48a8a068 100644\n--- a/src/ipa/raspberrypi/cam_helper.cpp\n+++ b/src/ipa/raspberrypi/cam_helper.cpp\n@@ -63,7 +63,7 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr\n&stats,\n\n uint32_t CamHelper::exposureLines(const Duration exposure, const Duration\nlineLength) const\n {\n- return exposure / lineLength;\n+ return std::chrono::duration(exposure) /\nstd::chrono::duration(lineLength);\n }\n\n Duration CamHelper::exposure(uint32_t exposureLines, const Duration\nlineLength) const\n@@ -85,8 +85,8 @@ std::pair<uint32_t, uint32_t>\nCamHelper::getBlanking(Duration &exposure,\n  * frameLengthMax gets calculated on the smallest line length as we do\n  * not want to extend that unless absolutely necessary.\n  */\n- frameLengthMin = minFrameDuration / mode_.minLineLength;\n- frameLengthMax = maxFrameDuration / mode_.minLineLength;\n+ frameLengthMin = std::chrono::duration(minFrameDuration) /\nstd::chrono::duration(mode_.minLineLength);\n+ frameLengthMax = std::chrono::duration(maxFrameDuration) /\nstd::chrono::duration(mode_.minLineLength);\n\n  /*\n  * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\nb/src/ipa/raspberrypi/cam_helper_imx296.cpp\nindex ecb845e7..65f76c3c 100644\n--- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n@@ -57,7 +57,8 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n  [[maybe_unused]] const Duration lineLength) const\n {\n- return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) /\ntimePerLine);\n+ return std::max<uint32_t>(minExposureLines,\nstd::chrono::duration(exposure - 14.26us) /\n+ std::chrono::duration(timePerLine));\n }\n\n Duration CamHelperImx296::exposure(uint32_t exposureLines,\ndiff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\nb/src/ipa/raspberrypi/controller/rpi/agc.cpp\nindex bd54a639..cfa5ed90 100644\n--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n@@ -418,7 +418,8 @@ void Agc::prepare(Metadata *imageMetadata)\n  Duration actualExposure = deviceStatus.shutterSpeed *\n   deviceStatus.analogueGain;\n  if (actualExposure) {\n- status_.digitalGain = status_.totalExposureValue / actualExposure;\n+ status_.digitalGain = std::chrono::duration(status_.totalExposureValue) /\n+ std::chrono::duration(actualExposure);\n  LOG(RPiAgc, Debug) << \"Want total exposure \" <<\nstatus_.totalExposureValue;\n  /*\n  * Never ask for a gain < 1.0, and also impose\n@@ -823,7 +824,8 @@ void Agc::divideUpExposure()\n  }\n  if (status_.fixedAnalogueGain == 0.0) {\n  if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {\n- analogueGain = exposureValue / shutterTime;\n+ analogueGain = std::chrono::duration(exposureValue) /\n+ std::chrono::duration(shutterTime);\n  break;\n  }\n  analogueGain = exposureMode_->gain[stage];\n@@ -838,10 +840,12 @@ void Agc::divideUpExposure()\n  */\n  if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n     status_.flickerPeriod) {\n- int flickerPeriods = shutterTime / status_.flickerPeriod;\n+ int flickerPeriods = std::chrono::duration(shutterTime) /\n+ std::chrono::duration(status_.flickerPeriod);\n  if (flickerPeriods) {\n  Duration newShutterTime = flickerPeriods * status_.flickerPeriod;\n- analogueGain *= shutterTime / newShutterTime;\n+ analogueGain *= std::chrono::duration(shutterTime) /\n+ std::chrono::duration(newShutterTime);\n  /*\n  * We should still not allow the ag to go over the\n  * largest value in the exposure mode. Note that this\ndiff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\nb/src/ipa/raspberrypi/controller/rpi/lux.cpp\nindex 9759186a..430642f0 100644\n--- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n@@ -94,7 +94,8 @@ void Lux::process(StatisticsPtr &stats, Metadata\n*imageMetadata)\n  double currentY = sum / (double)num + .5;\n  double gainRatio = referenceGain_ / currentGain;\n  double shutterSpeedRatio =\n- referenceShutterSpeed_ / deviceStatus.shutterSpeed;\n+ std::chrono::duration(referenceShutterSpeed_) /\n+ std::chrono::duration(deviceStatus.shutterSpeed);\n  double apertureRatio = referenceAperture_ / currentAperture;\n  double yRatio = currentY * (65536 / numBins) / referenceY_;\n  double estimatedLux = shutterSpeedRatio * gainRatio *\ndiff --git a/src/ipa/rkisp1/algorithms/agc.cpp\nb/src/ipa/rkisp1/algorithms/agc.cpp\nindex 04062a36..e8814802 100644\n--- a/src/ipa/rkisp1/algorithms/agc.cpp\n+++ b/src/ipa/rkisp1/algorithms/agc.cpp\n@@ -74,7 +74,8 @@ int Agc::configure(IPAContext &context, const\nIPACameraSensorInfo &configInfo)\n {\n  /* Configure the default exposure and gain. */\n  context.activeState.agc.gain =\nstd::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n- context.activeState.agc.exposure = 10ms /\ncontext.configuration.sensor.lineDuration;\n+ context.activeState.agc.exposure = 10ms /\n+ std::chrono::duration(context.configuration.sensor.lineDuration);\n\n  /*\n  * According to the RkISP1 documentation:\n@@ -212,16 +213,19 @@ void Agc::computeExposure(IPAContext &context,\nIPAFrameContext &frameContext,\n  * Push the shutter time up to the maximum first, and only then\n  * increase the gain.\n  */\n- utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue /\nminAnalogueGain,\n+ utils::Duration shutterTime =\nstd::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n+ minAnalogueGain,\n   minShutterSpeed, maxShutterSpeed);\n- double stepGain = std::clamp(exposureValue / shutterTime,\n+ double stepGain = std::clamp(std::chrono::duration(exposureValue) /\n+ std::chrono::duration(shutterTime),\n      minAnalogueGain, maxAnalogueGain);\n  LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n       << shutterTime << \" and \"\n       << stepGain;\n\n  /* Update the estimated exposure and gain. */\n- activeState.agc.exposure = shutterTime /\nconfiguration.sensor.lineDuration;\n+ activeState.agc.exposure = std::chrono::duration(shutterTime) /\n+ std::chrono::duration(configuration.sensor.lineDuration);\n  activeState.agc.gain = stepGain;\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 EE2C1BDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Oct 2022 13:28:25 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3165362F4E;\n\tWed, 26 Oct 2022 15:28:25 +0200 (CEST)","from mail-io1-xd33.google.com (mail-io1-xd33.google.com\n\t[IPv6:2607:f8b0:4864:20::d33])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4EEB361F4B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 15:28:23 +0200 (CEST)","by mail-io1-xd33.google.com with SMTP id q75so3549321iod.7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 06:28:23 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666790905;\n\tbh=i0Sh/YESCZduJtHbhgXd65NhBXDVFp8VNKKeX3pParA=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=njhzX6cWa//SHwdeHHYKETgrOt27FPzdp8ihATYaE3n2C6jJ1/KAXmxDB5Cty4m/p\n\t+lmJW+BQOH+HlBSw6FXR8FJdWUTbK5+NFVEwmZmmn/Aafs47V/TMz2AftUHsJQJmEK\n\t/rnClE/4f0eCO3SVG9H2K16D/r9nqKo9IvrnvFAw4PzCYM0foLVRPjfsIF4L5E37WW\n\tjdACs23cAqMFhYAGy1Od/VlVAJT5DaUU7CjUhM9cCKf2j325oURL27U4abCKnEVuel\n\tuGuIrrLNAdLAd+xItxdKT7pXZ6KXbAxLZZV0EF9dhzsGmd33DoXQJ1KeG2mFEgUCi2\n\tc9bViJ8w/OU/g==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=rothemail-net.20210112.gappssmtp.com; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=8aO4Rh2kORZNIXxI1sytxhjVeMQDEGT9VRcy88Qy2wQ=;\n\tb=mLXmNRcC9RkSUG3G0fvkyC7heHauMflv2F386GpFCI1+88DM2D18LtCkEiD7Y6tTn0\n\tm2Nyhpz0cVSR2oFSE6m+nS2TOGlyX78SFhpJM6cBK7BgMaztjf2xY01VthbmcGaEofAz\n\tcq5XnU2VUV5v+l/7CAByi2PWOyr3fMUiz4tqfwdB/Mj/8MUMEf8+RiM2vIk4Iy/QZJn4\n\tJDf9rCbdLabiC8nFACgTolWs7PWqPZvNVAATobtxqolg4cG3iRxUjPpDJQiYRGKl/Eiq\n\t2/J4tlo1BLII4fN/aoMneBKDxn5hSLMQowUbQqqqY5J/K7b5zOmdcSvVh4zy2VaXkgJK\n\tAGNQ=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=rothemail-net.20210112.gappssmtp.com\n\theader.i=@rothemail-net.20210112.gappssmtp.com header.b=\"mLXmNRcC\"; \n\tdkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=8aO4Rh2kORZNIXxI1sytxhjVeMQDEGT9VRcy88Qy2wQ=;\n\tb=fjgdLTUWKfdeAdT18b12+gxZRszgK3AHLO1IxOM2y3eWq4XVtyegYxR/MYZCb4vnxm\n\twc9tvR4oriHTRfKh8PdjSkHSVDtI6PxhPfCLXuvUIy6gTPyxIFaTZ/UoC3JC3xuUKkwM\n\tVFD4nlcCAX3CdcEu1J0nRSQPy2Tbw4wsTfgDPP94YkemL/zM9xyA2x/w3IjDm9vZBhnf\n\ttla3g4WmgA+owcfVBEPOrrq4G81jQCCHC9wrTlW953no4kZnQjkJ4Q7MO9DCBh8myN2s\n\thyd3Tob1oJ0o52S39kjBqmJUZr2gylKRavPrqU4lQCqI0f3jVEFxT134HoqexnYMpJKj\n\tJ8bw==","X-Gm-Message-State":"ACrzQf14QfqOWK2ZfWzccuxNlNiZMxmcWg4r0Vy/3SA2jPYpEweuOHJW\n\tK0bAw9yZWj8TfXSrOGT1tRGGpSz6+ivcdOlo4HiaLg==","X-Google-Smtp-Source":"AMsMyM66uV0lEhgPXzA435zTncInLfqzIbbBD8jkQDwfNqQ3Foy/w/FnUmo40WYWCA8SCfN4gJVLOuxjfnHvHM6muDM=","X-Received":"by 2002:a05:6638:2613:b0:364:7c5:81dc with SMTP id\n\tm19-20020a056638261300b0036407c581dcmr25690436jat.225.1666790901666;\n\tWed, 26 Oct 2022 06:28:21 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>\n\t<166677268158.3974115.15111815458042537047@Monstersaurus>\n\t<CAEmqJPpZBckB1gRr25UsmDp623J3Fzj7LXxJZmHKj_YSBiqDnQ@mail.gmail.com>\n\t<166677431137.3974115.16374594371777153094@Monstersaurus>","In-Reply-To":"<166677431137.3974115.16374594371777153094@Monstersaurus>","Date":"Wed, 26 Oct 2022 08:28:10 -0500","Message-ID":"<CAD2rFCo5NDktCzmmEOXQmrxsuAvCA8q8tms48hYWA+eYvkfPJA@mail.gmail.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Content-Type":"multipart/alternative; boundary=\"0000000000009bea6605ebefffdf\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Nicholas Roth <nicholas@rothemail.net>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25600,"web_url":"https://patchwork.libcamera.org/comment/25600/","msgid":"<CAEmqJPoow7Aw3KXojrKiUf6zxCC8bb0k-4TPpH-x6gg=PSwS0A@mail.gmail.com>","date":"2022-10-26T14:26:13","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"On Wed, 26 Oct 2022 at 14:28, Nicholas Roth <nicholas@rothemail.net> wrote:\n\n> Naushir,\n> > I hope there is a centralized solution with operator / overloading, but\n> > if there's no choice...\n>\n> The only centralized solution I've been able to find with operator/ that\n> *might* work has some major limitations. Namely, it only really works\n> when the LHS is a libcamera::utils::Duration and you get weird errors when\n> it's on the RHS. I can't overload at the namespace level because then it\n> causes ambiguity with (sometimes even linker errors with) existing\n> std::chrono overloads.\n>\n\nI've briefly tried the following snippet of code:\n\n---\n\ndiff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\nindex eb7bcdf4c173..ebcd56475b17 100644\n--- a/include/libcamera/base/utils.h\n+++ b/include/libcamera/base/utils.h\n@@ -358,6 +358,32 @@ public:\n        }\n };\n\n+inline double operator/(const Duration &num, const Duration &den)\n+{\n+       double n = num.get<std::nano>();\n+       double d = den.get<std::nano>();\n+\n+       return n / d;\n+}\n+\n+template<typename Rep, typename Period>\n+inline double operator/(const Duration &num, const\nstd::chrono::duration<Rep, Period> &den)\n+{\n+       double n = num.get<std::nano>();\n+       double d =\n(std::chrono::duration_cast<std::chrono::duration<double,\nstd::nano>>(den)).count();\n+\n+       return n / d;\n+}\n+\n+template<typename Rep, typename Period>\n+inline double operator/(const std::chrono::duration<Rep, Period> &num,\nconst Duration &den)\n+{\n+       double n =\n(std::chrono::duration_cast<std::chrono::duration<double,\nstd::nano>>(num)).count();\n+       double d = den.get<std::nano>();\n+\n+       return n / d;\n+}\n+\n template<typename T>\n decltype(auto) abs_diff(const T &a, const T &b)\n\n---\nIt compiles/links ok on clang 11.0.1 (the only version of clang-11 that is\navailable on my platform, but does not exactly match your version).\nFunctionally it seems to do the right thing as well.\nAre you able to try this out in your environment to see if it resolves your\ncompile issues?\n\nRegards,\nNaush\n\n\n>\n> Kieran,\n> > That sounds like we still have to make global updates. Are any of those\n> > locations where we should store a libcamera::utils::Duration instead of\n> > a std::chrono::duration to prevent having to cast?\n> Did you mean vice versa (store a std::chrono::duration instead of\n> libcamera::utils::Duration)? That would fix it, but from my understanding\n> that would miss the point of standardizing around a double-width floating\n> point representation at std::nano timebase.\n>\n> > If casting works around the issue, is it sufficient / possible to\n> > provide an explicit casting operator? (I've never done this to more than\n> > the POD types, but it 'looks' like you can specify specific target\n> > classes as an operator?)\n>\n> I'm not sure what this would accomplish. I've been able to upcast\n> libcamera::utils::Duration to std::chrono::duration with just\n> `std::chrono::duration(x)` without adding an operator. Note that this seems\n> to have nuked my <TAB>s, which I used instead of spaces for indentation to\n> be consistent with surrounding code.\n>\n> I'm also appending the proposed v2 of this patch below to add clarity to\n> what I propose:\n> From 4efd469a63288b89c65be45ea1724ccde4ec486f Mon Sep 17 00:00:00 2001\n> From: Nicholas Roth <nicholas@rothemail.net>\n> Date: Mon, 24 Oct 2022 00:03:25 -0500\n> Subject: [PATCH 1/3] ipa: workaround libcxx duration limitation\n>\n> A bug in libcxx [0] used by clang version 11.0.2 is prevalent when\n> building libcamera for Android SDK30. This has been fixed and\n> integrated upstream with [1].\n>\n> As a workaround, directly cast libcamera::utils::Duration objects to\n> std::chrono::duration when dividing.\n>\n> Alternatives evaluated:\n> Considered: Enable public inheritance of std::chrono::duration and\n> override operator/ in the class.\n> Outcome: Does not fix the original compiler error.\n>\n> Considered: Enable public inheritance of std::chrono::duration and\n> override operator/ in the libcamera namespace.\n> Outcome: new compiler error:\n> ld.lld: error: duplicate symbol: libcamera::operator/\n> (libcamera::utils::Duration const&, libcamera::utils::Duration const&)\n>\n> Considered: Use private inheritance of std::chrono::duration and\n> re-implement a pass-through version of each std::chrono::duration\n> operator within libcamera::utils::Duration and use template\n> metaprogramming to fix the division operator.\n> Outcome: Testing shows that this would introduce substantial\n> limitations, i.e. requring the Duration object to be on the LHS of any\n> arithmetic operation with other numeric types. This also substantially\n> increases implementation complexity.\n>\n> Considered: Extract double values from libcamera::utils::Duration\n> objects and use those to divide.\n> Outcome: This creates substantial readability and unit-safety issues.\n>\n> [0] https://github.com/llvm/llvm-project/issues/40475\n> [1]\n> https://github.com/llvm/llvm-project/commit/efa6d803c624f9251d0ab7881122501bb9d27368\n> Bug: https://bugs.libcamera.org/show_bug.cgi?id=156\n>\n> Signed-off-by: Nicholas Roth <nicholas@rothemail.net>\n> ---\n>  src/ipa/ipu3/algorithms/agc.cpp            | 17 +++++++++++------\n>  src/ipa/raspberrypi/cam_helper.cpp         |  6 +++---\n>  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  3 ++-\n>  src/ipa/raspberrypi/controller/rpi/agc.cpp | 12 ++++++++----\n>  src/ipa/raspberrypi/controller/rpi/lux.cpp |  3 ++-\n>  src/ipa/rkisp1/algorithms/agc.cpp          | 12 ++++++++----\n>  6 files changed, 34 insertions(+), 19 deletions(-)\n>\n> diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n> b/src/ipa/ipu3/algorithms/agc.cpp\n> index a1a3c38f..1d8518da 100644\n> --- a/src/ipa/ipu3/algorithms/agc.cpp\n> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> @@ -100,7 +100,8 @@ int Agc::configure(IPAContext &context,\n>\n>   /* Configure the default exposure and gain. */\n>   activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n> - activeState.agc.exposure = 10ms / configuration.sensor.lineDuration;\n> + activeState.agc.exposure = 10ms /\n> + std::chrono::duration(configuration.sensor.lineDuration);\n>\n>   frameCount_ = 0;\n>   return 0;\n> @@ -240,17 +241,21 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n>   * increase the gain.\n>   */\n>   utils::Duration shutterTime =\n> - std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,\n> -    minShutterSpeed_, maxShutterSpeed_);\n> - double stepGain = std::clamp(exposureValue / shutterTime,\n> -     minAnalogueGain_, maxAnalogueGain_);\n> + std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n> + std::chrono::duration(minAnalogueGain_),\n> +    minShutterSpeed_, maxShutterSpeed_);\n> + double stepGain = std::clamp(std::chrono::duration(exposureValue) /\n> + std::chrono::duration(shutterTime),\n> + minAnalogueGain_, maxAnalogueGain_);\n>   LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n>      << shutterTime << \" and \"\n>      << stepGain;\n>\n>   IPAActiveState &activeState = context.activeState;\n>   /* Update the estimated exposure and gain. */\n> - activeState.agc.exposure = shutterTime /\n> configuration.sensor.lineDuration;\n> + double lineDurationDouble = .get<std::nano>();\n> + activeState.agc.exposure = std::chrono::duration(shutterTimeDouble) /\n> + std::chrono::duration(configuration.sensor.lineDuration);\n>   activeState.agc.gain = stepGain;\n>  }\n>\n> diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n> b/src/ipa/raspberrypi/cam_helper.cpp\n> index d90ac1de..48a8a068 100644\n> --- a/src/ipa/raspberrypi/cam_helper.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> @@ -63,7 +63,7 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr\n> &stats,\n>\n>  uint32_t CamHelper::exposureLines(const Duration exposure, const Duration\n> lineLength) const\n>  {\n> - return exposure / lineLength;\n> + return std::chrono::duration(exposure) /\n> std::chrono::duration(lineLength);\n>  }\n>\n>  Duration CamHelper::exposure(uint32_t exposureLines, const Duration\n> lineLength) const\n> @@ -85,8 +85,8 @@ std::pair<uint32_t, uint32_t>\n> CamHelper::getBlanking(Duration &exposure,\n>   * frameLengthMax gets calculated on the smallest line length as we do\n>   * not want to extend that unless absolutely necessary.\n>   */\n> - frameLengthMin = minFrameDuration / mode_.minLineLength;\n> - frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> + frameLengthMin = std::chrono::duration(minFrameDuration) /\n> std::chrono::duration(mode_.minLineLength);\n> + frameLengthMax = std::chrono::duration(maxFrameDuration) /\n> std::chrono::duration(mode_.minLineLength);\n>\n>   /*\n>   * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> index ecb845e7..65f76c3c 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> @@ -57,7 +57,8 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n>  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n>   [[maybe_unused]] const Duration lineLength) const\n>  {\n> - return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) /\n> timePerLine);\n> + return std::max<uint32_t>(minExposureLines,\n> std::chrono::duration(exposure - 14.26us) /\n> + std::chrono::duration(timePerLine));\n>  }\n>\n>  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> index bd54a639..cfa5ed90 100644\n> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> @@ -418,7 +418,8 @@ void Agc::prepare(Metadata *imageMetadata)\n>   Duration actualExposure = deviceStatus.shutterSpeed *\n>    deviceStatus.analogueGain;\n>   if (actualExposure) {\n> - status_.digitalGain = status_.totalExposureValue / actualExposure;\n> + status_.digitalGain = std::chrono::duration(status_.totalExposureValue) /\n> + std::chrono::duration(actualExposure);\n>   LOG(RPiAgc, Debug) << \"Want total exposure \" <<\n> status_.totalExposureValue;\n>   /*\n>   * Never ask for a gain < 1.0, and also impose\n> @@ -823,7 +824,8 @@ void Agc::divideUpExposure()\n>   }\n>   if (status_.fixedAnalogueGain == 0.0) {\n>   if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {\n> - analogueGain = exposureValue / shutterTime;\n> + analogueGain = std::chrono::duration(exposureValue) /\n> + std::chrono::duration(shutterTime);\n>   break;\n>   }\n>   analogueGain = exposureMode_->gain[stage];\n> @@ -838,10 +840,12 @@ void Agc::divideUpExposure()\n>   */\n>   if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n>      status_.flickerPeriod) {\n> - int flickerPeriods = shutterTime / status_.flickerPeriod;\n> + int flickerPeriods = std::chrono::duration(shutterTime) /\n> + std::chrono::duration(status_.flickerPeriod);\n>   if (flickerPeriods) {\n>   Duration newShutterTime = flickerPeriods * status_.flickerPeriod;\n> - analogueGain *= shutterTime / newShutterTime;\n> + analogueGain *= std::chrono::duration(shutterTime) /\n> + std::chrono::duration(newShutterTime);\n>   /*\n>   * We should still not allow the ag to go over the\n>   * largest value in the exposure mode. Note that this\n> diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> index 9759186a..430642f0 100644\n> --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> @@ -94,7 +94,8 @@ void Lux::process(StatisticsPtr &stats, Metadata\n> *imageMetadata)\n>   double currentY = sum / (double)num + .5;\n>   double gainRatio = referenceGain_ / currentGain;\n>   double shutterSpeedRatio =\n> - referenceShutterSpeed_ / deviceStatus.shutterSpeed;\n> + std::chrono::duration(referenceShutterSpeed_) /\n> + std::chrono::duration(deviceStatus.shutterSpeed);\n>   double apertureRatio = referenceAperture_ / currentAperture;\n>   double yRatio = currentY * (65536 / numBins) / referenceY_;\n>   double estimatedLux = shutterSpeedRatio * gainRatio *\n> diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n> b/src/ipa/rkisp1/algorithms/agc.cpp\n> index 04062a36..e8814802 100644\n> --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> @@ -74,7 +74,8 @@ int Agc::configure(IPAContext &context, const\n> IPACameraSensorInfo &configInfo)\n>  {\n>   /* Configure the default exposure and gain. */\n>   context.activeState.agc.gain =\n> std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> - context.activeState.agc.exposure = 10ms /\n> context.configuration.sensor.lineDuration;\n> + context.activeState.agc.exposure = 10ms /\n> + std::chrono::duration(context.configuration.sensor.lineDuration);\n>\n>   /*\n>   * According to the RkISP1 documentation:\n> @@ -212,16 +213,19 @@ void Agc::computeExposure(IPAContext &context,\n> IPAFrameContext &frameContext,\n>   * Push the shutter time up to the maximum first, and only then\n>   * increase the gain.\n>   */\n> - utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue\n> / minAnalogueGain,\n> + utils::Duration shutterTime =\n> std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n> + minAnalogueGain,\n>    minShutterSpeed, maxShutterSpeed);\n> - double stepGain = std::clamp(exposureValue / shutterTime,\n> + double stepGain = std::clamp(std::chrono::duration(exposureValue) /\n> + std::chrono::duration(shutterTime),\n>       minAnalogueGain, maxAnalogueGain);\n>   LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n>        << shutterTime << \" and \"\n>        << stepGain;\n>\n>   /* Update the estimated exposure and gain. */\n> - activeState.agc.exposure = shutterTime /\n> configuration.sensor.lineDuration;\n> + activeState.agc.exposure = std::chrono::duration(shutterTime) /\n> + std::chrono::duration(configuration.sensor.lineDuration);\n>   activeState.agc.gain = stepGain;\n>  }\n>\n> --\n> 2.34.1\n>\n>\n> On Wed, Oct 26, 2022 at 3:51 AM Kieran Bingham <\n> kieran.bingham@ideasonboard.com> wrote:\n>\n>> Quoting Naushir Patuck (2022-10-26 09:46:51)\n>> > Hi,\n>> >\n>> > On Wed, 26 Oct 2022 at 09:24, Kieran Bingham via libcamera-devel <\n>> > libcamera-devel@lists.libcamera.org> wrote:\n>> >\n>> > > Quoting Nicholas Roth (2022-10-26 02:50:34)\n>> > > > Another possible fix is to cast libcamera::utils::Duration to\n>> > > > std::chrono::duration before performing division. I've tested that\n>> and it\n>> > > > works. Would folks be amenable to that instead?\n>> > >\n>> > > That sounds like we still have to make global updates. Are any of\n>> those\n>> > > locations where we should store a libcamera::utils::Duration instead\n>> of\n>> > > a std::chrono::duration to prevent having to cast?\n>> > >\n>> > > If casting works around the issue, is it sufficient / possible to\n>> > > provide an explicit casting operator? (I've never done this to more\n>> than\n>> > > the POD types, but it 'looks' like you can specify specific target\n>> > > classes as an operator?)\n>> > >\n>> > >   https://en.cppreference.com/w/cpp/language/cast_operator\n>> >\n>> >\n>> > Casting like this is indeed possible, but even then, the changes\n>> required\n>> > are spread across the codebase.  IMO this is undesirable for\n>> readability,\n>> > and error prone as any future developers must know to do this cast\n>> > if they were to do computations with utils::Duration.\n>> >\n>> > I hope there is a centralized solution with operator / overloading, but\n>> > if there's no choice...\n>>\n>> ahh, I thought that would allow the compiler to do the implicit casting,\n>> if the type was defined.\n>>\n>> But perhaps the clue is in the name \"cast_operator\"\n>>\n>> --\n>> Kieran\n>>\n>> >\n>> > Naush\n>> >\n>> >\n>> > >\n>> > > Something like (I have no idea if this is something that can work, or\n>> if\n>> > > it helps the compiler as it should already know the type?!)...:\n>> > >\n>> > > class Duration : public std::chrono::duration<double, std::nano>\n>> > > {\n>> > > ...\n>> > >\n>> > >         explicit operator std::chrono::duration() {\n>> > >                 return\n>> std::chrono::duration_cast<BaseDuration>>(*this);\n>> > >         }\n>> > >\n>> > > or perhaps 'worse' ? (but at least isolated to here in the class?)...\n>> > >\n>> > >         constexpr explicit operator double() {\n>> > >                 return get<std::nano>();\n>> > >         }\n>> > >\n>> > > ...\n>> > > }\n>> > >\n>> > > --\n>> > > Kieran\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 0428CBDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Oct 2022 14:26:32 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B387F61F4B;\n\tWed, 26 Oct 2022 16:26:32 +0200 (CEST)","from mail-qk1-x731.google.com (mail-qk1-x731.google.com\n\t[IPv6:2607:f8b0:4864:20::731])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id BD10E61F4B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 16:26:30 +0200 (CEST)","by mail-qk1-x731.google.com with SMTP id d13so10614532qko.5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 07:26:30 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666794392;\n\tbh=bXV1GqoXRA0NCWb+RR/cvgxuU6IuDgyEfc+1FdaesgE=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=ExvvPVBdF+HcTsvTfy4AV9SGp4QhGxD1wVLI07CS8Kqu02sxsy5koEufuJzX6JX1Q\n\tldE8yrcNGBJ2Q/DyDIla6BMEi8IaHqT9gRhT01OZ7qHztuWvYN1UizDUgQo+BojJ54\n\tSkSCFOzW0EXXdRyjSFyMGMUugVDOAl4wiAedueJ3pg9UOeYKi4oX6UMaXVu7cvVllM\n\tmleBOwwiso0pHt3KVV9Mw8vmg49qF0RBdmAOqhKgjWIMJHiBqWcL5JCH+dsPJAGI8g\n\twjAt/OEG/NR9rZPPmVgkMThvhJ8vJK4OykWHMWLcnLVtfL3H/hsY0z9We22W0Yboi+\n\tFpqt8ULeuFVIQ==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=TpqLCGunqXz5PnjKIxnLdOyWpdUNjp99kWL2+6RbAIk=;\n\tb=N2i3WuvMXpIO5sqZcHN99N1s3UoKVgEnLgA5QGgfkTwMcVKQv2Db5u0VqFH84ttv7n\n\tZCFiNAXENjUeoOjsTpNco5Ed8DOdk8wkAwUH6U7z6UjubQrsjNf3/u6Z/LE5T4tp/5x5\n\tPNosRv4xIKVszTjgXycTrcWy/LPbgs6KkWS+GyWCi6Jzb30gSzm4RibHdDvF9AGYZlWV\n\tQ+xmw9UginFz/0KB9+4vXQCw8DKNN+gZDdgA6QBNYlS/aFMatbPWEKwUAi+bfej8iBzG\n\tDlDWfBVJA2qXM3RXxuceMEhABPIZxF1PljInAWpiou/hUgQWaRkVvZV0TwBrnJBYAiXY\n\t3RbA=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"N2i3WuvM\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=TpqLCGunqXz5PnjKIxnLdOyWpdUNjp99kWL2+6RbAIk=;\n\tb=yJfazRFrXx/OmTJg/PlPnGInu7Y6PgNOXswvoxFryMd8uH89/4zkXL01ruqoTU2Yr8\n\t1cCTU0KFFR+gFAS1nLk+Ff/yeao6mWkhvHOFFvPle9butnVtxXIUrpEixyfSkLX5a6JF\n\tnAZAGscgOPS4JelOite9AX34U+BjlpoUI2GWUrjSHRCBrvUJbmbPTSljzR3dnKQ7wkhO\n\tCPA8hD8eX+9Uz/WmwnxU2V9cPzHZ4Yn/ahFjpXXMpQ2rOZSW9WcPDNiC4FrF0YbNNMRp\n\tLUh23AUIYS3AkNf35pkal6kZyx0HyzJXxvaSbp9lCbiU4KiIkC1U1a6ZyWlU92/3vpqx\n\tq6tA==","X-Gm-Message-State":"ACrzQf0JMORMzkUHPCltXTMXPZwhSeZg8sc/FAfrM6NjBw6N4JcwZ1iF\n\txpWuzJj3nIJVEjYxFATog+ZZ7afnFIkvNTVMR5asMvsprhNl/w==","X-Google-Smtp-Source":"AMsMyM7++JNzhJhMec0o7VdIpyFRoSZniR1DRCBIAvQYpKuCaHAPyFc8Q+0tRAZ7ZRglCIbpnKvQMxrORbWXS7B/mj4=","X-Received":"by 2002:ae9:f310:0:b0:6f9:90bb:4988 with SMTP id\n\tp16-20020ae9f310000000b006f990bb4988mr1180132qkg.379.1666794389600;\n\tWed, 26 Oct 2022 07:26:29 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>\n\t<166677268158.3974115.15111815458042537047@Monstersaurus>\n\t<CAEmqJPpZBckB1gRr25UsmDp623J3Fzj7LXxJZmHKj_YSBiqDnQ@mail.gmail.com>\n\t<166677431137.3974115.16374594371777153094@Monstersaurus>\n\t<CAD2rFCo5NDktCzmmEOXQmrxsuAvCA8q8tms48hYWA+eYvkfPJA@mail.gmail.com>","In-Reply-To":"<CAD2rFCo5NDktCzmmEOXQmrxsuAvCA8q8tms48hYWA+eYvkfPJA@mail.gmail.com>","Date":"Wed, 26 Oct 2022 15:26:13 +0100","Message-ID":"<CAEmqJPoow7Aw3KXojrKiUf6zxCC8bb0k-4TPpH-x6gg=PSwS0A@mail.gmail.com>","To":"Nicholas Roth <nicholas@rothemail.net>","Content-Type":"multipart/alternative; boundary=\"00000000000081925405ebf0cfe3\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Naushir Patuck via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Naushir Patuck <naush@raspberrypi.com>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25614,"web_url":"https://patchwork.libcamera.org/comment/25614/","msgid":"<CAD2rFCpeacgrnKDB_nmOXddnV5yYhJ20AhfwybBsuJ2G2B5dag@mail.gmail.com>","date":"2022-10-27T03:11:25","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":137,"url":"https://patchwork.libcamera.org/api/people/137/","name":"Nicholas Roth","email":"nicholas@rothemail.net"},"content":"Naushir,\n\nI really wanted to be wrong and was hoping that you cracked the code! But.\nWhile the example above compiles in isolation, I still get the following\nerror in SDK30 when I undo my fixes:\n\nIn file included from ../src/ipa/rkisp1/algorithms/agc.cpp:8:\nIn file included from ../src/ipa/rkisp1/algorithms/agc.h:12:\nIn file included from ../include/libcamera/base/utils.h:11:\n/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1273:81:\nerror: no type named 'type' in 'std::__1::common_type<long long,\nlibcamera::utils::Duration>'\n                          typename common_type<typename _Duration::rep,\n_Rep2>::type>::value>\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~\n/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1286:7:\nnote: in instantiation of default argument for\n'__duration_divide_imp<std::__1::chrono::duration<long long,\nstd::__1::ratio<1, 1000> >, libcamera::utils::Duration>' required here\n    : __duration_divide_imp<duration<_Rep1, _Period>, _Rep2>\n      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n/media/nroth/BIGLINUX/lineageos/external/libcxx/include/chrono:1293:10:\nnote: in instantiation of template class\n'std::__1::chrono::__duration_divide_result<std::__1::chrono::duration<long\nlong, std::__1::ratio<1, 1000> >, libcamera::utils::Duration, false>'\nrequested here\ntypename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type\n         ^\n../src/ipa/rkisp1/algorithms/agc.cpp:81:30: note: while substituting\ndeduced template arguments into function template 'operator/' [with _Rep1 =\nlong long, _Period = std::__1::ratio<1, 1000>, _Rep2 =\nlibcamera::utils::Duration]\n        long double exposure = 10ms /\ncontext.configuration.sensor.lineDuration;\n                                    ^\n1 error generated.\n\n\nOn Wed, Oct 26, 2022 at 9:26 AM Naushir Patuck <naush@raspberrypi.com>\nwrote:\n\n> On Wed, 26 Oct 2022 at 14:28, Nicholas Roth <nicholas@rothemail.net>\n> wrote:\n>\n>> Naushir,\n>> > I hope there is a centralized solution with operator / overloading, but\n>> > if there's no choice...\n>>\n>> The only centralized solution I've been able to find with operator/ that\n>> *might* work has some major limitations. Namely, it only really works\n>> when the LHS is a libcamera::utils::Duration and you get weird errors when\n>> it's on the RHS. I can't overload at the namespace level because then it\n>> causes ambiguity with (sometimes even linker errors with) existing\n>> std::chrono overloads.\n>>\n>\n> I've briefly tried the following snippet of code:\n>\n> ---\n>\n> diff --git a/include/libcamera/base/utils.h\n> b/include/libcamera/base/utils.h\n> index eb7bcdf4c173..ebcd56475b17 100644\n> --- a/include/libcamera/base/utils.h\n> +++ b/include/libcamera/base/utils.h\n> @@ -358,6 +358,32 @@ public:\n>         }\n>  };\n>\n> +inline double operator/(const Duration &num, const Duration &den)\n> +{\n> +       double n = num.get<std::nano>();\n> +       double d = den.get<std::nano>();\n> +\n> +       return n / d;\n> +}\n> +\n> +template<typename Rep, typename Period>\n> +inline double operator/(const Duration &num, const\n> std::chrono::duration<Rep, Period> &den)\n> +{\n> +       double n = num.get<std::nano>();\n> +       double d =\n> (std::chrono::duration_cast<std::chrono::duration<double,\n> std::nano>>(den)).count();\n> +\n> +       return n / d;\n> +}\n> +\n> +template<typename Rep, typename Period>\n> +inline double operator/(const std::chrono::duration<Rep, Period> &num,\n> const Duration &den)\n> +{\n> +       double n =\n> (std::chrono::duration_cast<std::chrono::duration<double,\n> std::nano>>(num)).count();\n> +       double d = den.get<std::nano>();\n> +\n> +       return n / d;\n> +}\n> +\n>  template<typename T>\n>  decltype(auto) abs_diff(const T &a, const T &b)\n>\n> ---\n> It compiles/links ok on clang 11.0.1 (the only version of clang-11 that is\n> available on my platform, but does not exactly match your version).\n> Functionally it seems to do the right thing as well.\n> Are you able to try this out in your environment to see if it resolves\n> your compile issues?\n>\n> Regards,\n> Naush\n>\n>\n>>\n>> Kieran,\n>> > That sounds like we still have to make global updates. Are any of those\n>> > locations where we should store a libcamera::utils::Duration instead of\n>> > a std::chrono::duration to prevent having to cast?\n>> Did you mean vice versa (store a std::chrono::duration instead of\n>> libcamera::utils::Duration)? That would fix it, but from my understanding\n>> that would miss the point of standardizing around a double-width floating\n>> point representation at std::nano timebase.\n>>\n>> > If casting works around the issue, is it sufficient / possible to\n>> > provide an explicit casting operator? (I've never done this to more than\n>> > the POD types, but it 'looks' like you can specify specific target\n>> > classes as an operator?)\n>>\n>> I'm not sure what this would accomplish. I've been able to upcast\n>> libcamera::utils::Duration to std::chrono::duration with just\n>> `std::chrono::duration(x)` without adding an operator. Note that this seems\n>> to have nuked my <TAB>s, which I used instead of spaces for indentation to\n>> be consistent with surrounding code.\n>>\n>> I'm also appending the proposed v2 of this patch below to add clarity to\n>> what I propose:\n>> From 4efd469a63288b89c65be45ea1724ccde4ec486f Mon Sep 17 00:00:00 2001\n>> From: Nicholas Roth <nicholas@rothemail.net>\n>> Date: Mon, 24 Oct 2022 00:03:25 -0500\n>> Subject: [PATCH 1/3] ipa: workaround libcxx duration limitation\n>>\n>> A bug in libcxx [0] used by clang version 11.0.2 is prevalent when\n>> building libcamera for Android SDK30. This has been fixed and\n>> integrated upstream with [1].\n>>\n>> As a workaround, directly cast libcamera::utils::Duration objects to\n>> std::chrono::duration when dividing.\n>>\n>> Alternatives evaluated:\n>> Considered: Enable public inheritance of std::chrono::duration and\n>> override operator/ in the class.\n>> Outcome: Does not fix the original compiler error.\n>>\n>> Considered: Enable public inheritance of std::chrono::duration and\n>> override operator/ in the libcamera namespace.\n>> Outcome: new compiler error:\n>> ld.lld: error: duplicate symbol: libcamera::operator/\n>> (libcamera::utils::Duration const&, libcamera::utils::Duration const&)\n>>\n>> Considered: Use private inheritance of std::chrono::duration and\n>> re-implement a pass-through version of each std::chrono::duration\n>> operator within libcamera::utils::Duration and use template\n>> metaprogramming to fix the division operator.\n>> Outcome: Testing shows that this would introduce substantial\n>> limitations, i.e. requring the Duration object to be on the LHS of any\n>> arithmetic operation with other numeric types. This also substantially\n>> increases implementation complexity.\n>>\n>> Considered: Extract double values from libcamera::utils::Duration\n>> objects and use those to divide.\n>> Outcome: This creates substantial readability and unit-safety issues.\n>>\n>> [0] https://github.com/llvm/llvm-project/issues/40475\n>> [1]\n>> https://github.com/llvm/llvm-project/commit/efa6d803c624f9251d0ab7881122501bb9d27368\n>> Bug: https://bugs.libcamera.org/show_bug.cgi?id=156\n>>\n>> Signed-off-by: Nicholas Roth <nicholas@rothemail.net>\n>> ---\n>>  src/ipa/ipu3/algorithms/agc.cpp            | 17 +++++++++++------\n>>  src/ipa/raspberrypi/cam_helper.cpp         |  6 +++---\n>>  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  3 ++-\n>>  src/ipa/raspberrypi/controller/rpi/agc.cpp | 12 ++++++++----\n>>  src/ipa/raspberrypi/controller/rpi/lux.cpp |  3 ++-\n>>  src/ipa/rkisp1/algorithms/agc.cpp          | 12 ++++++++----\n>>  6 files changed, 34 insertions(+), 19 deletions(-)\n>>\n>> diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n>> b/src/ipa/ipu3/algorithms/agc.cpp\n>> index a1a3c38f..1d8518da 100644\n>> --- a/src/ipa/ipu3/algorithms/agc.cpp\n>> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n>> @@ -100,7 +100,8 @@ int Agc::configure(IPAContext &context,\n>>\n>>   /* Configure the default exposure and gain. */\n>>   activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n>> - activeState.agc.exposure = 10ms / configuration.sensor.lineDuration;\n>> + activeState.agc.exposure = 10ms /\n>> + std::chrono::duration(configuration.sensor.lineDuration);\n>>\n>>   frameCount_ = 0;\n>>   return 0;\n>> @@ -240,17 +241,21 @@ void Agc::computeExposure(IPAContext &context,\n>> IPAFrameContext &frameContext,\n>>   * increase the gain.\n>>   */\n>>   utils::Duration shutterTime =\n>> - std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,\n>> -    minShutterSpeed_, maxShutterSpeed_);\n>> - double stepGain = std::clamp(exposureValue / shutterTime,\n>> -     minAnalogueGain_, maxAnalogueGain_);\n>> + std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n>> + std::chrono::duration(minAnalogueGain_),\n>> +    minShutterSpeed_, maxShutterSpeed_);\n>> + double stepGain = std::clamp(std::chrono::duration(exposureValue) /\n>> + std::chrono::duration(shutterTime),\n>> + minAnalogueGain_, maxAnalogueGain_);\n>>   LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n>>      << shutterTime << \" and \"\n>>      << stepGain;\n>>\n>>   IPAActiveState &activeState = context.activeState;\n>>   /* Update the estimated exposure and gain. */\n>> - activeState.agc.exposure = shutterTime /\n>> configuration.sensor.lineDuration;\n>> + double lineDurationDouble = .get<std::nano>();\n>> + activeState.agc.exposure = std::chrono::duration(shutterTimeDouble) /\n>> + std::chrono::duration(configuration.sensor.lineDuration);\n>>   activeState.agc.gain = stepGain;\n>>  }\n>>\n>> diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n>> b/src/ipa/raspberrypi/cam_helper.cpp\n>> index d90ac1de..48a8a068 100644\n>> --- a/src/ipa/raspberrypi/cam_helper.cpp\n>> +++ b/src/ipa/raspberrypi/cam_helper.cpp\n>> @@ -63,7 +63,7 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr\n>> &stats,\n>>\n>>  uint32_t CamHelper::exposureLines(const Duration exposure, const\n>> Duration lineLength) const\n>>  {\n>> - return exposure / lineLength;\n>> + return std::chrono::duration(exposure) /\n>> std::chrono::duration(lineLength);\n>>  }\n>>\n>>  Duration CamHelper::exposure(uint32_t exposureLines, const Duration\n>> lineLength) const\n>> @@ -85,8 +85,8 @@ std::pair<uint32_t, uint32_t>\n>> CamHelper::getBlanking(Duration &exposure,\n>>   * frameLengthMax gets calculated on the smallest line length as we do\n>>   * not want to extend that unless absolutely necessary.\n>>   */\n>> - frameLengthMin = minFrameDuration / mode_.minLineLength;\n>> - frameLengthMax = maxFrameDuration / mode_.minLineLength;\n>> + frameLengthMin = std::chrono::duration(minFrameDuration) /\n>> std::chrono::duration(mode_.minLineLength);\n>> + frameLengthMax = std::chrono::duration(maxFrameDuration) /\n>> std::chrono::duration(mode_.minLineLength);\n>>\n>>   /*\n>>   * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a\n>> diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> index ecb845e7..65f76c3c 100644\n>> --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n>> @@ -57,7 +57,8 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n>>  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n>>   [[maybe_unused]] const Duration lineLength) const\n>>  {\n>> - return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) /\n>> timePerLine);\n>> + return std::max<uint32_t>(minExposureLines,\n>> std::chrono::duration(exposure - 14.26us) /\n>> + std::chrono::duration(timePerLine));\n>>  }\n>>\n>>  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n>> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> index bd54a639..cfa5ed90 100644\n>> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n>> @@ -418,7 +418,8 @@ void Agc::prepare(Metadata *imageMetadata)\n>>   Duration actualExposure = deviceStatus.shutterSpeed *\n>>    deviceStatus.analogueGain;\n>>   if (actualExposure) {\n>> - status_.digitalGain = status_.totalExposureValue / actualExposure;\n>> + status_.digitalGain = std::chrono::duration(status_.totalExposureValue)\n>> /\n>> + std::chrono::duration(actualExposure);\n>>   LOG(RPiAgc, Debug) << \"Want total exposure \" <<\n>> status_.totalExposureValue;\n>>   /*\n>>   * Never ask for a gain < 1.0, and also impose\n>> @@ -823,7 +824,8 @@ void Agc::divideUpExposure()\n>>   }\n>>   if (status_.fixedAnalogueGain == 0.0) {\n>>   if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {\n>> - analogueGain = exposureValue / shutterTime;\n>> + analogueGain = std::chrono::duration(exposureValue) /\n>> + std::chrono::duration(shutterTime);\n>>   break;\n>>   }\n>>   analogueGain = exposureMode_->gain[stage];\n>> @@ -838,10 +840,12 @@ void Agc::divideUpExposure()\n>>   */\n>>   if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n>>      status_.flickerPeriod) {\n>> - int flickerPeriods = shutterTime / status_.flickerPeriod;\n>> + int flickerPeriods = std::chrono::duration(shutterTime) /\n>> + std::chrono::duration(status_.flickerPeriod);\n>>   if (flickerPeriods) {\n>>   Duration newShutterTime = flickerPeriods * status_.flickerPeriod;\n>> - analogueGain *= shutterTime / newShutterTime;\n>> + analogueGain *= std::chrono::duration(shutterTime) /\n>> + std::chrono::duration(newShutterTime);\n>>   /*\n>>   * We should still not allow the ag to go over the\n>>   * largest value in the exposure mode. Note that this\n>> diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> index 9759186a..430642f0 100644\n>> --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n>> @@ -94,7 +94,8 @@ void Lux::process(StatisticsPtr &stats, Metadata\n>> *imageMetadata)\n>>   double currentY = sum / (double)num + .5;\n>>   double gainRatio = referenceGain_ / currentGain;\n>>   double shutterSpeedRatio =\n>> - referenceShutterSpeed_ / deviceStatus.shutterSpeed;\n>> + std::chrono::duration(referenceShutterSpeed_) /\n>> + std::chrono::duration(deviceStatus.shutterSpeed);\n>>   double apertureRatio = referenceAperture_ / currentAperture;\n>>   double yRatio = currentY * (65536 / numBins) / referenceY_;\n>>   double estimatedLux = shutterSpeedRatio * gainRatio *\n>> diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n>> b/src/ipa/rkisp1/algorithms/agc.cpp\n>> index 04062a36..e8814802 100644\n>> --- a/src/ipa/rkisp1/algorithms/agc.cpp\n>> +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n>> @@ -74,7 +74,8 @@ int Agc::configure(IPAContext &context, const\n>> IPACameraSensorInfo &configInfo)\n>>  {\n>>   /* Configure the default exposure and gain. */\n>>   context.activeState.agc.gain =\n>> std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n>> - context.activeState.agc.exposure = 10ms /\n>> context.configuration.sensor.lineDuration;\n>> + context.activeState.agc.exposure = 10ms /\n>> + std::chrono::duration(context.configuration.sensor.lineDuration);\n>>\n>>   /*\n>>   * According to the RkISP1 documentation:\n>> @@ -212,16 +213,19 @@ void Agc::computeExposure(IPAContext &context,\n>> IPAFrameContext &frameContext,\n>>   * Push the shutter time up to the maximum first, and only then\n>>   * increase the gain.\n>>   */\n>> - utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue\n>> / minAnalogueGain,\n>> + utils::Duration shutterTime =\n>> std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n>> + minAnalogueGain,\n>>    minShutterSpeed, maxShutterSpeed);\n>> - double stepGain = std::clamp(exposureValue / shutterTime,\n>> + double stepGain = std::clamp(std::chrono::duration(exposureValue) /\n>> + std::chrono::duration(shutterTime),\n>>       minAnalogueGain, maxAnalogueGain);\n>>   LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n>>        << shutterTime << \" and \"\n>>        << stepGain;\n>>\n>>   /* Update the estimated exposure and gain. */\n>> - activeState.agc.exposure = shutterTime /\n>> configuration.sensor.lineDuration;\n>> + activeState.agc.exposure = std::chrono::duration(shutterTime) /\n>> + std::chrono::duration(configuration.sensor.lineDuration);\n>>   activeState.agc.gain = stepGain;\n>>  }\n>>\n>> --\n>> 2.34.1\n>>\n>>\n>> On Wed, Oct 26, 2022 at 3:51 AM Kieran Bingham <\n>> kieran.bingham@ideasonboard.com> wrote:\n>>\n>>> Quoting Naushir Patuck (2022-10-26 09:46:51)\n>>> > Hi,\n>>> >\n>>> > On Wed, 26 Oct 2022 at 09:24, Kieran Bingham via libcamera-devel <\n>>> > libcamera-devel@lists.libcamera.org> wrote:\n>>> >\n>>> > > Quoting Nicholas Roth (2022-10-26 02:50:34)\n>>> > > > Another possible fix is to cast libcamera::utils::Duration to\n>>> > > > std::chrono::duration before performing division. I've tested that\n>>> and it\n>>> > > > works. Would folks be amenable to that instead?\n>>> > >\n>>> > > That sounds like we still have to make global updates. Are any of\n>>> those\n>>> > > locations where we should store a libcamera::utils::Duration instead\n>>> of\n>>> > > a std::chrono::duration to prevent having to cast?\n>>> > >\n>>> > > If casting works around the issue, is it sufficient / possible to\n>>> > > provide an explicit casting operator? (I've never done this to more\n>>> than\n>>> > > the POD types, but it 'looks' like you can specify specific target\n>>> > > classes as an operator?)\n>>> > >\n>>> > >   https://en.cppreference.com/w/cpp/language/cast_operator\n>>> >\n>>> >\n>>> > Casting like this is indeed possible, but even then, the changes\n>>> required\n>>> > are spread across the codebase.  IMO this is undesirable for\n>>> readability,\n>>> > and error prone as any future developers must know to do this cast\n>>> > if they were to do computations with utils::Duration.\n>>> >\n>>> > I hope there is a centralized solution with operator / overloading, but\n>>> > if there's no choice...\n>>>\n>>> ahh, I thought that would allow the compiler to do the implicit casting,\n>>> if the type was defined.\n>>>\n>>> But perhaps the clue is in the name \"cast_operator\"\n>>>\n>>> --\n>>> Kieran\n>>>\n>>> >\n>>> > Naush\n>>> >\n>>> >\n>>> > >\n>>> > > Something like (I have no idea if this is something that can work,\n>>> or if\n>>> > > it helps the compiler as it should already know the type?!)...:\n>>> > >\n>>> > > class Duration : public std::chrono::duration<double, std::nano>\n>>> > > {\n>>> > > ...\n>>> > >\n>>> > >         explicit operator std::chrono::duration() {\n>>> > >                 return\n>>> std::chrono::duration_cast<BaseDuration>>(*this);\n>>> > >         }\n>>> > >\n>>> > > or perhaps 'worse' ? (but at least isolated to here in the class?)...\n>>> > >\n>>> > >         constexpr explicit operator double() {\n>>> > >                 return get<std::nano>();\n>>> > >         }\n>>> > >\n>>> > > ...\n>>> > > }\n>>> > >\n>>> > > --\n>>> > > Kieran\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 A66CEBDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Oct 2022 03:11:40 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id ABA0962F67;\n\tThu, 27 Oct 2022 05:11:39 +0200 (CEST)","from mail-io1-xd2c.google.com (mail-io1-xd2c.google.com\n\t[IPv6:2607:f8b0:4864:20::d2c])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CC94561F4A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Oct 2022 05:11:37 +0200 (CEST)","by mail-io1-xd2c.google.com with SMTP id p141so347329iod.6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 20:11:37 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666840299;\n\tbh=8mSQkN7K4HlLn3ZgrR2NqC1y+RJEzi4EfzZ7BArnsZA=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=Z5tP7Hx7s09h895eQMcTAwEym8vtVKY4NtQOXHDNO0uWUHy1yZvYCPrthAaMEJSZd\n\t5L5NRwVpljIOoB4K0egMHHhb974pb4N3QeBc4cRnSA3NGkiS8IAwJznNJT5xhJifGm\n\tQV4AIv2joHhdMqgRaCs4q6UX84BL1w14Df6ULElK8Ajdx/30ZrhcJBnWNaWfkA5i0S\n\tKk4VwkgeKZi9ZLduDAYNbGXYf4/4BlbculoVJKTywJHRwlUO0BhLtNnMQVtixox3DX\n\tHk2D8/HBxW5r3FKM4RuiY3M1lJ53UbJqMg/dj1khW3wH3MOf+dcZSKyczB5LcIoosq\n\tSJEFgK0ogB+Mw==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=rothemail-net.20210112.gappssmtp.com; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=bJKqYniJM8qZXPZt1m4DnFFgX/Vcxb/F1Fft1HTrlVk=;\n\tb=FwrYt7Tt4e0e+hnCiS9uyQf0EyOeAxeq0qpgVCAeu8tMdFpJPXPHTsse80Hpkg49fZ\n\tJ4P4zS6AJaIKHqrIHBfCRaFMHdw1DNSJ3OP5CSCqqMnJ7LAW193b2he9EEjusiPoqFj8\n\tBuotnRXVIOk1dlqZUyxGRkGWKV2JLuPhztXDFznJt+HBTAu9CPbRprCwOhWdxLHuDkn3\n\tj3ReA0gUO2IAQpJZlxguTqr2yxh4YWoelNMIrQpL9rpcms0ccwM+jQDYIExk0aNSi2xx\n\t7PKzfTltYoUFsAG+FYqNP6TFBF2D9V7ve7W+WcoHXDnkhF6Lctv8lrno78XEQ691mu6t\n\tb2Pw=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=rothemail-net.20210112.gappssmtp.com\n\theader.i=@rothemail-net.20210112.gappssmtp.com header.b=\"FwrYt7Tt\"; \n\tdkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=bJKqYniJM8qZXPZt1m4DnFFgX/Vcxb/F1Fft1HTrlVk=;\n\tb=TN1TcwSASauL5xAaGuYq8kZfauakMZAyKKYYJWm1EsjE7WoKBWfhgtmNzjqQD5pYWw\n\tWxn8j6gTYvWEMAQjJQx8yLRWKklqW35CQEwBoJaLEpNvSJlOdAerrtf59QqCkuOGcnZi\n\tJzU+M0hUmA3L2ruzQPfbF4/tawVuV1VxL5KwWtwGnl9kwlojE35pkWwtWETyeGM+IVwE\n\tbg6FOmn/HWRtJAkfyOamE9X951J5rEQmnE005wTAcuJG9K6BLKQQcUeRg3Pg6R7Ntxr7\n\twg8sI8DKJPF5Oyd3bF/9lwYEBS+iN+l5hSX7+gsQkVvv59WIXqYZRoDW5T5zBOPjpydZ\n\t68AA==","X-Gm-Message-State":"ACrzQf1XO/yi/KkWL8RHn8P9TZ40VKzicfoW7CkwrxqhwAu7PhhT3KN5\n\tOawCOemwoOcelr6ZkfjSP8fFsfmhHRMG/E5MIg+yHg==","X-Google-Smtp-Source":"AMsMyM5GbnxOsdNBI9EGoMZ5K0vOzZvoJRmtgzc7cacxPL4F/0vW4iQQHznPgMjonrxZ0hxuNo5U2CL+k3eDDRru/+s=","X-Received":"by 2002:a05:6602:154f:b0:6bc:f701:cb37 with SMTP id\n\th15-20020a056602154f00b006bcf701cb37mr29244871iow.136.1666840296199;\n\tWed, 26 Oct 2022 20:11:36 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCo-9g3bx5CsNuFp0Xdx76qBmvgfh3L1H=SB2yDCNxAdOQ@mail.gmail.com>\n\t<166677268158.3974115.15111815458042537047@Monstersaurus>\n\t<CAEmqJPpZBckB1gRr25UsmDp623J3Fzj7LXxJZmHKj_YSBiqDnQ@mail.gmail.com>\n\t<166677431137.3974115.16374594371777153094@Monstersaurus>\n\t<CAD2rFCo5NDktCzmmEOXQmrxsuAvCA8q8tms48hYWA+eYvkfPJA@mail.gmail.com>\n\t<CAEmqJPoow7Aw3KXojrKiUf6zxCC8bb0k-4TPpH-x6gg=PSwS0A@mail.gmail.com>","In-Reply-To":"<CAEmqJPoow7Aw3KXojrKiUf6zxCC8bb0k-4TPpH-x6gg=PSwS0A@mail.gmail.com>","Date":"Wed, 26 Oct 2022 22:11:25 -0500","Message-ID":"<CAD2rFCpeacgrnKDB_nmOXddnV5yYhJ20AhfwybBsuJ2G2B5dag@mail.gmail.com>","To":"Naushir Patuck <naush@raspberrypi.com>","Content-Type":"multipart/alternative; boundary=\"000000000000c0b0c105ebfb7fba\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Nicholas Roth <nicholas@rothemail.net>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25617,"web_url":"https://patchwork.libcamera.org/comment/25617/","msgid":"<CAD2rFCqEw9NrSOqOJc6+EpDOmh320f0fF4qxtDyxd1hidsHbuA@mail.gmail.com>","date":"2022-10-27T04:24:28","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":137,"url":"https://patchwork.libcamera.org/api/people/137/","name":"Nicholas Roth","email":"nicholas@rothemail.net"},"content":">  cp utils/hooks/post-commit .git/hooks/post-commit\nThe post-commits seem to want me to replace my tabs with spaces. I use tabs\nto be consistent with the surrounding codebase. Is it OK to ignore these\nerrors, or should I do something else?\n\nExample:\n--- src/android/camera_hal_config.cpp\n+++ src/android/camera_hal_config.cpp\n@@ -164,7 +164,7 @@\n        File file(filePath);\n        if (!file.exist()) {\n                LOG(HALConfig, Debug)\n-                                       << \"Configuration file: \\\"\" <<\nfilePath << \"\\\" not found\";\n+                       << \"Configuration file: \\\"\" << filePath << \"\\\" not\nfound\";\n                return -ENOENT;\n        }\n\n---\n1 potential issue detected, please review\n\n\nOn Tue, Oct 25, 2022 at 6:14 AM Kieran Bingham <\nkieran.bingham@ideasonboard.com> wrote:\n\n> Quoting Nicholas Roth via libcamera-devel (2022-10-25 04:15:36)\n> > > Could I ask you to read https://cbea.ms/git-commit/ please?\n> > Read. I thought that was quite informative. I noticed some differences\n> > between the style suggested in the blog post and the commit messages you\n> > suggest. Indeed, I have generally foregone good history in favor of\n>\n> Style differences are fine. Content is King. We won't merge patches that\n> say \"Latest code\" or \"fixes foo\". I like to break things down to cover\n> three points, but it doesn't always apply. Capturing rationale is the\n> important part.\n>\n>\n> prefix: of: components: Clear subject\n>\n>  - What is wrong\n>  - What this patch does\n>  - Why it does it (the way it does)\n>\n> Signed-off-by: <author>\n>\n>\n>\n>  Subject: ships: argo: Increase sailers on the Argo\n>\n>  The Argo is insuffienctly staffed and incapable of slaying any\n>  dragons, (or managing any other adventures accordingly).\n>\n>  To avoid mortal peril beyond expectations, staff the Argo with at\n>  least 50 of the finest Heroes available.\n>\n>  The target of 50 has been reached according to the size of the vessel,\n>  and the number of beds available for resting during the journey, as\n>  well as examining the food supplies that are expected to last over the\n>  extended travel period.\n>\n>  The return Journey may have a reduced staffing level, but this is not\n>  desired. Staffing levels should be kept as close to the maximum level\n>  as possible at all times.\n>\n>  Signed-off-by: Jason of Aeson <jason@argonauts.org>\n>  ---\n>  diff --git a/ships/argo b/ships/argo\n>  index c9a40e8788e7..e257b2e257b4 100644\n>  --- a/ships/argo\n>  +++ b/ships/argo\n>  @@ -1 +1 @@\n>  -staff-level: 0\n>  +staff-level: 50\n>\n>\n>\n> Why do I have a sudden urge to write an anthology of mythological\n> stories in patch form ?\n>\n>\n> > convenience in git projects, and I hope it will be interesting to\n> > experience the advantages of clear history and educational to learn how\n> > this looks in a Git project.\n>\n> Please feel free to look through the commit history of libcamera. We're\n> over 4000 commits now, and I would really hope that a vast majority\n> would be considered as good examples of commits. (we do allow some slack\n> at times... - justifying a typo is usually quite short :D )\n>\n>  - https://git.libcamera.org/libcamera/libcamera.git/log/\n>\n> We mostly come with a background (and continuation) in Linux Kernel\n> development, where keeping this history is cruicial due to the scale of\n> the kernel. It could be argued that it's not crucial to the same level\n> at libcamera, but I believe it's good development practice to maintain\n> clear commits throughout.\n>\n> The commit messages usually come into their own when bisecting failures,\n> or looking through git-blame to see /why/ a line of code is the way it\n> is.\n>\n> Ah yes, also we expect bisectability - so each commit should compile and\n> be functional as an independent task, while aiming to do one thing per\n> patch.\n>\n>\n> > This might also be a good place to ask about a style guide for your code.\n> > I've done my best to be consistent with surrounding code, but it would be\n> > helpful to have something more concrete, maybe even someone's .vimrc if\n> > that's available.\n>\n> We have tooling in place to help already.\n>  -\n> https://git.libcamera.org/libcamera/libcamera.git/tree/utils/hooks/post-commit\n>\n> To utilise this hook, install this file with:\n>   cp utils/hooks/post-commit .git/hooks/post-commit\n>\n> That will run our commit style checks on every commit.\n> I prefer doing it as a post-commit so you can still commit with\n> failures. pre-commit is usually too 'harsh'.\n>\n> Beyond that, we have some documentation on the subject at:\n>  - https://libcamera.org/contributing.html\n> and\n>  - https://libcamera.org/coding-style.html\n>\n> But I'm sure this is always something that needs more work on\n> documenting, or making it easier to read/find.\n>\n>\n>\n> > > I wonder if it would be possible to overload \"operator /\" for the\n> > utils::Duration type\n> > Gives an error: multiple definitions.\n> > > Or, if that can't be done for the Duration type only, somehow override\n> > the std::chrono::duration::operator/() globally\n> > In global namespace: compiler error\n>\n> What's the compiler error here ?\n>\n>\n> > In the class itself: read on\n> >\n> > My power is out but I’ll follow up with the actual compiler errors\n> sometime\n> > tomorrow.\n> >\n> > I’ve come up with a centralized solution that might work, but it’s not\n> > ideal either. I’d like to get your thoughts here before going further:\n> > * Make the chrono baseclass private to resolve ambiguity\n> > * Implement all of the usual operators i.e. +, -, /, * inside the class\n> > (even friend functions can’t see private base classes, oddly enough)\n> >\n> > This might also involve some template metaprogramming but I’m trying hard\n> > to do without it.\n>\n> Ayee, this sounds like more work ... which is painful. I'd be interested\n> to see what the compiler error is for the operator/() is to see if\n> that's a shorter solution.\n>\n> --\n> Kieran\n>\n>\n> >\n> > -Nicholas\n> >\n> >\n> > On Mon, Oct 24, 2022 at 8:30 AM Laurent Pinchart <\n> > laurent.pinchart@ideasonboard.com> wrote:\n> >\n> > > On Mon, Oct 24, 2022 at 11:50:53AM +0100, Naushir Patuck via\n> > > libcamera-devel wrote:\n> > > > Hi Nicholas,\n> > > >\n> > > > Thank you for your patch.\n> > > >\n> > > > As you've already noted, this removes much of the niceness of using\n> > > > std::chrono\n> > > > types, and impacts code readability.\n> > > >\n> > > > I wonder if it would be possible to overload \"operator /\" for the\n> > > utils::Duration type\n> > > > to work-around this bug instead? That way majority of the code need\n> not\n> > > change\n> > > > and the fix only lives in one place in the codebase making it easier\n> to\n> > > revert when\n> > > > the time comes.\n> > >\n> > > Or, if that can't be done for the Duration type only, somehow override\n> > > the std::chrono::duration::operator/() globally, with a version that\n> > > fixes the bug. I think this change is fairly intrusive, I'd like a more\n> > > centralized solution that will not require patching every division.\n> > >\n> > > > On Mon, 24 Oct 2022 at 06:55, Nicholas Roth via libcamera-devel\n> wrote:\n> > > >\n> > > > > From: Nicholas Roth <nicholas@rothemail.net>\n> > > > >\n> > > > > ---\n> > > > >  src/ipa/ipu3/algorithms/agc.cpp            | 18 ++++++++++++++----\n> > > > >  src/ipa/raspberrypi/cam_helper.cpp         |  9 ++++++---\n> > > > >  src/ipa/raspberrypi/cam_helper_imx296.cpp  |  5 ++++-\n> > > > >  src/ipa/raspberrypi/controller/rpi/agc.cpp | 18 ++++++++++++++----\n> > > > >  src/ipa/raspberrypi/controller/rpi/lux.cpp |  5 ++++-\n> > > > >  src/ipa/rkisp1/algorithms/agc.cpp          | 22\n> ++++++++++++++++++----\n> > > > >  6 files changed, 60 insertions(+), 17 deletions(-)\n> > > > >\n> > > > > diff --git a/src/ipa/ipu3/algorithms/agc.cpp\n> > > b/src/ipa/ipu3/algorithms/agc.cpp\n> > > > > index a1a3c38f..80c551bb 100644\n> > > > > --- a/src/ipa/ipu3/algorithms/agc.cpp\n> > > > > +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> > > > > @@ -100,7 +100,10 @@ int Agc::configure(IPAContext &context,\n> > > > >\n> > > > >         /* Configure the default exposure and gain. */\n> > > > >         activeState.agc.gain = std::max(minAnalogueGain_,\n> > > kMinAnalogueGain);\n> > > > > -       activeState.agc.exposure = 10ms /\n> > > configuration.sensor.lineDuration;\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       double ten_millis = utils::Duration(10ms).get<std::nano>();\n> > > > > +       activeState.agc.exposure = ten_millis /\n> > > > > +               configuration.sensor.lineDuration.get<std::nano>();\n> > > > >\n> > > > >         frameCount_ = 0;\n> > > > >         return 0;\n> > > > > @@ -238,11 +241,16 @@ void Agc::computeExposure(IPAContext\n> &context,\n> > > IPAFrameContext &frameContext,\n> > > > >          *\n> > > > >          * Push the shutter time up to the maximum first, and only\n> then\n> > > > >          * increase the gain.\n> > > > > +        *\n> > > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > > > >          */\n> > > > > +       double exposureValueDouble =\n> exposureValue.get<std::nano>();\n> > > > > +       utils::Duration shutterTimeRaw(exposureValueDouble /\n> > > minAnalogueGain_);\n> > > > >         utils::Duration shutterTime =\n> > > > > -               std::clamp<utils::Duration>(exposureValue /\n> > > minAnalogueGain_,\n> > > > > +               std::clamp<utils::Duration>(shutterTimeRaw,\n> > > > >                                             minShutterSpeed_,\n> > > maxShutterSpeed_);\n> > > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > > > +       double shutterTimeDouble = shutterTime.get<std::nano>();\n> > > > > +       double stepGain = std::clamp(exposureValueDouble /\n> > > shutterTimeDouble,\n> > > > >                                      minAnalogueGain_,\n> > > maxAnalogueGain_);\n> > > > >         LOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n> > > > >                             << shutterTime << \" and \"\n> > > > > @@ -250,7 +258,9 @@ void Agc::computeExposure(IPAContext &context,\n> > > IPAFrameContext &frameContext,\n> > > > >\n> > > > >         IPAActiveState &activeState = context.activeState;\n> > > > >         /* Update the estimated exposure and gain. */\n> > > > > -       activeState.agc.exposure = shutterTime /\n> > > configuration.sensor.lineDuration;\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       double lineDurationDouble =\n> > > configuration.sensor.lineDuration.get<std::nano>();\n> > > > > +       activeState.agc.exposure = shutterTimeDouble /\n> > > lineDurationDouble;\n> > > > >         activeState.agc.gain = stepGain;\n> > > > >  }\n> > > > >\n> > > > > diff --git a/src/ipa/raspberrypi/cam_helper.cpp\n> > > b/src/ipa/raspberrypi/cam_helper.cpp\n> > > > > index d90ac1de..31a9a1ef 100644\n> > > > > --- a/src/ipa/raspberrypi/cam_helper.cpp\n> > > > > +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> > > > > @@ -63,7 +63,8 @@ void CamHelper::process([[maybe_unused]]\n> > > StatisticsPtr\n> > > > > &stats,\n> > > > >\n> > > > >  uint32_t CamHelper::exposureLines(const Duration exposure, const\n> > > Duration\n> > > > > lineLength) const\n> > > > >  {\n> > > > > -       return exposure / lineLength;\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       return exposure.get<std::nano>() /\n> lineLength.get<std::nano>();\n> > > > >  }\n> > > > >\n> > > > >  Duration CamHelper::exposure(uint32_t exposureLines, const\n> Duration\n> > > lineLength) const\n> > > > > @@ -84,9 +85,11 @@ std::pair<uint32_t, uint32_t>\n> > > CamHelper::getBlanking(Duration &exposure,\n> > > > >          *\n> > > > >          * frameLengthMax gets calculated on the smallest line\n> length\n> > > as we do\n> > > > >          * not want to extend that unless absolutely necessary.\n> > > > > +        *\n> > > > > +        * TODO(Bug 156): Workaround for LLVM bug.\n> > > > >          */\n> > > > > -       frameLengthMin = minFrameDuration / mode_.minLineLength;\n> > > > > -       frameLengthMax = maxFrameDuration / mode_.minLineLength;\n> > > > > +       frameLengthMin = minFrameDuration.get<std::nano>() /\n> > > mode_.minLineLength.get<std::nano>();\n> > > > > +       frameLengthMax = maxFrameDuration.get<std::nano>() /\n> > > mode_.minLineLength.get<std::nano>();\n> > > > >\n> > > > >         /*\n> > > > >          * Watch out for (exposureLines + frameIntegrationDiff_)\n> > > overflowing a\n> > > > > diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > > index ecb845e7..e48f5cf2 100644\n> > > > > --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > > +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> > > > > @@ -57,7 +57,10 @@ double CamHelperImx296::gain(uint32_t gainCode)\n> > > const\n> > > > >  uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n> > > > >                                         [[maybe_unused]] const\n> > > Duration lineLength) const\n> > > > >  {\n> > > > > -       return std::max<uint32_t>(minExposureLines, (exposure -\n> > > 14.26us) / timePerLine);\n> > > > > +       /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +       double exposureTime = Duration(exposure -\n> > > 14.26us).get<std::nano>();\n> > > > > +       double timePerLineNano = timePerLine.get<std::nano>();\n> > > > > +       return std::max<uint32_t>(minExposureLines, exposureTime /\n> > > timePerLineNano);\n> > > > >  }\n> > > > >\n> > > > >  Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> > > > > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > > index bd54a639..720ba788 100644\n> > > > > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n> > > > > @@ -418,7 +418,10 @@ void Agc::prepare(Metadata *imageMetadata)\n> > > > >                         Duration actualExposure =\n> > > deviceStatus.shutterSpeed *\n> > > > >\n> > >  deviceStatus.analogueGain;\n> > > > >                         if (actualExposure) {\n> > > > > -                               status_.digitalGain =\n> > > status_.totalExposureValue / actualExposure;\n> > > > > +                               /* TODO(Bug 156): Workaround for\n> LLVM\n> > > bug.\n> > > > > */\n> > > > > +                               double totalExposureDouble =\n> > > status_.totalExposureValue.get<std::nano>();\n> > > > > +                               double actualExposureDouble =\n> > > actualExposure.get<std::nano>();\n> > > > > +                               status_.digitalGain =\n> > > totalExposureDouble / actualExposureDouble;\n> > > > >                                 LOG(RPiAgc, Debug) << \"Want total\n> > > exposure \" << status_.totalExposureValue;\n> > > > >                                 /*\n> > > > >                                  * Never ask for a gain < 1.0, and\n> > > also impose\n> > > > > @@ -823,7 +826,10 @@ void Agc::divideUpExposure()\n> > > > >                         }\n> > > > >                         if (status_.fixedAnalogueGain == 0.0) {\n> > > > >                                 if (exposureMode_->gain[stage] *\n> > > shutterTime >= exposureValue) {\n> > > > > -                                       analogueGain =\n> exposureValue /\n> > > shutterTime;\n> > > > > +                                       /* TODO(Bug 156):\n> Workaround\n> > > for LLVM bug. */\n> > > > > +                                       double exposureDouble =\n> > > exposureValue.get<std::nano>();\n> > > > > +                                       double shutterTimeDouble =\n> > > shutterTime.get<std::nano>();\n> > > > > +                                       analogueGain =\n> exposureDouble\n> > > / shutterTimeDouble;\n> > > > >                                         break;\n> > > > >                                 }\n> > > > >                                 analogueGain =\n> > > exposureMode_->gain[stage];\n> > > > > @@ -838,10 +844,14 @@ void Agc::divideUpExposure()\n> > > > >          */\n> > > > >         if (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n> > > > >             status_.flickerPeriod) {\n> > > > > -               int flickerPeriods = shutterTime /\n> > > status_.flickerPeriod;\n> > > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +               double shutterTimeDouble =\n> > > shutterTime.get<std::nano>();\n> > > > > +               double flickerPeriod =\n> > > status_.flickerPeriod.get<std::nano>();\n> > > > > +               int flickerPeriods = shutterTimeDouble /\n> flickerPeriod;\n> > > > >                 if (flickerPeriods) {\n> > > > >                         Duration newShutterTime = flickerPeriods *\n> > > status_.flickerPeriod;\n> > > > > -                       analogueGain *= shutterTime /\n> newShutterTime;\n> > > > > +                       double newShutterTimeDouble =\n> > > newShutterTime.get<std::nano>();\n> > > > > +                       analogueGain *= shutterTimeDouble /\n> > > newShutterTimeDouble;\n> > > > >                         /*\n> > > > >                          * We should still not allow the ag to go\n> over\n> > > the\n> > > > >                          * largest value in the exposure mode. Note\n> > > that this\n> > > > > diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > > index 9759186a..49303409 100644\n> > > > > --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > > +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n> > > > > @@ -93,8 +93,11 @@ void Lux::process(StatisticsPtr &stats, Metadata\n> > > *imageMetadata)\n> > > > >                 /* add .5 to reflect the mid-points of bins */\n> > > > >                 double currentY = sum / (double)num + .5;\n> > > > >                 double gainRatio = referenceGain_ / currentGain;\n> > > > > +               /* TODO(Bug 156): Workaround for LLVM bug. */\n> > > > > +               double referenceShutterSpeedDouble =\n> > > referenceShutterSpeed_.get<std::nano>();\n> > > > > +               double deviceShutterSpeed =\n> > > deviceStatus.shutterSpeed.get<std::nano>();\n> > > > >                 double shutterSpeedRatio =\n> > > > > -                       referenceShutterSpeed_ /\n> > > deviceStatus.shutterSpeed;\n> > > > > +                       referenceShutterSpeedDouble /\n> > > deviceShutterSpeed;\n> > > > >                 double apertureRatio = referenceAperture_ /\n> > > currentAperture;\n> > > > >                 double yRatio = currentY * (65536 / numBins) /\n> > > referenceY_;\n> > > > >                 double estimatedLux = shutterSpeedRatio *\n> gainRatio *\n> > > > > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp\n> > > b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > > index 04062a36..3ea0b732 100644\n> > > > > --- a/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > > +++ b/src/ipa/rkisp1/algorithms/agc.cpp\n> > > > > @@ -74,7 +74,13 @@ int Agc::configure(IPAContext &context, const\n> > > IPACameraSensorInfo &configInfo)\n> > > > >  {\n> > > > >         /* Configure the default exposure and gain. */\n> > > > >         context.activeState.agc.gain =\n> > > std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n> > > > > -       context.activeState.agc.exposure = 10ms /\n> > > context.configuration.sensor.lineDuration;\n> > > > > +       /* TODO(Bug 156): Explicit division of ticks (e.g.,\n> > > `x.get<std::nano>() /\n> > > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a\n> workaround\n> > > for\n> > > > > +        * LLVM bug 41130 and should be reverted once we no longer\n> > > target\n> > > > > +        * Android 11 / sdk30 since it compromises unit safety and\n> > > readability. */\n> > > > > +       constexpr libcamera::utils::Duration ten_millis(10ms);\n> > > > > +       long double exposure = ten_millis.get<std::nano>() /\n> > > context.configuration.sensor.lineDuration.get<std::nano>();\n> > > > > +       context.activeState.agc.exposure = uint32_t(exposure);\n> > > > >\n> > > > >         /*\n> > > > >          * According to the RkISP1 documentation:\n> > > > > @@ -211,17 +217,25 @@ void Agc::computeExposure(IPAContext\n> &context,\n> > > IPAFrameContext &frameContext,\n> > > > >         /*\n> > > > >          * Push the shutter time up to the maximum first, and only\n> then\n> > > > >          * increase the gain.\n> > > > > +        *\n> > > > > +        * TODO(Bug 156): Explicit division of ticks (e.g.,\n> > > `x.get<std::nano>() /\n> > > > > +        * y.get<std::nano>()` as opposed to `x / y`) is a\n> workaround\n> > > for\n> > > > > +        * LLVM bug 41130 and should be reverted once we no longer\n> > > target\n> > > > > +        * Android 11 / sdk30 since it compromises unit safety and\n> > > readability.\n> > > > >          */\n> > > > > -       utils::Duration shutterTime =\n> > > std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n> > > > > +       utils::Duration\n> > > shutterTimeUnclamped(exposureValue.get<std::nano>() / minAnalogueGain);\n> > > > > +       utils::Duration shutterTime =\n> > > std::clamp<utils::Duration>(shutterTimeUnclamped,\n> > > > >\n> > >  minShutterSpeed, maxShutterSpeed);\n> > > > > -       double stepGain = std::clamp(exposureValue / shutterTime,\n> > > > > +       double stepGainUnclamped = exposureValue.get<std::nano>() /\n> > > shutterTime.get<std::nano>();\n> > > > > +       double stepGain = std::clamp(stepGainUnclamped,\n> > > > >                                      minAnalogueGain,\n> maxAnalogueGain);\n> > > > >         LOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n> > > > >                               << shutterTime << \" and \"\n> > > > >                               << stepGain;\n> > > > >\n> > > > >         /* Update the estimated exposure and gain. */\n> > > > > -       activeState.agc.exposure = shutterTime /\n> > > configuration.sensor.lineDuration;\n> > > > > +       activeState.agc.exposure =\n> > > uint32_t(shutterTime.get<std::nano>() /\n> > > > > +\n>  configuration.sensor.lineDuration.get<std::nano>());\n> > > > >         activeState.agc.gain = stepGain;\n> > > > >  }\n> > > > >\n> > >\n> > > --\n> > > Regards,\n> > >\n> > > Laurent Pinchart\n> > >\n> > --\n> > *Nicholas Roth*\n> > *Software Engineer, Machine Learning*\n> > *Google <https://www.google.com/> *\n> > C: (512) 944-0747\n> >\n> > *This footer provides context about my professional background. I am not\n> > acting on behalf of Google. My words and opinions are my own, and not\n> those\n> > of Google.*\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 AA1F5BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Oct 2022 04:24:43 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9F28862F69;\n\tThu, 27 Oct 2022 06:24:42 +0200 (CEST)","from mail-io1-xd35.google.com (mail-io1-xd35.google.com\n\t[IPv6:2607:f8b0:4864:20::d35])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 643EE61F4A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Oct 2022 06:24:40 +0200 (CEST)","by mail-io1-xd35.google.com with SMTP id p141so449985iod.6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Oct 2022 21:24:40 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666844682;\n\tbh=6GXLaoG3zQf10+v6t9C/5mlhSP+Bca+k1XJo3BSNqlM=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=aXKpnIVdo1msvA1iWH740fkChrk+q97e0atzPIO9pP76P3WoQamJud0uNVLfpoPtW\n\ttud16S0WxwTokzquKG2QMsBxIlZ+1AhoE8WL7LzNr6iemQIfkDvhwq251lAFB4TNLP\n\tkoKLkVLQC3V4dYtshQI7u4W/+dhROD9/lJZxQvWKb/GYEvg3ftjadSCw6+WvG04Fgx\n\tTutXTUDqLRTQEq9w4SjHfai6EJ5xXi2BNrbw3XiqH+TU56Cdwv/B3JUN1bjMhhPAnY\n\t9DQQwlH3hOhQi7qIAEm9lyFr6gRER2QI+4PsH0kIM5AltiNrEWaRTsHT1MUa3ETXsC\n\tBbqAXXzOaCo2A==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=rothemail-net.20210112.gappssmtp.com; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=5dyADnQ8VNziLZ2mQpqiBlxLTMTub8M5Lho/G38KfJo=;\n\tb=kSSOHinB2H2aNr1sJsRfcyy2y9qvEy2G2ASDh0hPdWPFM7soSOpIZ/dc4Iti5S5ivO\n\tf92S/GSNP58SISPK4bFaXNsUDCs3I6w3beZuj7+pkvXJa7H3jWdm6m7iG51eV73OkdZG\n\tTAo440Su/wFRIJ020U22rLVyGNJpT3mwUpdmOC5dK0Hq/Qh/YzYoIaYaDrbTc8+lGjsd\n\t4Zi/zK1EeW885sRF8twsxXfj4RBSDgxyRzJs30Pxg9orf5wDzQNucyvB2ZQIdJ/g+CQp\n\tObYmyF56UF9w1JSyVp82ibaxdUSoLJzBR1/1e4a5PRsb+fITyDiSnz8DrhXWc1rxQJC8\n\tNNIg=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=rothemail-net.20210112.gappssmtp.com\n\theader.i=@rothemail-net.20210112.gappssmtp.com header.b=\"kSSOHinB\"; \n\tdkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=5dyADnQ8VNziLZ2mQpqiBlxLTMTub8M5Lho/G38KfJo=;\n\tb=L9XoFng1DjDKMYPJvMQGsHydNVPyC1Hzve9Nh9iN2L9RQv/e/fnrlQnzAHOb1NyXzL\n\tjPnq9qIK4Dp/dt1+cYrCYqLQ3DTwNgbLroRT4Are1g2HyHCUuoJx0RMiVZTXt8MhG2Xk\n\tX/228U0CPkRxOtsIdTQgusBn5SHPLhuInti50/MYpOS0YSw5dskEv6HraRWMBto7+K8U\n\tgR5uL5X5GDUzc5wdUUX4ImkNB4C3Rx2nSaDkqVliDEWOIJVjxYEtLGj458G0u9F/J2D9\n\tSPf2YUsDjlkdSMa9GegMjNzDrhwW9rzecU2EuQBAYuCCDCkkTXbgf/2HE2yt9t+/aPZ2\n\tjcig==","X-Gm-Message-State":"ACrzQf0x0RNjbeDgBU5hXjmrajLZBJqUnkPKbRS5GNUm4QdQv4QNRued\n\tLLmpT/4N2igDctU7wo6F9bdlnSfSOopfHgx0et0JAgbX+2NghZS9","X-Google-Smtp-Source":"AMsMyM4Kp9uk8urnu9QOGDgWcgEsPloRZYH+26dnfiFko6ZqrdIV/XajJA1io/boQMt8TiPsELXroPYPae7G0sMaqIA=","X-Received":"by 2002:a02:94ab:0:b0:35a:d1b9:c71c with SMTP id\n\tx40-20020a0294ab000000b0035ad1b9c71cmr29456577jah.310.1666844678714;\n\tWed, 26 Oct 2022 21:24:38 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>","In-Reply-To":"<166669644142.2560709.8792080139352113364@Monstersaurus>","Date":"Wed, 26 Oct 2022 23:24:28 -0500","Message-ID":"<CAD2rFCqEw9NrSOqOJc6+EpDOmh320f0fF4qxtDyxd1hidsHbuA@mail.gmail.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Content-Type":"multipart/alternative; boundary=\"000000000000f898ec05ebfc841d\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Nicholas Roth <nicholas@rothemail.net>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25623,"web_url":"https://patchwork.libcamera.org/comment/25623/","msgid":"<166686952986.3974115.9468622881324570578@Monstersaurus>","date":"2022-10-27T11:18:49","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Nicholas Roth (2022-10-27 05:24:28)\n> >  cp utils/hooks/post-commit .git/hooks/post-commit\n> The post-commits seem to want me to replace my tabs with spaces. I use tabs\n> to be consistent with the surrounding codebase. Is it OK to ignore these\n> errors, or should I do something else?\n\nThat's odd - it shouldn't be changing tabs for spaces?\n\nWhat's your tabsize set to ? We use 8-character tabs.\n\n \n> Example:\n> --- src/android/camera_hal_config.cpp\n> +++ src/android/camera_hal_config.cpp\n> @@ -164,7 +164,7 @@\n>         File file(filePath);\n>         if (!file.exist()) {\n>                 LOG(HALConfig, Debug)\n> -                                       << \"Configuration file: \\\"\" <<\n> filePath << \"\\\" not found\";\n> +                       << \"Configuration file: \\\"\" << filePath << \"\\\" not\n> found\";\n>                 return -ENOENT;\n\nIn my terminal, this change looks correct:\n\n\t\tLOG(HALConfig, Debug)\n\t\t\t<< \"Configuration file: \\\"\" << filePath << \"\\\" not found\";\n\nWe often take the debug print lines to the following line to allow a\nlonger length without breaking the text, or hitting our line length\nlimit. We only use a single indentation from the start of the previous\nline\n\n--\nKieran\n\n\n>         }\n> \n> ---\n> 1 potential issue detected, please review","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 16C90BDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Oct 2022 11:18:56 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3354762F84;\n\tThu, 27 Oct 2022 13:18:55 +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 BE5C262F0C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Oct 2022 13:18:52 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 305004F8;\n\tThu, 27 Oct 2022 13:18:52 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666869535;\n\tbh=gjI2eEG6TI8h88IEVAFu8TJVkTeXgIf8UNlHes5mHNo=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=Ez2+DHrRFhVJV7B3UEBRkvzt2sL4Jbf9wzjLogYs8MefS783jotYXLJjaM2nmLM4f\n\tecGmcwJAhbAoy46/OAaohCgPRfSNJjwI9NT+0Zjb6RggqrGjQt7s0k0CMvGwcMxCjB\n\t97C8SggOwp8YXXC+0Tk47QZKxtMi9GQs9ppBo8l3PzaQPl5WPkh7xnlsyYIV/HcYci\n\ti5iFYBh77zBWczEaFFRKN1Nxp7PMcgTdN1f9cwURwM648uqd5KGzT7z9K9cyI/aV7K\n\tjhJChwakJnFDFYRblCnkmJkD5YPYOSAWktWs+GI16150b7R+zp4+BmARQO8JJ0p6O6\n\tNQYRSeHVIH+Iw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666869532;\n\tbh=gjI2eEG6TI8h88IEVAFu8TJVkTeXgIf8UNlHes5mHNo=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=dhl3MLdW/Ds2/3mjwoBunJnaY6oNHCB7oEhchgVJCzqD243ehelTV4Phu9d+laNWV\n\tfzbqet+l+fxM+qpJf8IkCUAETyBkXLVxhU48E9iSXInseHDkyyMS8hdgZFnxtndI1D\n\t4habjGaQXKxumqv933a8xWtki5W0BNPYye9SBjBA="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"dhl3MLdW\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<CAD2rFCqEw9NrSOqOJc6+EpDOmh320f0fF4qxtDyxd1hidsHbuA@mail.gmail.com>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCqEw9NrSOqOJc6+EpDOmh320f0fF4qxtDyxd1hidsHbuA@mail.gmail.com>","To":"Nicholas Roth <nicholas@rothemail.net>","Date":"Thu, 27 Oct 2022 12:18:49 +0100","Message-ID":"<166686952986.3974115.9468622881324570578@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25632,"web_url":"https://patchwork.libcamera.org/comment/25632/","msgid":"<CAD2rFCrDDCzdmVV+uasBUXnMhDsBaXDkK2B6PdOef2tWaQChsA@mail.gmail.com>","date":"2022-10-27T21:52:46","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":137,"url":"https://patchwork.libcamera.org/api/people/137/","name":"Nicholas Roth","email":"nicholas@rothemail.net"},"content":"Hey, so now I'm *really* confused by the post-commit. It almost seems like\nit wants me to use a mix of spaces and tabs, which I've never seen before.\nLet me know what you make of this:\n\nI start with this suggestion:\n--- src/ipa/ipu3/algorithms/agc.cpp\n+++ src/ipa/ipu3/algorithms/agc.cpp\n@@ -101,7 +101,7 @@\n        /* Configure the default exposure and gain. */\n        activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n        activeState.agc.exposure = 10ms /\n-\nstd::chrono::duration(configuration.sensor.lineDuration);\n+\n std::chrono::duration(configuration.sensor.lineDuration);\n\n        frameCount_ = 0;\n        return 0;\n\nThen when I delete a tab as suggested, I end up with this:\n--- src/ipa/ipu3/algorithms/agc.cpp\n+++ src/ipa/ipu3/algorithms/agc.cpp\n@@ -101,7 +101,7 @@\n        /* Configure the default exposure and gain. */\n        activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n        activeState.agc.exposure = 10ms /\n-\nstd::chrono::duration(configuration.sensor.lineDuration);\n+\n std::chrono::duration(configuration.sensor.lineDuration);\n\n        frameCount_ = 0;\n        return 0;\n\nIf a mix of tabs and spaces is what's standard for us, I'll do it. I just\nthought to ask first since it would be the first time I've seen a project\nwith this convention.\n\nThanks,\n-Nicholas\n\nOn Thu, Oct 27, 2022 at 6:18 AM Kieran Bingham <\nkieran.bingham@ideasonboard.com> wrote:\n\n> Quoting Nicholas Roth (2022-10-27 05:24:28)\n> > >  cp utils/hooks/post-commit .git/hooks/post-commit\n> > The post-commits seem to want me to replace my tabs with spaces. I use\n> tabs\n> > to be consistent with the surrounding codebase. Is it OK to ignore these\n> > errors, or should I do something else?\n>\n> That's odd - it shouldn't be changing tabs for spaces?\n>\n> What's your tabsize set to ? We use 8-character tabs.\n>\n>\n> > Example:\n> > --- src/android/camera_hal_config.cpp\n> > +++ src/android/camera_hal_config.cpp\n> > @@ -164,7 +164,7 @@\n> >         File file(filePath);\n> >         if (!file.exist()) {\n> >                 LOG(HALConfig, Debug)\n> > -                                       << \"Configuration file: \\\"\" <<\n> > filePath << \"\\\" not found\";\n> > +                       << \"Configuration file: \\\"\" << filePath << \"\\\"\n> not\n> > found\";\n> >                 return -ENOENT;\n>\n> In my terminal, this change looks correct:\n>\n>                 LOG(HALConfig, Debug)\n>                         << \"Configuration file: \\\"\" << filePath << \"\\\" not\n> found\";\n>\n> We often take the debug print lines to the following line to allow a\n> longer length without breaking the text, or hitting our line length\n> limit. We only use a single indentation from the start of the previous\n> line\n>\n> --\n> Kieran\n>\n>\n> >         }\n> >\n> > ---\n> > 1 potential issue detected, please review\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 A317DBDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Oct 2022 21:53:01 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D9AAF62FA0;\n\tThu, 27 Oct 2022 23:53:00 +0200 (CEST)","from mail-il1-x12d.google.com (mail-il1-x12d.google.com\n\t[IPv6:2607:f8b0:4864:20::12d])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id F261462F89\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Oct 2022 23:52:58 +0200 (CEST)","by mail-il1-x12d.google.com with SMTP id h18so1948182ilq.9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Oct 2022 14:52:58 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666907580;\n\tbh=s+9aeua+QR/iQvKra54MBkIg3Z0NTGrHGOFWejMmRpg=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=ispNw3bMj42NzQ7bHd6ezKOJ2dbOfFFGQqw8eJBEJLwHLEc2fr6SJom6hz7zbmnN3\n\t6Lzza8MbzRIV69SOYFyz6a0NK+gvkVIqF80LOq9EEMRJpPXQfCWnmXreebAzAuoHgs\n\t3E6n3pYTUOvAkVmqJoJTKUURdeSxmTNWzPAUZp8q+xfWWB4BaTzBE7MU4/0/V72vBj\n\tXoAUGgmsGiS0rNkKcTWwObP9eQmWjz6ZEZ8WJJ5qPJ6xjy2IEg1L1M36GqWLUFfkzH\n\trCIkFBUicKwui/m1aDjoFnxVM7RX2SrBjftBzleObS0+vgSCMyQo2Km8CXPaZQncz2\n\tgJAnHSYszNebA==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=rothemail-net.20210112.gappssmtp.com; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=42uZgCQK7F57/61F6kza44oWaiWzhNlU2H+EUB+XF18=;\n\tb=gtkNo6jBY86KvXnBxe1wT0Xds8SV6VSrnqXc2WpclHocRXHLVp8vbkkvHHd3umkVys\n\tm7ylSzx2SOYTfGR2j0ivBK9Brc77s3vZgrJ1BeQAQe5MOT18OqFFiAmRg5vOL9MKhlmj\n\t2JOh8iAy4OJ18P/ZMbR39YGYW2Y6r/lL8EIq39yGe7fm7mCTF6Nh79CiZgtuaSBfjgfr\n\t7V9Wgda1Vhk3DyQ5DSEv+zrVbaAsPPLG7dnxT48a0IhqQmuqAzdVIpdZTblFzqK7IT61\n\ttr5xLd8ErSSJWR0PIapFvwsMvQZ338Tq/SBo5J6t40wrnk8y5iGAnAnHKx5zuWXVPG/O\n\tl/KA=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=rothemail-net.20210112.gappssmtp.com\n\theader.i=@rothemail-net.20210112.gappssmtp.com header.b=\"gtkNo6jB\"; \n\tdkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=42uZgCQK7F57/61F6kza44oWaiWzhNlU2H+EUB+XF18=;\n\tb=GKBZbBOF4CLKskh0Kx547Th6HAi1jOk7mvlorECzYh+zd7my2iTwjBX15aOE6/W18E\n\t7wKLV/CuZgZzOZdZF34eoX8s0I2VV2hoWXVEdCQblGdVT0/2GX/XLOcTtAyjpLNbUxlw\n\txLEUQ+zW/KmPww3znJKcFYLGTWKNOxcRHmc6VllMHWWUz0AptlT0nKWyDbIqNYWUhl+d\n\tr/10rJw4HJWOtn9ZL8gSNVKO0E+1cIaqsJumkPZwY7icnGhn7RSXy0/dh4ClJyK+6EZA\n\t7rpMXJm5u0kvPnE3aJ8vO01pZY9afGvdYvQo/JV7mli1g5JJEP14+Oh6aOxdRRTVUuPN\n\tBMPQ==","X-Gm-Message-State":"ACrzQf07JJi2+aPnsgbIJ3aRCGactYDuBBs/Kf7U8AYNGCKMHtHXEp+Z\n\t6speJ1lv3d4RiWWoLYtrloMlBrfOWuaqACH71HzegA==","X-Google-Smtp-Source":"AMsMyM5YVRx5kAqPVRakY5ncyMBX0VjKrIthV1EE3VBA6C8LKNbOFXWheim39DrhmDSRd83ebV7YLzQdFu62WHjvF84=","X-Received":"by 2002:a05:6e02:1bab:b0:2fa:2cfb:80e3 with SMTP id\n\tn11-20020a056e021bab00b002fa2cfb80e3mr30046454ili.24.1666907577216;\n\tThu, 27 Oct 2022 14:52:57 -0700 (PDT)","MIME-Version":"1.0","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCqEw9NrSOqOJc6+EpDOmh320f0fF4qxtDyxd1hidsHbuA@mail.gmail.com>\n\t<166686952986.3974115.9468622881324570578@Monstersaurus>","In-Reply-To":"<166686952986.3974115.9468622881324570578@Monstersaurus>","Date":"Thu, 27 Oct 2022 16:52:46 -0500","Message-ID":"<CAD2rFCrDDCzdmVV+uasBUXnMhDsBaXDkK2B6PdOef2tWaQChsA@mail.gmail.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Content-Type":"multipart/alternative; boundary=\"00000000000003896f05ec0b2afe\"","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Nicholas Roth <nicholas@rothemail.net>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25642,"web_url":"https://patchwork.libcamera.org/comment/25642/","msgid":"<166694800841.2560709.17446588748125093315@Monstersaurus>","date":"2022-10-28T09:06:48","subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Nicholas Roth (2022-10-27 22:52:46)\n> Hey, so now I'm *really* confused by the post-commit. It almost seems like\n> it wants me to use a mix of spaces and tabs, which I've never seen before.\n> Let me know what you make of this:\n> \n> I start with this suggestion:\n> --- src/ipa/ipu3/algorithms/agc.cpp\n> +++ src/ipa/ipu3/algorithms/agc.cpp\n> @@ -101,7 +101,7 @@\n>         /* Configure the default exposure and gain. */\n>         activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n>         activeState.agc.exposure = 10ms /\n> -\n> std::chrono::duration(configuration.sensor.lineDuration);\n> +\n>  std::chrono::duration(configuration.sensor.lineDuration);\n> \n>         frameCount_ = 0;\n>         return 0;\n> \n> Then when I delete a tab as suggested, I end up with this:\n> --- src/ipa/ipu3/algorithms/agc.cpp\n> +++ src/ipa/ipu3/algorithms/agc.cpp\n> @@ -101,7 +101,7 @@\n>         /* Configure the default exposure and gain. */\n>         activeState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n>         activeState.agc.exposure = 10ms /\n> -\n> std::chrono::duration(configuration.sensor.lineDuration);\n> +\n>  std::chrono::duration(configuration.sensor.lineDuration);\n> \n>         frameCount_ = 0;\n>         return 0;\n> \n> If a mix of tabs and spaces is what's standard for us, I'll do it. I just\n> thought to ask first since it would be the first time I've seen a project\n> with this convention.\n\nThere 'are' a mix of spaces and tabs - but it's about alignment.\n\nIt's really hard to determine from your mail above which is\nspace/tabs/indent due to the mail wraps. but hopefully this can lay it\nout. clang-format gets it right most of the time (which is what the post\ncommit hook is using) but it always needs a quick review because\nsometimes clang-format does things that are just plain stupid or less\nreadable. So it's there for guidance rather than specification.\n\n\n~######~ == Tab (8 per tab)\n.....    == Spaces ( 1 per space )\n\n\nSo these single indents for example are all tabs:\n\n~######~if (cfg.size != size) {\n~######~~######~LOG(UVC, Debug)\n~######~~######~~######~<< \"Adjusting size from \" << size << \" to \" << cfg.size;\n~######~~######~status = Adjusted;\n~######~}\n\nBut if there was something which needs to be directly aligned below a\ncharacter on the previous line, then it's tabs to fill the gap, with\nspaces for the alignment:\n\nFor example on this function prototype, the paramaters are aligned:\n\n~######~int exportFrameBuffers(Camera *camera, Stream *stream,\n~######~~######~~######~.......std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n\nAs I understand it, that's pretty close to the style in the kernel:\n\n  https://www.kernel.org/doc/html/v4.10/process/coding-style.html\n\n\nAnd this is the extract from our https://libcamera.org/coding-style.html#coding-style-guidelines\n\n  Coding Style\n\nEven if the programming language in use is different, the project\nembraces the Linux Kernel Coding Style with a few exception and some C++\nspecificities.\n\nIn particular, from the kernel style document, the following section are\nadopted:\n\n    1 “Indentation”\n    2 “Breaking Long Lines” striving to fit code within 80 columns and accepting up to 120 columns when necessary\n    3 “Placing Braces and Spaces”\n    3.1 “Spaces”\n    8 “Commenting” with the exception that in-function comments are not always un-welcome.\n\n\n> \n> Thanks,\n> -Nicholas\n> \n> On Thu, Oct 27, 2022 at 6:18 AM Kieran Bingham <\n> kieran.bingham@ideasonboard.com> wrote:\n> \n> > Quoting Nicholas Roth (2022-10-27 05:24:28)\n> > > >  cp utils/hooks/post-commit .git/hooks/post-commit\n> > > The post-commits seem to want me to replace my tabs with spaces. I use\n> > tabs\n> > > to be consistent with the surrounding codebase. Is it OK to ignore these\n> > > errors, or should I do something else?\n> >\n> > That's odd - it shouldn't be changing tabs for spaces?\n> >\n> > What's your tabsize set to ? We use 8-character tabs.\n> >\n> >\n> > > Example:\n> > > --- src/android/camera_hal_config.cpp\n> > > +++ src/android/camera_hal_config.cpp\n> > > @@ -164,7 +164,7 @@\n> > >         File file(filePath);\n> > >         if (!file.exist()) {\n> > >                 LOG(HALConfig, Debug)\n> > > -                                       << \"Configuration file: \\\"\" <<\n> > > filePath << \"\\\" not found\";\n> > > +                       << \"Configuration file: \\\"\" << filePath << \"\\\"\n> > not\n> > > found\";\n> > >                 return -ENOENT;\n> >\n> > In my terminal, this change looks correct:\n> >\n> >                 LOG(HALConfig, Debug)\n> >                         << \"Configuration file: \\\"\" << filePath << \"\\\" not\n> > found\";\n> >\n> > We often take the debug print lines to the following line to allow a\n> > longer length without breaking the text, or hitting our line length\n> > limit. We only use a single indentation from the start of the previous\n> > line\n> >\n> > --\n> > Kieran\n> >\n> >\n> > >         }\n> > >\n> > > ---\n> > > 1 potential issue detected, please review\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 C5DEFBDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 28 Oct 2022 09:06:53 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 397D062FBB;\n\tFri, 28 Oct 2022 11:06:53 +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 E061462F41\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 28 Oct 2022 11:06:51 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 702FE6BE;\n\tFri, 28 Oct 2022 11:06:51 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666948013;\n\tbh=Nasiu9WOHzb2S1izFWqPmxT2gqyj+OR1zU0qeUYvIPY=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=h9BGFwuoImxNNOj8LdDSmjaEPoTI3WcM/Hh56TyV0E+LYh31ULkrIQ1vmpgmeWZlM\n\tJxnKXHI1hWBrCCivWQF7o/f7avxcnrA9EsKe0CzT7gqeqnnQfY6udzXGT2OaCIYAnc\n\t2XR62AxCs2KICCD0NECQtZC6bnGr5hQRryd1prr43bkage0pwxXQep2tgkIAk9fbMA\n\t3lWSKLbJd9FZozvpscEQRcxGkrEtjuEapc2w553hFDwrqdpQhp5q/agAUuxs83x3Wa\n\tMwwoiktOxhHDsDV+5/CJtHqxFkE0LGAGr6/q+NWDyc0Zh+uHMLT0PdwGMcmOe2yYLp\n\t9kRWLEb9tM6zg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666948011;\n\tbh=Nasiu9WOHzb2S1izFWqPmxT2gqyj+OR1zU0qeUYvIPY=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=aqHzeazGMtwqLV7Owq6j9PsR/7nN9VvYqw6oifGgek7J7BpvvJqooXIEIDmPQBZUn\n\topAihmDqDym1BKkNkRXTPnPYE7JShtWtwBOpZ9IeCCPwZDl0r45sENEypuAQtjW4HC\n\tr4q1CpCUo6ecL4XgAHoJGfeeDVe7XnBVLjNu30ps="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"aqHzeazG\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<CAD2rFCrDDCzdmVV+uasBUXnMhDsBaXDkK2B6PdOef2tWaQChsA@mail.gmail.com>","References":"<20221024055543.116040-1-nicholas@rothemail.net>\n\t<20221024055543.116040-2-nicholas@rothemail.net>\n\t<CAEmqJPr9H_Vt4k2uCMGfZW=sgn7SBLQ9N_gxZOeeSUHmN4Mrcg@mail.gmail.com>\n\t<Y1aTYd74lNsKp0fx@pendragon.ideasonboard.com>\n\t<CAD2rFCoOva3GZa0Xyg61fDxque-AWschCx3bjs=t0edy0QPFVQ@mail.gmail.com>\n\t<166669644142.2560709.8792080139352113364@Monstersaurus>\n\t<CAD2rFCqEw9NrSOqOJc6+EpDOmh320f0fF4qxtDyxd1hidsHbuA@mail.gmail.com>\n\t<166686952986.3974115.9468622881324570578@Monstersaurus>\n\t<CAD2rFCrDDCzdmVV+uasBUXnMhDsBaXDkK2B6PdOef2tWaQChsA@mail.gmail.com>","To":"Nicholas Roth <nicholas@rothemail.net>","Date":"Fri, 28 Oct 2022 10:06:48 +0100","Message-ID":"<166694800841.2560709.17446588748125093315@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 01/11] Fixes Bug 156,\n\twhich breaks libcamera on Android < 12.","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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Nicholas Roth via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]