[{"id":25352,"web_url":"https://patchwork.libcamera.org/comment/25352/","msgid":"<Y0CpGUS6W3y11XdB@pendragon.ideasonboard.com>","date":"2022-10-07T22:32:57","subject":"Re: [libcamera-devel] [PATCH v2 03/10] ipa: raspberrypi: Pass\n\tlineLength into the CamHelper API","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Naush,\n\nThank you for the patch.\n\nOn Thu, Oct 06, 2022 at 02:17:37PM +0100, Naushir Patuck via libcamera-devel wrote:\n> Update CamHelper::exposureLines() and CamHelper::exposure() to take a\n> line length duration parameter for use in the exposure calculations.\n> \n> For now, only use the minimum line length for all the calculations to match\n> the existing IPA behavior.\n> \n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> Tested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  src/ipa/raspberrypi/cam_helper.cpp        | 12 ++++++------\n>  src/ipa/raspberrypi/cam_helper.h          |  6 ++++--\n>  src/ipa/raspberrypi/cam_helper_imx219.cpp |  3 ++-\n>  src/ipa/raspberrypi/cam_helper_imx296.cpp | 10 ++++++----\n>  src/ipa/raspberrypi/cam_helper_imx477.cpp |  7 ++++---\n>  src/ipa/raspberrypi/cam_helper_imx519.cpp |  7 ++++---\n>  src/ipa/raspberrypi/raspberrypi.cpp       |  8 ++++----\n>  7 files changed, 30 insertions(+), 23 deletions(-)\n> \n> diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp\n> index 42251ba29682..fd3527b94501 100644\n> --- a/src/ipa/raspberrypi/cam_helper.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> @@ -61,16 +61,16 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr &stats,\n>  {\n>  }\n>  \n> -uint32_t CamHelper::exposureLines(const Duration exposure) const\n> +uint32_t CamHelper::exposureLines(const Duration exposure, const Duration lineLength) const\n>  {\n>  \tassert(initialized_);\n> -\treturn exposure / mode_.minLineLength;\n> +\treturn exposure / lineLength;\n>  }\n>  \n> -Duration CamHelper::exposure(uint32_t exposureLines) const\n> +Duration CamHelper::exposure(uint32_t exposureLines, const Duration lineLength) const\n>  {\n>  \tassert(initialized_);\n> -\treturn exposureLines * mode_.minLineLength;\n> +\treturn exposureLines * lineLength;\n>  }\n>  \n>  uint32_t CamHelper::getVBlanking(Duration &exposure,\n> @@ -78,7 +78,7 @@ uint32_t CamHelper::getVBlanking(Duration &exposure,\n>  \t\t\t\t Duration maxFrameDuration) const\n>  {\n>  \tuint32_t frameLengthMin, frameLengthMax, vblank;\n> -\tuint32_t exposureLines = CamHelper::exposureLines(exposure);\n> +\tuint32_t exposureLines = CamHelper::exposureLines(exposure, mode_.minLineLength);\n>  \n>  \tassert(initialized_);\n>  \n> @@ -94,7 +94,7 @@ uint32_t CamHelper::getVBlanking(Duration &exposure,\n>  \t * re-calculate if it has been clipped.\n>  \t */\n>  \texposureLines = std::min(frameLengthMax - frameIntegrationDiff_, exposureLines);\n> -\texposure = CamHelper::exposure(exposureLines);\n> +\texposure = CamHelper::exposure(exposureLines, mode_.minLineLength);\n>  \n>  \t/* Limit the vblank to the range allowed by the frame length limits. */\n>  \tvblank = std::clamp(exposureLines + frameIntegrationDiff_,\n> diff --git a/src/ipa/raspberrypi/cam_helper.h b/src/ipa/raspberrypi/cam_helper.h\n> index 70d62719da86..9b5e602689f3 100644\n> --- a/src/ipa/raspberrypi/cam_helper.h\n> +++ b/src/ipa/raspberrypi/cam_helper.h\n> @@ -78,8 +78,10 @@ public:\n>  \tvirtual void prepare(libcamera::Span<const uint8_t> buffer,\n>  \t\t\t     Metadata &metadata);\n>  \tvirtual void process(StatisticsPtr &stats, Metadata &metadata);\n> -\tvirtual uint32_t exposureLines(libcamera::utils::Duration exposure) const;\n> -\tvirtual libcamera::utils::Duration exposure(uint32_t exposureLines) const;\n> +\tvirtual uint32_t exposureLines(const libcamera::utils::Duration exposure,\n> +\t\t\t\t       const libcamera::utils::Duration lineLength) const;\n> +\tvirtual libcamera::utils::Duration exposure(uint32_t exposureLines,\n> +\t\t\t\t\t\t    const libcamera::utils::Duration lineLength) const;\n>  \tvirtual uint32_t getVBlanking(libcamera::utils::Duration &exposure,\n>  \t\t\t\t      libcamera::utils::Duration minFrameDuration,\n>  \t\t\t\t      libcamera::utils::Duration maxFrameDuration) const;\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp\n> index 7ded07a213cd..98a3b31956ec 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx219.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp\n> @@ -94,7 +94,8 @@ void CamHelperImx219::populateMetadata(const MdParser::RegisterMap &registers,\n>  {\n>  \tDeviceStatus deviceStatus;\n>  \n> -\tdeviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg));\n> +\tdeviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg),\n> +\t\t\t\t\t     mode_.minLineLength);\n>  \tdeviceStatus.analogueGain = gain(registers.at(gainReg));\n>  \tdeviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);\n>  \n> diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> index 66d21e36ecd0..d86ff3878983 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp\n> @@ -21,8 +21,8 @@ public:\n>  \tCamHelperImx296();\n>  \tuint32_t gainCode(double gain) const override;\n>  \tdouble gain(uint32_t gainCode) const override;\n> -\tuint32_t exposureLines(Duration exposure) const override;\n> -\tDuration exposure(uint32_t exposureLines) const override;\n> +\tuint32_t exposureLines(const Duration exposure, const Duration lineLength) const override;\n> +\tDuration exposure(uint32_t exposureLines, const Duration lineLength) const override;\n>  \tvoid getDelays(int &exposureDelay, int &gainDelay, int &vblankDelay) const override;\n>  \n>  private:\n> @@ -53,12 +53,14 @@ double CamHelperImx296::gain(uint32_t gainCode) const\n>  \treturn std::pow(10.0, gainCode / 200.0);\n>  }\n>  \n> -uint32_t CamHelperImx296::exposureLines(Duration exposure) const\n> +uint32_t CamHelperImx296::exposureLines(const Duration exposure,\n> +\t\t\t\t\t[[maybe_unused]] const Duration lineLength) const\n>  {\n>  \treturn std::max<uint32_t>(minExposureLines, (exposure - 14.26us) / timePerLine);\n>  }\n>  \n> -Duration CamHelperImx296::exposure(uint32_t exposureLines) const\n> +Duration CamHelperImx296::exposure(uint32_t exposureLines,\n> +\t\t\t\t   [[maybe_unused]] const Duration lineLength) const\n>  {\n>  \treturn std::max<uint32_t>(minExposureLines, exposureLines) * timePerLine + 14.26us;\n>  }\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp\n> index aa306d6661c6..71529bdd3034 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp\n> @@ -144,9 +144,9 @@ uint32_t CamHelperImx477::getVBlanking(Duration &exposure,\n>  \tif (shift) {\n>  \t\t/* Account for any rounding in the scaled frame length value. */\n>  \t\tframeLength <<= shift;\n> -\t\texposureLines = CamHelperImx477::exposureLines(exposure);\n> +\t\texposureLines = CamHelperImx477::exposureLines(exposure, mode_.minLineLength);\n>  \t\texposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);\n> -\t\texposure = CamHelperImx477::exposure(exposureLines);\n> +\t\texposure = CamHelperImx477::exposure(exposureLines, mode_.minLineLength);\n>  \t}\n>  \n>  \treturn frameLength - mode_.height;\n> @@ -170,7 +170,8 @@ void CamHelperImx477::populateMetadata(const MdParser::RegisterMap &registers,\n>  {\n>  \tDeviceStatus deviceStatus;\n>  \n> -\tdeviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg));\n> +\tdeviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg),\n> +\t\t\t\t\t     mode_.minLineLength);\n>  \tdeviceStatus.analogueGain = gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg));\n>  \tdeviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);\n>  \tdeviceStatus.sensorTemperature = std::clamp<int8_t>(registers.at(temperatureReg), -20, 80);\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp b/src/ipa/raspberrypi/cam_helper_imx519.cpp\n> index 54e104e7659a..2c120dad1680 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx519.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx519.cpp\n> @@ -144,9 +144,9 @@ uint32_t CamHelperImx519::getVBlanking(Duration &exposure,\n>  \tif (shift) {\n>  \t\t/* Account for any rounding in the scaled frame length value. */\n>  \t\tframeLength <<= shift;\n> -\t\texposureLines = CamHelperImx519::exposureLines(exposure);\n> +\t\texposureLines = CamHelperImx519::exposureLines(exposure, mode_.minLineLength);\n>  \t\texposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);\n> -\t\texposure = CamHelperImx519::exposure(exposureLines);\n> +\t\texposure = CamHelperImx519::exposure(exposureLines, mode_.minLineLength);\n>  \t}\n>  \n>  \treturn frameLength - mode_.height;\n> @@ -170,7 +170,8 @@ void CamHelperImx519::populateMetadata(const MdParser::RegisterMap &registers,\n>  {\n>  \tDeviceStatus deviceStatus;\n>  \n> -\tdeviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg));\n> +\tdeviceStatus.shutterSpeed = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg),\n> +\t\t\t\t\t     mode_.minLineLength);\n>  \tdeviceStatus.analogueGain = gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg));\n>  \tdeviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);\n>  \n> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> index 67326bcf4a14..13807f4d47f7 100644\n> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> @@ -477,7 +477,7 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo,\n>  \tconst uint32_t exposureMin = sensorCtrls_.at(V4L2_CID_EXPOSURE).min().get<int32_t>();\n>  \n>  \tctrlMap[&controls::ExposureTime] =\n> -\t\tControlInfo(static_cast<int32_t>(helper_->exposure(exposureMin).get<std::micro>()),\n> +\t\tControlInfo(static_cast<int32_t>(helper_->exposure(exposureMin, mode_.minLineLength).get<std::micro>()),\n>  \t\t\t    static_cast<int32_t>(maxShutter.get<std::micro>()));\n>  \n>  \tresult->controlInfo = ControlInfoMap(std::move(ctrlMap), controls::controls);\n> @@ -550,7 +550,7 @@ void IPARPi::reportMetadata()\n>  \t\t\t\t       deviceStatus->shutterSpeed.get<std::micro>());\n>  \t\tlibcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogueGain);\n>  \t\tlibcameraMetadata_.set(controls::FrameDuration,\n> -\t\t\t\t       helper_->exposure(deviceStatus->frameLength).get<std::micro>());\n> +\t\t\t\t       helper_->exposure(deviceStatus->frameLength, mode_.minLineLength).get<std::micro>());\n>  \t\tif (deviceStatus->sensorTemperature)\n>  \t\t\tlibcameraMetadata_.set(controls::SensorTemperature, *deviceStatus->sensorTemperature);\n>  \t}\n> @@ -1106,7 +1106,7 @@ void IPARPi::fillDeviceStatus(const ControlList &sensorControls)\n>  \tint32_t gainCode = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();\n>  \tint32_t vblank = sensorControls.get(V4L2_CID_VBLANK).get<int32_t>();\n>  \n> -\tdeviceStatus.shutterSpeed = helper_->exposure(exposureLines);\n> +\tdeviceStatus.shutterSpeed = helper_->exposure(exposureLines, mode_.minLineLength);\n>  \tdeviceStatus.analogueGain = helper_->gain(gainCode);\n>  \tdeviceStatus.frameLength = mode_.height + vblank;\n>  \n> @@ -1198,7 +1198,7 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n>  \t/* getVBlanking might clip exposure time to the fps limits. */\n>  \tDuration exposure = agcStatus->shutterTime;\n>  \tint32_t vblanking = helper_->getVBlanking(exposure, minFrameDuration_, maxFrameDuration_);\n> -\tint32_t exposureLines = helper_->exposureLines(exposure);\n> +\tint32_t exposureLines = helper_->exposureLines(exposure, mode_.minLineLength);\n>  \n>  \tLOG(IPARPI, Debug) << \"Applying AGC Exposure: \" << exposure\n>  \t\t\t   << \" (Shutter lines: \" << exposureLines << \", AGC requested \"","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 01504BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri,  7 Oct 2022 22:33:03 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4E5F862D2D;\n\tSat,  8 Oct 2022 00:33:03 +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 7064C62CEC\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  8 Oct 2022 00:33:02 +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 CC13A4E6;\n\tSat,  8 Oct 2022 00:33:01 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1665181983;\n\tbh=akYor/zszQeb/xsMYm8Xhl64agDdmnjaoPEMS8xBTOA=;\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=PAbhErLm72lnlstPnhpLx5tEI4t2EVlsGNyn7a5HxZpCNITENpcfvO++H7NcUU6s4\n\th+yMQ5QkRgCe3KxBojoCytjF7VXJEYyyhJi2TmBpa3UQTCWjzPzvc60/E2r2LjF7hr\n\tEgqA1j0u/lGBxWdIPAuPBb+2C27MnmvWnpFUQCRk+4eBKRilti/7Zy+zzcvrzWpgCg\n\t9mmpNuYJq6yShUJk8fAAQmajTjiQ6a7KAoVwAIuZE28gusvn7G52mK2Mbg3UpyKtAd\n\tDPtVuwQHKsGG7kS/VKmCmd3sx4ODLuZLKu/KOs6YYTR9J6oxFizf/8cBC9hPyMBO3K\n\tAENONqv3DZBmg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1665181982;\n\tbh=akYor/zszQeb/xsMYm8Xhl64agDdmnjaoPEMS8xBTOA=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=YN9VeoEIRuScTDLK5AVHhANv/IxHPgzfS6wVVVeJO8KWBxDfHOfRdmiI5AcatQNMl\n\tpbf54fI0F4bO6tCLzVmfQq/P3CzbW3lSrbkHyS2j+m1IK+3iy700plaVN84x+7cNgq\n\t1Df1O9pGU7O0aGQ3qzAH8hla1LVeNNxIW8Lq2QEI="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"YN9VeoEI\"; dkim-atps=neutral","Date":"Sat, 8 Oct 2022 01:32:57 +0300","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<Y0CpGUS6W3y11XdB@pendragon.ideasonboard.com>","References":"<20221006131744.5179-1-naush@raspberrypi.com>\n\t<20221006131744.5179-4-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20221006131744.5179-4-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH v2 03/10] ipa: raspberrypi: Pass\n\tlineLength into the CamHelper API","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]