Patch Detail
Show a patch.
GET /api/1.1/patches/18440/?format=api
{ "id": 18440, "url": "https://patchwork.libcamera.org/api/1.1/patches/18440/?format=api", "web_url": "https://patchwork.libcamera.org/patch/18440/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20230322161317.18055-3-naush@raspberrypi.com>", "date": "2023-03-22T16:13:16", "name": "[libcamera-devel,v1,2/3] ipa: raspberrypi: Populate SensorLimits", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "8e9d79d5b49e1f9e449c26f78dc8dd0297260583", "submitter": { "id": 34, "url": "https://patchwork.libcamera.org/api/1.1/people/34/?format=api", "name": "Naushir Patuck", "email": "naush@raspberrypi.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/18440/mbox/", "series": [ { "id": 3811, "url": "https://patchwork.libcamera.org/api/1.1/series/3811/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3811", "date": "2023-03-22T16:13:14", "name": "Raspberry Pi: Sensor limits", "version": 1, "mbox": "https://patchwork.libcamera.org/series/3811/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/18440/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/18440/checks/", "tags": {}, "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 587D7C329C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 22 Mar 2023 16:13:18 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3CD69626E6;\n\tWed, 22 Mar 2023 17:13:17 +0100 (CET)", "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 778DD61ECE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 Mar 2023 17:13:14 +0100 (CET)", "by mail-io1-xd29.google.com with SMTP id e13so648119ioc.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 Mar 2023 09:13:14 -0700 (PDT)", "from localhost.localdomain ([93.93.133.154])\n\tby smtp.gmail.com with ESMTPSA id\n\tn24-20020a02a918000000b004050d92f6d4sm5100119jam.50.2023.03.22.09.13.12\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 22 Mar 2023 09:13:12 -0700 (PDT)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1679501597;\n\tbh=VYKperBBYbHQZ4V5a/30P5cKliRg9gd4k2sKwfLuepQ=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=X61uoHXXAU0xbR4m4GVI3xdYUWNCHI/n5eWbEOAZU4Ttq3iRRbnVrw5iyv5wLMQya\n\tOx/WFnpLsHfzMhNoP7zFJJwvjE9bGeJXmJTia2mSfGbWhxdbtX5PrKNcZH8MrxFLYw\n\t/HUo8/Bf/lfJUCpyhKznnbadVk2d7VQUYxaPuYMbt8Qen5SydzTWxQwhmDD/s9LuWh\n\tmbYleYZ1Bap05V87tU024zsGooMAczZMB+t0f+bcy0nrPdWMqwHWO3LDfhwmqDf6yL\n\tCIi/xMqkfpB1AAn1+8Lt+c8yRuSqJEQggjLA2Uvxmf+nvTEDJsVymW12fY+6bjUN4Y\n\tjeb78LjUP9RCw==", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1679501593;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=AI7QePFulGJyiLBn7dSeGdrq5BdJQids08mpyLUydP4=;\n\tb=F4egNLotmWHGTzacRI9UkfyzGWsPJkwL7IZD97xYQSzFoLObee6uYFZWYaGZNVIo/p\n\tmLE+qt9J/LgcA2e/IhLW8jYwwszqcK9EPaE/lzV2ov3rMowWnpnXAJrTJ68V1riLHudy\n\t1JglvtC8apYMk7Sh+3w+WkIrPnfQKT1IdRO90edQf0OMWJcsxbcdklrI5mUMl9ksr30Q\n\t9vFjm6OxJtxBX5YZgIvsmQuPWTbe3fMAXBOxXzZtWEoRxuk47BQ4Q73r3vsZSG6ps6V3\n\tlBQ0kiowF/HDx8YF4h/Pc/mEEZtT16Jz9mZ3CWD4JXd97eFghhhh0RQCqEuVNp/2BFU3\n\t4ruw==" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"F4egNLot\"; dkim-atps=neutral", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112; t=1679501593;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n\t:subject:date:message-id:reply-to;\n\tbh=AI7QePFulGJyiLBn7dSeGdrq5BdJQids08mpyLUydP4=;\n\tb=1RAgXEc7nszvna3OEPxftsmeuH36d11lboqwXP1Aqtd9aXeVUm4M73UcDs5i1dCFst\n\t4E7sOkAhpGN2wxRyr5l+KMI9bglrQvBJgg4VrP0DWxaOhmTyo2plEWJQ1OpoPCIKG/2I\n\t53CCYC9Zpsy9ZlDvREBxPqVwwNnBtjeUvTyl43x+SP/SFp2DWm93mxBKH/tp7Ru0eaqS\n\t3PXmcHlBZy9vwm7YuZXrLDBbbygJrGI6BE+9Hew0tliMrjfTBCepkyb6+PmmYJaol96a\n\t1ccU7+Y+yN5S2+6lfwA/2kO/C4XG3AnaFe3Nddyn6BEYBJ6v+g2igpjdt6uhUbdgUD5m\n\tsDxw==", "X-Gm-Message-State": "AO0yUKXenTCoaDJZ86spIO48gU3Nt+A60Cpjn775le2sMhc9R+30vjAf\n\t08KSXI53IZJhZXDIdRuLAEJi9DZDrl4dywMyMjQ5Hw==", "X-Google-Smtp-Source": "AK7set93R8PCjeemzJiLvNnDyuxgxfwLDI8Bht2ua74uYZhrMM/jTp5jP+W9QosvUAdU4t0y9WjwbQ==", "X-Received": "by 2002:a6b:7613:0:b0:751:df6e:79ba with SMTP id\n\tg19-20020a6b7613000000b00751df6e79bamr1927007iom.5.1679501593055; \n\tWed, 22 Mar 2023 09:13:13 -0700 (PDT)", "To": "libcamera-devel@lists.libcamera.org", "Date": "Wed, 22 Mar 2023 16:13:16 +0000", "Message-Id": "<20230322161317.18055-3-naush@raspberrypi.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20230322161317.18055-1-naush@raspberrypi.com>", "References": "<20230322161317.18055-1-naush@raspberrypi.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v1 2/3] ipa: raspberrypi: Populate\n\tSensorLimits", "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>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "Populate all the fields of the SensorLimits structure in configure().\nThis allows us to use the cached values instead of re-computing them\non every frame.\n\nFor the gain -> code convertion, ensure we clamp to the analogue gain\nlimits set in the SensorLimits structure.\n\nSigned-off-by: Naushir Patuck <naush@raspberrypi.com>\nReviewed-by: David Plowman <david.plowman@raspberrypi.com>\n---\n src/ipa/raspberrypi/raspberrypi.cpp | 67 ++++++++++++++++-------------\n 1 file changed, 38 insertions(+), 29 deletions(-)", "diff": "diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex c3b2c375036f..e8d8023bcfe7 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -224,8 +224,8 @@ private:\n \tDuration minFrameDuration_;\n \tDuration maxFrameDuration_;\n \n-\t/* Maximum gain code for the sensor. */\n-\tuint32_t maxSensorGainCode_;\n+\t/* Mode specific sensor gain/exposure limits. */\n+\tRPiController::AgcAlgorithm::SensorLimits sensorLimits_;\n \n \t/* Track the frame length times over FrameLengthsQueueSize frames. */\n \tstd::deque<Duration> frameLengths_;\n@@ -439,8 +439,6 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo, const IPAConfig &ip\n \t\t}\n \t}\n \n-\tmaxSensorGainCode_ = sensorCtrls_.at(V4L2_CID_ANALOGUE_GAIN).max().get<int32_t>();\n-\n \t/* Setup a metadata ControlList to output metadata. */\n \tlibcameraMetadata_ = ControlList(controls::controls);\n \n@@ -473,6 +471,28 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo, const IPAConfig &ip\n \t/* Pass the camera mode to the CamHelper to setup algorithms. */\n \thelper_->setCameraMode(mode_);\n \n+\t/*\n+\t * Store the sensor gain and shutter limits for the mode.\n+\t *\n+\t * The maximum shutter value are calculated from the frame duration limit\n+\t * as V4L2 will restrict the maximum control value based on the current\n+\t * VBLANK value.\n+\t *\n+\t * These limits get set in the AGC algorithm through applyFrameDurations()\n+\t * below.\n+\t */\n+\tconst ControlInfo &gainCtrl = sensorCtrls_.at(V4L2_CID_ANALOGUE_GAIN);\n+\tconst ControlInfo &shutterCtrl = sensorCtrls_.at(V4L2_CID_EXPOSURE);\n+\n+\tsensorLimits_.minAnalogueGain = helper_->gain(gainCtrl.min().get<int32_t>());\n+\tsensorLimits_.maxAnalogueGain = helper_->gain(gainCtrl.max().get<int32_t>());\n+\tsensorLimits_.minFrameDuration = mode_.minFrameLength * mode_.minLineLength;\n+\tsensorLimits_.maxFrameDuration = mode_.maxFrameLength * mode_.maxLineLength;\n+\tsensorLimits_.minShutter = helper_->exposure(shutterCtrl.min().get<int32_t>(), mode_.minLineLength);\n+\tsensorLimits_.maxShutter = Duration::max();\n+\thelper_->getBlanking(sensorLimits_.maxShutter,\n+\t\t\t sensorLimits_.minFrameDuration, sensorLimits_.maxFrameDuration);\n+\n \t/*\n \t * Initialise this ControlList correctly, even if empty, in case the IPA is\n \t * running is isolation mode (passing the ControlList through the IPC layer).\n@@ -501,26 +521,17 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo, const IPAConfig &ip\n \t * based on the current sensor mode.\n \t */\n \tControlInfoMap::Map ctrlMap = ipaControls;\n-\tconst Duration minSensorFrameDuration = mode_.minFrameLength * mode_.minLineLength;\n-\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.maxLineLength;\n \tctrlMap[&controls::FrameDurationLimits] =\n-\t\tControlInfo(static_cast<int64_t>(minSensorFrameDuration.get<std::micro>()),\n-\t\t\t static_cast<int64_t>(maxSensorFrameDuration.get<std::micro>()));\n+\t\tControlInfo(static_cast<int64_t>(sensorLimits_.minFrameDuration.get<std::micro>()),\n+\t\t\t static_cast<int64_t>(sensorLimits_.maxFrameDuration.get<std::micro>()));\n \n \tctrlMap[&controls::AnalogueGain] =\n-\t\tControlInfo(1.0f, static_cast<float>(helper_->gain(maxSensorGainCode_)));\n-\n-\t/*\n-\t * Calculate the max exposure limit from the frame duration limit as V4L2\n-\t * will limit the maximum control value based on the current VBLANK value.\n-\t */\n-\tDuration maxShutter = Duration::max();\n-\thelper_->getBlanking(maxShutter, minSensorFrameDuration, maxSensorFrameDuration);\n-\tconst uint32_t exposureMin = sensorCtrls_.at(V4L2_CID_EXPOSURE).min().get<int32_t>();\n+\t\tControlInfo(static_cast<float>(sensorLimits_.minAnalogueGain),\n+\t\t\t static_cast<float>(sensorLimits_.maxAnalogueGain));\n \n \tctrlMap[&controls::ExposureTime] =\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+\t\tControlInfo(static_cast<int32_t>(sensorLimits_.minShutter.get<std::micro>()),\n+\t\t\t static_cast<int32_t>(sensorLimits_.maxShutter.get<std::micro>()));\n \n \t/* Declare Autofocus controls, only if we have a controllable lens */\n \tif (lensPresent_)\n@@ -1480,9 +1491,6 @@ void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n \n void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration)\n {\n-\tconst Duration minSensorFrameDuration = mode_.minFrameLength * mode_.minLineLength;\n-\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.maxLineLength;\n-\n \t/*\n \t * This will only be applied once AGC recalculations occur.\n \t * The values may be clamped based on the sensor mode capabilities as well.\n@@ -1490,9 +1498,9 @@ void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDur\n \tminFrameDuration_ = minFrameDuration ? minFrameDuration : defaultMaxFrameDuration;\n \tmaxFrameDuration_ = maxFrameDuration ? maxFrameDuration : defaultMinFrameDuration;\n \tminFrameDuration_ = std::clamp(minFrameDuration_,\n-\t\t\t\t minSensorFrameDuration, maxSensorFrameDuration);\n+\t\t\t\t sensorLimits_.minFrameDuration, sensorLimits_.maxFrameDuration);\n \tmaxFrameDuration_ = std::clamp(maxFrameDuration_,\n-\t\t\t\t minSensorFrameDuration, maxSensorFrameDuration);\n+\t\t\t\t sensorLimits_.minFrameDuration, sensorLimits_.maxFrameDuration);\n \tmaxFrameDuration_ = std::max(maxFrameDuration_, minFrameDuration_);\n \n \t/* Return the validated limits via metadata. */\n@@ -1505,17 +1513,18 @@ void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDur\n \t * getBlanking() will update maxShutter with the largest exposure\n \t * value possible.\n \t */\n-\tRPiController::AgcAlgorithm::SensorLimits limits;\n-\tlimits.maxShutter = Duration::max();\n-\thelper_->getBlanking(limits.maxShutter, minFrameDuration_, maxFrameDuration_);\n+\tsensorLimits_.maxShutter = Duration::max();\n+\thelper_->getBlanking(sensorLimits_.maxShutter, minFrameDuration_, maxFrameDuration_);\n \n \tRPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(\n \t\tcontroller_.getAlgorithm(\"agc\"));\n-\tagc->setSensorLimits(limits);\n+\tagc->setSensorLimits(sensorLimits_);\n }\n \n void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n {\n+\tconst int32_t minGainCode = helper_->gainCode(sensorLimits_.minAnalogueGain);\n+\tconst int32_t maxGainCode = helper_->gainCode(sensorLimits_.maxAnalogueGain);\n \tint32_t gainCode = helper_->gainCode(agcStatus->analogueGain);\n \n \t/*\n@@ -1523,7 +1532,7 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n \t * DelayedControls. The AGC will correctly handle a lower gain returned\n \t * by the sensor, provided it knows the actual gain used.\n \t */\n-\tgainCode = std::min<int32_t>(gainCode, maxSensorGainCode_);\n+\tgainCode = std::clamp<int32_t>(gainCode, minGainCode, maxGainCode);\n \n \t/* getBlanking might clip exposure time to the fps limits. */\n \tDuration exposure = agcStatus->shutterTime;\n", "prefixes": [ "libcamera-devel", "v1", "2/3" ] }