Patch Detail
Show a patch.
GET /api/patches/19057/?format=api
{ "id": 19057, "url": "https://patchwork.libcamera.org/api/patches/19057/?format=api", "web_url": "https://patchwork.libcamera.org/patch/19057/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/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": "<20230918105027.4170-2-david.plowman@raspberrypi.com>", "date": "2023-09-18T10:50:26", "name": "[libcamera-devel,v3,1/2] ipa: rpi: Add an HDR algorithm to drive multi-channel AGC", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "aee47296054f42149e28772647830aa8a14c0826", "submitter": { "id": 42, "url": "https://patchwork.libcamera.org/api/people/42/?format=api", "name": "David Plowman", "email": "david.plowman@raspberrypi.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/19057/mbox/", "series": [ { "id": 4031, "url": "https://patchwork.libcamera.org/api/series/4031/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4031", "date": "2023-09-18T10:50:25", "name": "HDR for Raspberry Pi", "version": 3, "mbox": "https://patchwork.libcamera.org/series/4031/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/19057/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/19057/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 38E7FC326C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 18 Sep 2023 10:50:34 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F069462942;\n\tMon, 18 Sep 2023 12:50:33 +0200 (CEST)", "from mail-wr1-x434.google.com (mail-wr1-x434.google.com\n\t[IPv6:2a00:1450:4864:20::434])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8C2306293D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Sep 2023 12:50:32 +0200 (CEST)", "by mail-wr1-x434.google.com with SMTP id\n\tffacd0b85a97d-31dca134c83so4375657f8f.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Sep 2023 03:50:32 -0700 (PDT)", "from pi4-davidp.pitowers.org\n\t([2a00:1098:3142:14:2bce:64d6:1a5c:49a2])\n\tby smtp.gmail.com with ESMTPSA id\n\to12-20020adfeacc000000b003176c6e87b1sm3415249wrn.81.2023.09.18.03.50.30\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 18 Sep 2023 03:50:30 -0700 (PDT)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1695034234;\n\tbh=5o6snAwmMyZrdUu5jablI7TO1M+9BxAx8bHMSauCrgY=;\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=kO67BHKuBbYF9ciRGtM7JsHossM9UdLABOjVIQdmB6QUI7vVTBQ6In4PTyd8AAj4o\n\tAAI02JZxO95lXcfCIpEU5hJ9n9Tdouj5HLIH+oWnxJvSiAWPECRCZ+TUCFFPp3awJr\n\ti3sV3FBcPwuVOVThaYuD1DW4rcogrySTpeeNDM6EpMHnkPCDPt4imGYWnT36SWA5/S\n\t1CxT4t+DeUQkPxfXGCuxSmlg0HxqjkSKWr0zeGck66EPjtA47yC5kvtYIzrK+8yI1F\n\tioBXYOBhlZUSoTvOF9E5jVb0j7tYHTo+9I98pM68ZYswcIecG/Daxx+MKtvTsC4r5g\n\t8oDwNshIENbzA==", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1695034231; x=1695639031;\n\tdarn=lists.libcamera.org; \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=KRDkhyuWeq3rCXoVU2No3kNPzaL5NXFZPlh8z0oNz/Q=;\n\tb=dsorKgOwx7+fkzpZtI/9BKBaHfUuSmFX+LOjnFG1q0O3PeD917W7Vs1j2x6A6oGdFX\n\tswOvOo/E5QDuKh6argB9afTXd9hfRbJWuaJmVETLN7spLzkx+tixk1PW0aVYJj0N2nu/\n\tbAzSlAN5I5fDv3MVfX8e+lN2BXOSOhMN5mHlKw5zjhwP+eaEhCgd9RHrb1tc+pQr7+7y\n\tz8H+B5bbspEkteSVn/KxZdFg/V+we96bNNDUuqkoFKzzrld6YtGpLmqr8W5fQND4Ihfr\n\tgxaTeeUeoCPo2CHODArMRPweFf2rLdBrYVwphU9jNO3TADNa1AI+NNnNrQYAlkFGddsE\n\tDCFg==" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"dsorKgOw\"; dkim-atps=neutral", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1695034231; x=1695639031;\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=KRDkhyuWeq3rCXoVU2No3kNPzaL5NXFZPlh8z0oNz/Q=;\n\tb=rAl58bsd28FrvrtEpNxotLAJFaCnb04fADthlatJJpxSO4NAH18IEGGhTcIgyn2WDD\n\tWACZ/TDbm9WTtlhIYZ7raEgPAMpH262bHS94fUbr5umj7gUjTVRj3Dg2rAx9CxRBMcrF\n\tEsvdFqt2oolvWedzOOzKrUE/izNvvNujOE3ikrhg8o0jp6NJ4hcymoFc9Z1t/4IGTZVM\n\tOz6ASNPJq/SSjelZx3MEfe1bIOdvTi1Gu6HXCRQi2qsZPSR3I+7YqZGxu6nwMvQ1ACXw\n\tuXsIxyW9RbgO4gRRlP/ZWe1qfcgHtViS4KIAGZFwEAs5TWFZijygY4CUn6i6uwECOjp8\n\tdyAw==", "X-Gm-Message-State": "AOJu0YzeMbbOIb3Quov1VQkOB6Ss0nPbGChzmLXTyI6fTKKb1uZkEY6e\n\tl3xPgEmlPa8c2GBLTlXTx0Qedps7l5CA7VAZOgk=", "X-Google-Smtp-Source": "AGHT+IFrnkiMtekEgYqui6bEb9XIDBvYRw56kWAw3n08VwUXWtJHKWsaRK4oHep/FqqTwTkgpSyS5A==", "X-Received": "by 2002:a5d:4706:0:b0:319:7c14:b06b with SMTP id\n\ty6-20020a5d4706000000b003197c14b06bmr6747568wrq.47.1695034231628; \n\tMon, 18 Sep 2023 03:50:31 -0700 (PDT)", "To": "libcamera-devel@lists.libcamera.org", "Date": "Mon, 18 Sep 2023 11:50:26 +0100", "Message-Id": "<20230918105027.4170-2-david.plowman@raspberrypi.com>", "X-Mailer": "git-send-email 2.30.2", "In-Reply-To": "<20230918105027.4170-1-david.plowman@raspberrypi.com>", "References": "<20230918105027.4170-1-david.plowman@raspberrypi.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v3 1/2] ipa: rpi: Add an HDR algorithm to\n\tdrive multi-channel AGC", "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": "David Plowman via libcamera-devel <libcamera-devel@lists.libcamera.org>", "Reply-To": "David Plowman <david.plowman@raspberrypi.com>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "This HDR algorithm doesn't combine images in any way, but simply\nallows an application to drive the AGC in a multi-channel HDR type of\nmode, such as to produce short and long exposure images.\n\nSufficient plumbing is added to enable the libcamera HDR controls and\nmetadata to work.\n\nSigned-off-by: David Plowman <david.plowman@raspberrypi.com>\nReviewed-by: Naushir Patuck <naush@raspberrypi.com>\n---\n src/ipa/rpi/common/ipa_base.cpp | 49 +++++++++\n src/ipa/rpi/controller/hdr_algorithm.h | 25 +++++\n src/ipa/rpi/controller/hdr_status.h | 19 ++++\n src/ipa/rpi/controller/meson.build | 1 +\n src/ipa/rpi/controller/rpi/hdr.cpp | 132 +++++++++++++++++++++++++\n src/ipa/rpi/controller/rpi/hdr.h | 44 +++++++++\n 6 files changed, 270 insertions(+)\n create mode 100644 src/ipa/rpi/controller/hdr_algorithm.h\n create mode 100644 src/ipa/rpi/controller/hdr_status.h\n create mode 100644 src/ipa/rpi/controller/rpi/hdr.cpp\n create mode 100644 src/ipa/rpi/controller/rpi/hdr.h", "diff": "diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\nindex f7e7ad5e..231e8f96 100644\n--- a/src/ipa/rpi/common/ipa_base.cpp\n+++ b/src/ipa/rpi/common/ipa_base.cpp\n@@ -24,6 +24,8 @@\n #include \"controller/ccm_status.h\"\n #include \"controller/contrast_algorithm.h\"\n #include \"controller/denoise_algorithm.h\"\n+#include \"controller/hdr_algorithm.h\"\n+#include \"controller/hdr_status.h\"\n #include \"controller/lux_status.h\"\n #include \"controller/sharpen_algorithm.h\"\n #include \"controller/statistics.h\"\n@@ -67,6 +69,7 @@ const ControlInfoMap::Map ipaControls{\n \t{ &controls::AeFlickerPeriod, ControlInfo(100, 1000000) },\n \t{ &controls::Brightness, ControlInfo(-1.0f, 1.0f, 0.0f) },\n \t{ &controls::Contrast, ControlInfo(0.0f, 32.0f, 1.0f) },\n+\t{ &controls::HdrMode, ControlInfo(controls::HdrModeValues) },\n \t{ &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },\n \t{ &controls::ScalerCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },\n \t{ &controls::FrameDurationLimits, ControlInfo(INT64_C(33333), INT64_C(120000)) },\n@@ -658,9 +661,17 @@ static const std::map<int32_t, RPiController::AfAlgorithm::AfPause> AfPauseTable\n \t{ controls::AfPauseResume, RPiController::AfAlgorithm::AfPauseResume },\n };\n \n+static const std::map<int32_t, std::string> HdrModeTable = {\n+\t{ controls::HdrModeOff, \"Off\" },\n+\t{ controls::HdrModeMultiExposure, \"MultiExposure\" },\n+\t{ controls::HdrModeSingleExposure, \"SingleExposure\" },\n+};\n+\n void IpaBase::applyControls(const ControlList &controls)\n {\n+\tusing RPiController::AgcAlgorithm;\n \tusing RPiController::AfAlgorithm;\n+\tusing RPiController::HdrAlgorithm;\n \n \t/* Clear the return metadata buffer. */\n \tlibcameraMetadata_.clear();\n@@ -1157,6 +1168,34 @@ void IpaBase::applyControls(const ControlList &controls)\n \t\t\tbreak;\n \t\t}\n \n+\t\tcase controls::HDR_MODE: {\n+\t\t\tHdrAlgorithm *hdr = dynamic_cast<HdrAlgorithm *>(controller_.getAlgorithm(\"hdr\"));\n+\t\t\tif (!hdr) {\n+\t\t\t\tLOG(IPARPI, Warning) << \"No HDR algorithm available\";\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tauto mode = HdrModeTable.find(ctrl.second.get<int32_t>());\n+\t\t\tif (mode == HdrModeTable.end()) {\n+\t\t\t\tLOG(IPARPI, Warning) << \"Unrecognised HDR mode\";\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tAgcAlgorithm *agc = dynamic_cast<AgcAlgorithm *>(controller_.getAlgorithm(\"agc\"));\n+\t\t\tif (!agc) {\n+\t\t\t\tLOG(IPARPI, Warning) << \"HDR requires an AGC algorithm\";\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tif (hdr->setMode(mode->second) == 0)\n+\t\t\t\tagc->setActiveChannels(hdr->getChannels());\n+\t\t\telse\n+\t\t\t\tLOG(IPARPI, Warning)\n+\t\t\t\t\t<< \"HDR mode \" << mode->second << \" not supported\";\n+\n+\t\t\tbreak;\n+\t\t}\n+\n \t\tdefault:\n \t\t\tLOG(IPARPI, Warning)\n \t\t\t\t<< \"Ctrl \" << controls::controls.at(ctrl.first)->name()\n@@ -1304,6 +1343,16 @@ void IpaBase::reportMetadata(unsigned int ipaContext)\n \t\tlibcameraMetadata_.set(controls::AfPauseState, p);\n \t}\n \n+\tconst HdrStatus *hdrStatus = rpiMetadata.getLocked<HdrStatus>(\"hdr.status\");\n+\tif (hdrStatus) {\n+\t\tif (hdrStatus->channel == \"short\")\n+\t\t\tlibcameraMetadata_.set(controls::HdrChannel, controls::HdrChannelShort);\n+\t\telse if (hdrStatus->channel == \"long\")\n+\t\t\tlibcameraMetadata_.set(controls::HdrChannel, controls::HdrChannelLong);\n+\t\telse\n+\t\t\tlibcameraMetadata_.set(controls::HdrChannel, controls::HdrChannelNone);\n+\t}\n+\n \tmetadataReady.emit(libcameraMetadata_);\n }\n \ndiff --git a/src/ipa/rpi/controller/hdr_algorithm.h b/src/ipa/rpi/controller/hdr_algorithm.h\nnew file mode 100644\nindex 00000000..f622e099\n--- /dev/null\n+++ b/src/ipa/rpi/controller/hdr_algorithm.h\n@@ -0,0 +1,25 @@\n+/* SPDX-License-Identifier: BSD-2-Clause */\n+/*\n+ * Copyright (C) 2023, Raspberry Pi Ltd\n+ *\n+ * hdr_algorithm.h - HDR control algorithm interface\n+ */\n+#pragma once\n+\n+#include <vector>\n+\n+#include \"algorithm.h\"\n+\n+namespace RPiController {\n+\n+class HdrAlgorithm : public Algorithm\n+{\n+public:\n+\tHdrAlgorithm(Controller *controller)\n+\t\t: Algorithm(controller) {}\n+\t/* An HDR algorithm must provide the following: */\n+\tvirtual int setMode(std::string const &modeName) = 0;\n+\tvirtual std::vector<unsigned int> getChannels() const = 0;\n+};\n+\n+} /* namespace RPiController */\ndiff --git a/src/ipa/rpi/controller/hdr_status.h b/src/ipa/rpi/controller/hdr_status.h\nnew file mode 100644\nindex 00000000..24b1a935\n--- /dev/null\n+++ b/src/ipa/rpi/controller/hdr_status.h\n@@ -0,0 +1,19 @@\n+/* SPDX-License-Identifier: BSD-2-Clause */\n+/*\n+ * Copyright (C) 2023 Raspberry Pi Ltd\n+ *\n+ * hdr_status.h - HDR control algorithm status\n+ */\n+#pragma once\n+\n+#include <string>\n+\n+/*\n+ * The HDR algorithm process method should post an HdrStatus into the image\n+ * metadata under the tag \"hdr.status\".\n+ */\n+\n+struct HdrStatus {\n+\tstd::string mode;\n+\tstd::string channel;\n+};\ndiff --git a/src/ipa/rpi/controller/meson.build b/src/ipa/rpi/controller/meson.build\nindex 20b9cda9..c9a3e850 100644\n--- a/src/ipa/rpi/controller/meson.build\n+++ b/src/ipa/rpi/controller/meson.build\n@@ -16,6 +16,7 @@ rpi_ipa_controller_sources = files([\n 'rpi/contrast.cpp',\n 'rpi/dpc.cpp',\n 'rpi/geq.cpp',\n+ 'rpi/hdr.cpp',\n 'rpi/lux.cpp',\n 'rpi/noise.cpp',\n 'rpi/sdn.cpp',\ndiff --git a/src/ipa/rpi/controller/rpi/hdr.cpp b/src/ipa/rpi/controller/rpi/hdr.cpp\nnew file mode 100644\nindex 00000000..97c7e949\n--- /dev/null\n+++ b/src/ipa/rpi/controller/rpi/hdr.cpp\n@@ -0,0 +1,132 @@\n+/* SPDX-License-Identifier: BSD-2-Clause */\n+/*\n+ * Copyright (C) 2023 Raspberry Pi Ltd\n+ *\n+ * hdr.cpp - HDR control algorithm\n+ */\n+\n+#include \"hdr.h\"\n+\n+#include <libcamera/base/log.h>\n+\n+#include \"../agc_status.h\"\n+\n+using namespace RPiController;\n+using namespace libcamera;\n+\n+LOG_DEFINE_CATEGORY(RPiHdr)\n+\n+#define NAME \"rpi.hdr\"\n+\n+void HdrConfig::read(const libcamera::YamlObject ¶ms, const std::string &modeName)\n+{\n+\tname = modeName;\n+\n+\tif (!params.contains(\"cadence\"))\n+\t\tLOG(RPiHdr, Fatal) << \"No cadence for HDR mode \" << name;\n+\tcadence = params[\"cadence\"].getList<unsigned int>().value();\n+\tif (cadence.empty())\n+\t\tLOG(RPiHdr, Fatal) << \"Empty cadence in HDR mode \" << name;\n+\n+\t/*\n+\t * In the JSON file it's easier to use the channel name as the key, but\n+\t * for us it's convenient to swap them over.\n+\t */\n+\tfor (const auto &[k, v] : params[\"channel_map\"].asDict())\n+\t\tchannelMap[v.get<unsigned int>().value()] = k;\n+}\n+\n+Hdr::Hdr(Controller *controller)\n+\t: HdrAlgorithm(controller),\n+\t currentConfig_(nullptr)\n+{\n+}\n+\n+char const *Hdr::name() const\n+{\n+\treturn NAME;\n+}\n+\n+int Hdr::read(const libcamera::YamlObject ¶ms)\n+{\n+\t/* Make an \"HDR off\" mode by default so that tuning files don't have to. */\n+\tHdrConfig &offMode = config_[\"Off\"];\n+\toffMode.name = \"Off\";\n+\toffMode.cadence = { 0 };\n+\tcurrentConfig_ = &offMode;\n+\n+\t/*\n+\t * But we still allow the tuning file to override the \"Off\" mode if it wants.\n+\t * For example, maybe an application will make channel 0 be the \"short\"\n+\t * channel, in order to apply other AGC controls to it.\n+\t */\n+\tfor (const auto &[key, value] : params.asDict())\n+\t\tconfig_[key].read(value, key);\n+\n+\treturn 0;\n+}\n+\n+int Hdr::setMode(std::string const &mode)\n+{\n+\tauto it = config_.find(mode);\n+\tif (it == config_.end()) {\n+\t\tLOG(RPiHdr, Warning) << \"No such HDR mode \" << mode;\n+\t\treturn -1;\n+\t}\n+\n+\tcurrentConfig_ = &it->second;\n+\n+\treturn 0;\n+}\n+\n+std::vector<unsigned int> Hdr::getChannels() const\n+{\n+\treturn currentConfig_->cadence;\n+}\n+\n+void Hdr::switchMode([[maybe_unused]] CameraMode const &cameraMode,\n+\t\t [[maybe_unused]] Metadata *metadata)\n+{\n+}\n+\n+void Hdr::process([[maybe_unused]] StatisticsPtr &stats, Metadata *imageMetadata)\n+{\n+\tif (currentConfig_->name == \"Off\")\n+\t\treturn;\n+\n+\t/* First find out what AGC channel this is, which comes from the delayed_status. */\n+\tbool channelKnown = false;\n+\tunsigned int agcChannel = 0;\n+\t{\n+\t\tstd::scoped_lock<RPiController::Metadata> lock(*imageMetadata);\n+\t\tAgcStatus *agcStatus = imageMetadata->getLocked<AgcStatus>(\"agc.delayed_status\");\n+\t\tif (agcStatus) {\n+\t\t\tchannelKnown = true;\n+\t\t\tagcChannel = agcStatus->channel;\n+\t\t}\n+\t}\n+\n+\t/* Fill out the HdrStatus information. */\n+\tHdrStatus hdrStatus;\n+\thdrStatus.mode = currentConfig_->name;\n+\tif (channelKnown) {\n+\t\t/*\n+\t\t * Channels that aren't required for HDR processing might come through for\n+\t\t * various reasons, such as when HDR starts up, or even because the cadence\n+\t\t * demands some frames that you need for other purposes (e.g. for preview).\n+\t\t * We'll leave the channel name empty in these cases.\n+\t\t */\n+\t\tauto it = currentConfig_->channelMap.find(agcChannel);\n+\t\tif (it != currentConfig_->channelMap.end())\n+\t\t\thdrStatus.channel = it->second;\n+\t}\n+\n+\timageMetadata->set(\"hdr.status\", hdrStatus);\n+}\n+\n+/* Register algorithm with the system. */\n+static Algorithm *create(Controller *controller)\n+{\n+\treturn (Algorithm *)new Hdr(controller);\n+}\n+static RegisterAlgorithm reg(NAME, &create);\ndiff --git a/src/ipa/rpi/controller/rpi/hdr.h b/src/ipa/rpi/controller/rpi/hdr.h\nnew file mode 100644\nindex 00000000..7419ad64\n--- /dev/null\n+++ b/src/ipa/rpi/controller/rpi/hdr.h\n@@ -0,0 +1,44 @@\n+/* SPDX-License-Identifier: BSD-2-Clause */\n+/*\n+ * Copyright (C) 2023, Raspberry Pi Ltd\n+ *\n+ * hdr.h - HDR control algorithm\n+ */\n+#pragma once\n+\n+#include <map>\n+#include <string>\n+#include <vector>\n+\n+#include \"../hdr_algorithm.h\"\n+#include \"../hdr_status.h\"\n+\n+/* This is our implementation of an HDR algorithm. */\n+\n+namespace RPiController {\n+\n+struct HdrConfig {\n+\tstd::string name;\n+\tstd::vector<unsigned int> cadence;\n+\tstd::map<unsigned int, std::string> channelMap;\n+\n+\tvoid read(const libcamera::YamlObject ¶ms, const std::string &name);\n+};\n+\n+class Hdr : public HdrAlgorithm\n+{\n+public:\n+\tHdr(Controller *controller);\n+\tchar const *name() const override;\n+\tvoid switchMode(CameraMode const &cameraMode, Metadata *metadata) override;\n+\tint read(const libcamera::YamlObject ¶ms) override;\n+\tvoid process(StatisticsPtr &stats, Metadata *imageMetadata) override;\n+\tint setMode(std::string const &mode) override;\n+\tstd::vector<unsigned int> getChannels() const override;\n+\n+private:\n+\tstd::map<std::string, HdrConfig> config_;\n+\tconst HdrConfig *currentConfig_;\n+};\n+\n+} /* namespace RPiController */\n", "prefixes": [ "libcamera-devel", "v3", "1/2" ] }