Patch Detail
Show a patch.
GET /api/1.1/patches/17702/?format=api
{ "id": 17702, "url": "https://patchwork.libcamera.org/api/1.1/patches/17702/?format=api", "web_url": "https://patchwork.libcamera.org/patch/17702/", "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": "<20221027224135.348115-2-nicholas@rothemail.net>", "date": "2022-10-27T22:41:26", "name": "[libcamera-devel,v4,01/10] ipa: workaround libcxx duration limitation", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "ab7e2b59a6d5a2e3fd512d58c53fb228bbb2e4dd", "submitter": { "id": 97, "url": "https://patchwork.libcamera.org/api/1.1/people/97/?format=api", "name": "Nicolas Dufresne via libcamera-devel", "email": "libcamera-devel@lists.libcamera.org" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/17702/mbox/", "series": [ { "id": 3581, "url": "https://patchwork.libcamera.org/api/1.1/series/3581/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3581", "date": "2022-10-27T22:41:26", "name": "[libcamera-devel,v4,01/10] ipa: workaround libcxx duration limitation", "version": 4, "mbox": "https://patchwork.libcamera.org/series/3581/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/17702/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/17702/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 50222BDB16\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Oct 2022 22:41:46 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id DA6FF62FB3;\n\tFri, 28 Oct 2022 00:41:45 +0200 (CEST)", "from mail-oa1-x31.google.com (mail-oa1-x31.google.com\n\t[IPv6:2001:4860:4864:20::31])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AED7562FA0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 28 Oct 2022 00:41:42 +0200 (CEST)", "by mail-oa1-x31.google.com with SMTP id\n\t586e51a60fabf-13b103a3e5dso4315376fac.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Oct 2022 15:41:42 -0700 (PDT)", "from nroth-pc.attlocal.net\n\t([2600:1700:20:20c0:6a4b:7aa7:dda2:75cb])\n\tby smtp.gmail.com with ESMTPSA id\n\tr20-20020a056830419400b006619533d1ddsm976825otu.76.2022.10.27.15.41.40\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 27 Oct 2022 15:41:40 -0700 (PDT)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666910506;\n\tbh=KWL/Gsut2winiwjuDaIMQfAIE6R+nge1tS6vEQwVGqw=;\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:Cc:\n\tFrom;\n\tb=d8cZicGMYl0KT9o6pTmI/PKpcvxEvHfqcYllFuToyfHbU7C5kHLpl3Fyi0Nw6tcXt\n\tPI9sINJ35Euff2hHdxC8XPtgMMvcAteIkEDB1fiMhFVNKk03D935BR3GEacpZSb+bW\n\tGA3OZf2jQsTGsmlw21mPT0tDTLhtnYzIgbzRj2pXWYNUFFoqNLmIHhYVG/3FGcPsPF\n\tBKdodx57xloE9A/4565GMDx0I4ZWckbO/bY+N4SwjzOX/nGbBc2GDoRz56YaiX1JxT\n\tis4xcufRx63okOrU0QUBNcfFEHZLlhSjyKfSEDTqI3tQdbrazk34X5WszuJLj9UeQR\n\tv65nGTNKv9Adg==", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=rothemail-net.20210112.gappssmtp.com; s=20210112;\n\th=content-transfer-encoding:mime-version:reply-to:references\n\t:in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=uDW5dvSvOk67QVcuydLzLD48wSWjb/FyOIOUWFCTpuM=;\n\tb=RO17LY5J+MsUYZk5CUIOWWO1GMQvzXFjDdhuKbH75gADWGdNM1fejI47MZW0ZeNn7X\n\tQ/BMvmdH5gsW8Zo0bQO6FxgT+FXA+TC9bovIrHzgzRntDTvB9zTX5zFZ3Etzvox1wwsk\n\t+qbUs/BGNr+YWG+nfRk4Rn7NGJXcU+MKnZJisK/zS1RYaZPT8zA1nBaDRGOLfoM3BbF1\n\tQrd9aWNK0nzgIa1ayZA9qB6MJxsWkGu0ZtdAV5vEtQgR6LqRm/qy7HxmwaefHgjz8Ej3\n\tndQKyln39cmV+yagNBW1qa9eobcDwV+/P/1K9uXH+9P7+R/Yf2srFbglkZgK6nDmMZRt\n\t8ziQ==" ], "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=\"RO17LY5J\"; \n\tdkim-atps=neutral", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=content-transfer-encoding:mime-version:reply-to:references\n\t:in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state\n\t:from:to:cc:subject:date:message-id:reply-to;\n\tbh=uDW5dvSvOk67QVcuydLzLD48wSWjb/FyOIOUWFCTpuM=;\n\tb=AnH1FNkA0MgEo8kPzCVYFj/HxQlxfFhVb6q8vu6zPTaMqa6tHPx5FMJ7L0pgaY0/va\n\tVpx7nKE2t7vv/e/pghLOME6lA/tpEYhjSW/v+stQ0FFDNV6vwsvoAeUdgR0SEoMfRnSp\n\t5Jlu7WIL3ZCtJ497clPzIhROB0IH+JUOPj9LoR4crzgBoj5rtq/erqc/rr2octClSyJL\n\tpf4zWGFxfk00JT5z0JcTtoFBFf2z4YB2cDt8bsInKKX+d/ZZpYLjAgsnnGaFaQVYN9dQ\n\tEyFM0qT/TASWYfHRvcKTT41alwNCBs2v03gXEzUOfddMXEjk8oSfTAZvMkbc2nhta2aB\n\t0tBA==", "X-Gm-Message-State": "ACrzQf0kMPakCBne6DNODQRjBEqh6xp1ZE/cqZuInxXDxSHbGS6iq2Ij\n\tsAZfU/ujMAH3PRjbgiaE+w1oR314GdA8hMbG", "X-Google-Smtp-Source": "AMsMyM7xsMlYcmEtvlblhITYO4TjwC9ZtlZf5pKInXLQXv37Zjs7d9VfjLVwi9D4UF7t/g5VhvHjSA==", "X-Received": "by 2002:a05:6870:2417:b0:127:be13:2d1 with SMTP id\n\tn23-20020a056870241700b00127be1302d1mr7002288oap.268.1666910500835; \n\tThu, 27 Oct 2022 15:41:40 -0700 (PDT)", "To": "libcamera-devel@lists.libcamera.org", "Date": "Thu, 27 Oct 2022 17:41:26 -0500", "Message-Id": "<20221027224135.348115-2-nicholas@rothemail.net>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20221027224135.348115-1-nicholas@rothemail.net>", "References": "<20221027224135.348115-1-nicholas@rothemail.net>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v4 01/10] ipa: workaround libcxx duration\n\tlimitation", "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": "libcamera-devel@lists.libcamera.org", "Cc": "nicholas@rothemail.net", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "From: Nicholas Roth <nicholas@rothemail.net>\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] 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 src/ipa/ipu3/algorithms/agc.cpp | 16 ++++++++++------\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.swp | Bin 0 -> 45056 bytes\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 7 files changed, 33 insertions(+), 19 deletions(-)\n create mode 100644 src/ipa/raspberrypi/controller/rpi/.agc.cpp.swp", "diff": "diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\nindex a1a3c38f..f1650468 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 \t/* Configure the default exposure and gain. */\n \tactiveState.agc.gain = std::max(minAnalogueGain_, kMinAnalogueGain);\n-\tactiveState.agc.exposure = 10ms / configuration.sensor.lineDuration;\n+\tactiveState.agc.exposure = 10ms /\n+\t\t\t\tstd::chrono::duration(configuration.sensor.lineDuration);\n \n \tframeCount_ = 0;\n \treturn 0;\n@@ -240,17 +241,20 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n \t * increase the gain.\n \t */\n \tutils::Duration shutterTime =\n-\t\tstd::clamp<utils::Duration>(exposureValue / minAnalogueGain_,\n-\t\t\t\t\t minShutterSpeed_, maxShutterSpeed_);\n-\tdouble stepGain = std::clamp(exposureValue / shutterTime,\n-\t\t\t\t minAnalogueGain_, maxAnalogueGain_);\n+\t\tstd::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n+\t\t\t\t\t\tminAnalogueGain_,\n+\t\t\t\t\tminShutterSpeed_, maxShutterSpeed_);\n+\tdouble stepGain = std::clamp(std::chrono::duration(exposureValue) /\n+\t\t\t\t\tstd::chrono::duration(shutterTime),\n+\t\t\t\tminAnalogueGain_, maxAnalogueGain_);\n \tLOG(IPU3Agc, Debug) << \"Divided up shutter and gain are \"\n \t\t\t << shutterTime << \" and \"\n \t\t\t << stepGain;\n \n \tIPAActiveState &activeState = context.activeState;\n \t/* Update the estimated exposure and gain. */\n-\tactiveState.agc.exposure = shutterTime / configuration.sensor.lineDuration;\n+\tactiveState.agc.exposure = std::chrono::duration(shutterTime) /\n+\t\t\t\tstd::chrono::duration(configuration.sensor.lineDuration);\n \tactiveState.agc.gain = stepGain;\n }\n \ndiff --git a/src/ipa/raspberrypi/cam_helper.cpp b/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 &stats,\n \n uint32_t CamHelper::exposureLines(const Duration exposure, const Duration lineLength) const\n {\n-\treturn exposure / lineLength;\n+\treturn std::chrono::duration(exposure) / std::chrono::duration(lineLength);\n }\n \n Duration CamHelper::exposure(uint32_t exposureLines, const Duration lineLength) const\n@@ -85,8 +85,8 @@ std::pair<uint32_t, uint32_t> CamHelper::getBlanking(Duration &exposure,\n \t * frameLengthMax gets calculated on the smallest line length as we do\n \t * not want to extend that unless absolutely necessary.\n \t */\n-\tframeLengthMin = minFrameDuration / mode_.minLineLength;\n-\tframeLengthMax = maxFrameDuration / mode_.minLineLength;\n+\tframeLengthMin = std::chrono::duration(minFrameDuration) / std::chrono::duration(mode_.minLineLength);\n+\tframeLengthMax = std::chrono::duration(maxFrameDuration) / std::chrono::duration(mode_.minLineLength);\n \n \t/*\n \t * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp b/src/ipa/raspberrypi/cam_helper_imx296.cpp\nindex ecb845e7..c5180de5 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 \t\t\t\t\t[[maybe_unused]] const Duration lineLength) const\n {\n-\treturn std::max<uint32_t>(minExposureLines, (exposure - 14.26us) / timePerLine);\n+\treturn std::max<uint32_t>(minExposureLines, std::chrono::duration(exposure - 14.26us) /\n+\t\t\t\t\t\t\tstd::chrono::duration(timePerLine));\n }\n \n Duration CamHelperImx296::exposure(uint32_t exposureLines,\ndiff --git a/src/ipa/raspberrypi/controller/rpi/.agc.cpp.swp b/src/ipa/raspberrypi/controller/rpi/.agc.cpp.swp\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..7b26d5511f7338b4cd3f28246243c9110c39aab0\nGIT binary patch\nliteral 45056\n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\nE2js%%=l}o!\n\nliteral 0\nHcmV?d00001\n\ndiff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp\nindex bd54a639..65baab99 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 \t\t\tDuration actualExposure = deviceStatus.shutterSpeed *\n \t\t\t\t\t\t deviceStatus.analogueGain;\n \t\t\tif (actualExposure) {\n-\t\t\t\tstatus_.digitalGain = status_.totalExposureValue / actualExposure;\n+\t\t\t\tstatus_.digitalGain = std::chrono::duration(status_.totalExposureValue) /\n+\t\t\t\t\t\t\tstd::chrono::duration(actualExposure);\n \t\t\t\tLOG(RPiAgc, Debug) << \"Want total exposure \" << status_.totalExposureValue;\n \t\t\t\t/*\n \t\t\t\t * Never ask for a gain < 1.0, and also impose\n@@ -823,7 +824,8 @@ void Agc::divideUpExposure()\n \t\t\t}\n \t\t\tif (status_.fixedAnalogueGain == 0.0) {\n \t\t\t\tif (exposureMode_->gain[stage] * shutterTime >= exposureValue) {\n-\t\t\t\t\tanalogueGain = exposureValue / shutterTime;\n+\t\t\t\t\tanalogueGain = std::chrono::duration(exposureValue) /\n+\t\t\t\t\t\t\tstd::chrono::duration(shutterTime);\n \t\t\t\t\tbreak;\n \t\t\t\t}\n \t\t\t\tanalogueGain = exposureMode_->gain[stage];\n@@ -838,10 +840,12 @@ void Agc::divideUpExposure()\n \t */\n \tif (!status_.fixedShutter && !status_.fixedAnalogueGain &&\n \t status_.flickerPeriod) {\n-\t\tint flickerPeriods = shutterTime / status_.flickerPeriod;\n+\t\tint flickerPeriods = std::chrono::duration(shutterTime) /\n+\t\t\t\tstd::chrono::duration(status_.flickerPeriod);\n \t\tif (flickerPeriods) {\n \t\t\tDuration newShutterTime = flickerPeriods * status_.flickerPeriod;\n-\t\t\tanalogueGain *= shutterTime / newShutterTime;\n+\t\t\tanalogueGain *= std::chrono::duration(shutterTime) /\n+\t\t\t\t\tstd::chrono::duration(newShutterTime);\n \t\t\t/*\n \t\t\t * We should still not allow the ag to go over the\n \t\t\t * largest value in the exposure mode. Note that this\ndiff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp\nindex 9759186a..410f6f44 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 *imageMetadata)\n \t\tdouble currentY = sum / (double)num + .5;\n \t\tdouble gainRatio = referenceGain_ / currentGain;\n \t\tdouble shutterSpeedRatio =\n-\t\t\treferenceShutterSpeed_ / deviceStatus.shutterSpeed;\n+\t\t\tstd::chrono::duration(referenceShutterSpeed_) /\n+\t\t\tstd::chrono::duration(deviceStatus.shutterSpeed);\n \t\tdouble apertureRatio = referenceAperture_ / currentAperture;\n \t\tdouble yRatio = currentY * (65536 / numBins) / referenceY_;\n \t\tdouble estimatedLux = shutterSpeedRatio * gainRatio *\ndiff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex 04062a36..bb874356 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 IPACameraSensorInfo &configInfo)\n {\n \t/* Configure the default exposure and gain. */\n \tcontext.activeState.agc.gain = std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain);\n-\tcontext.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration;\n+\tcontext.activeState.agc.exposure = 10ms /\n+\t\t\t\t\tstd::chrono::duration(context.configuration.sensor.lineDuration);\n \n \t/*\n \t * According to the RkISP1 documentation:\n@@ -212,16 +213,19 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,\n \t * Push the shutter time up to the maximum first, and only then\n \t * increase the gain.\n \t */\n-\tutils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue / minAnalogueGain,\n+\tutils::Duration shutterTime = std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /\n+\t\t\t\t\t\t\t\t\tminAnalogueGain,\n \t\t\t\t\t\t\t\t minShutterSpeed, maxShutterSpeed);\n-\tdouble stepGain = std::clamp(exposureValue / shutterTime,\n+\tdouble stepGain = std::clamp(std::chrono::duration(exposureValue) /\n+\t\t\t\t\t\tstd::chrono::duration(shutterTime),\n \t\t\t\t minAnalogueGain, maxAnalogueGain);\n \tLOG(RkISP1Agc, Debug) << \"Divided up shutter and gain are \"\n \t\t\t << shutterTime << \" and \"\n \t\t\t << stepGain;\n \n \t/* Update the estimated exposure and gain. */\n-\tactiveState.agc.exposure = shutterTime / configuration.sensor.lineDuration;\n+\tactiveState.agc.exposure = std::chrono::duration(shutterTime) /\n+\t\t\t\tstd::chrono::duration(configuration.sensor.lineDuration);\n \tactiveState.agc.gain = stepGain;\n }\n \n", "prefixes": [ "libcamera-devel", "v4", "01/10" ] }