Show a patch.

GET /api/1.1/patches/16614/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 16614,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/16614/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/16614/",
    "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": "<20220713092159.9014-5-naush@raspberrypi.com>",
    "date": "2022-07-13T09:21:55",
    "name": "[libcamera-devel,v4,4/8] ipa: raspberrypi: Use YamlParser to replace dependency on boost",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "ec7a9c7020d3701cf39ccc05c9471604e9b3c060",
    "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/16614/mbox/",
    "series": [
        {
            "id": 3277,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3277/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3277",
            "date": "2022-07-13T09:21:51",
            "name": "Replace boost JSON parser with libyaml in Raspberry Pi IPA",
            "version": 4,
            "mbox": "https://patchwork.libcamera.org/series/3277/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/16614/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/16614/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 41EEBBD1F1\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 13 Jul 2022 09:22:24 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D643C6331E;\n\tWed, 13 Jul 2022 11:22:23 +0200 (CEST)",
            "from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com\n\t[IPv6:2a00:1450:4864:20::42e])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 056E763313\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 13 Jul 2022 11:22:19 +0200 (CEST)",
            "by mail-wr1-x42e.google.com with SMTP id d16so14588119wrv.10\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 13 Jul 2022 02:22:19 -0700 (PDT)",
            "from naush-laptop.localdomain ([93.93.133.154])\n\tby smtp.gmail.com with ESMTPSA id\n\tbd20-20020a05600c1f1400b0039747cf8354sm1514778wmb.39.2022.07.13.02.22.16\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 13 Jul 2022 02:22:16 -0700 (PDT)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1657704144;\n\tbh=IGeqx7irmBWlzrB0JPbTF+pCDMfRvgF3tn9JqoDNPnw=;\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=CisXgNbdGTSrQvaokIVNMiOOdSMB1DfyjNqXK/eXY6ndPhaXt+608VQy6FpwT7vE2\n\tlh3k0AufwqsasAy4f1zZQZqktu+nsXqu4HyevSKajTznWC1NsnWXe85eOxqNG2M45p\n\tC6djTr7wxRahS2bzR3sOvgZGB7EI3Mi9WY9xCoHMjVW/mrVKAf/GKNkkuTxtIyOqzO\n\tnDNrm28Jk/6oxAr1ddS95n4wDGjuyfycLt3TCZC8zpdJ84LSEuHAJmhY1swnPRsFKN\n\t4HKkyD5vW+G+YEFKDh+idYIdkdQx8rgVLSmfahY7IG/f0zVbokwy5430X2cXBoYHfI\n\tQaLDscZ64NaLg==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:mime-version:content-transfer-encoding;\n\tbh=Z20aVse7bxDwyA/p0bICBj4otiFy0z8WIkHY9d8uZtA=;\n\tb=SMlNi07gQT5MToFm6PG235eKMgJbg2JxnY/LxJpySoMiA+SpZjh3puogv3Fq2GAfPS\n\tdOpxjduhDdzQKv6bZTNHn52tPlWvhgR1MMinIGb9XJVCpH6+beUzdELG/EnoJ5cZvJcV\n\tEQ0RTry2AAgflzLzzDHCXmkBjuCN2nShDlC/ERlYDFRrltyL82/O73GSVYUvNLTxsoQ4\n\tVf+tvPVUNpT5zneKFnrzmSLJ9NO0agILMlZsbViUZ3/HpokO2KC/5aWJvuBTV9NDb5uC\n\tmb52pQ3ZCg9R6e9anT6eBZzfqszIO20qlzivkQZJC+u0NtB1yFK/ZrtnfVRizlzLVvby\n\tjdFw=="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"SMlNi07g\"; dkim-atps=neutral",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=Z20aVse7bxDwyA/p0bICBj4otiFy0z8WIkHY9d8uZtA=;\n\tb=EW9oErQkIz+qAkgEhRNZYxaN3E3+MDeHiciRSzIP+9obcI7bvVw2ghN5BxnM6ZPonK\n\twFF+sN18JrI4vep2PlHnyQSlRHjt7DZaf63v+z6cPiBNUuBTMtaa7kSeDB84BtxJnPe0\n\tUYANh5Vvbf3ax2c2UXo/NuWM63m65wmlZkzceEfcjnOv9OwCSKAhq3CkkMAAo7fUyhje\n\tL/Iu4tilcYYTDjnJtrMPRfa8RpUA4a3M37wST9zqTdv0sChcROvXpLXde6UnBeEp1a+H\n\t5GQThPCDPF5vDS2j8uhZhtlFo79CkqOdutHX65iCjPU7khwVaMuo9Xhun07OZm2MI87Q\n\t8YiA==",
        "X-Gm-Message-State": "AJIora8BOiF+kB1LIX1VH3zOMs4DKSUjztqaYTQ1+Ug+skArtIBZwe1C\n\thXXLkLFd75RK0FAX5o4vuFFjFWdmU2pmog==",
        "X-Google-Smtp-Source": "AGRyM1uX9G0A1o9aRKHLM0BNKucUawF3XFhnfSZ0wS9Sm4hOdvjMTsim+FOJ0KNXAmBLrRO34cOdJw==",
        "X-Received": "by 2002:a5d:4d4e:0:b0:21d:7a79:e04c with SMTP id\n\ta14-20020a5d4d4e000000b0021d7a79e04cmr2334271wru.519.1657704137657; \n\tWed, 13 Jul 2022 02:22:17 -0700 (PDT)",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 13 Jul 2022 10:21:55 +0100",
        "Message-Id": "<20220713092159.9014-5-naush@raspberrypi.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220713092159.9014-1-naush@raspberrypi.com>",
        "References": "<20220713092159.9014-1-naush@raspberrypi.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v4 4/8] ipa: raspberrypi: Use YamlParser\n\tto replace dependency on boost",
        "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": "From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nThe Raspberry Pi IPA module depends on boost only to parse the JSON\ntuning data files. As libcamera depends on libyaml, use the YamlParser\nclass to parse those files and drop the dependency on boost.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n README.rst                                    |  6 --\n src/ipa/raspberrypi/controller/algorithm.cpp  |  2 +-\n src/ipa/raspberrypi/controller/algorithm.hpp  |  6 +-\n src/ipa/raspberrypi/controller/controller.cpp | 27 ++++--\n src/ipa/raspberrypi/controller/pwl.cpp        | 12 ++-\n src/ipa/raspberrypi/controller/pwl.hpp        |  5 +-\n src/ipa/raspberrypi/controller/rpi/agc.cpp    | 94 +++++++++----------\n src/ipa/raspberrypi/controller/rpi/agc.hpp    | 10 +-\n src/ipa/raspberrypi/controller/rpi/alsc.cpp   | 94 +++++++++----------\n src/ipa/raspberrypi/controller/rpi/alsc.hpp   |  2 +-\n src/ipa/raspberrypi/controller/rpi/awb.cpp    | 89 +++++++++---------\n src/ipa/raspberrypi/controller/rpi/awb.hpp    |  8 +-\n .../controller/rpi/black_level.cpp            | 12 +--\n .../controller/rpi/black_level.hpp            |  2 +-\n src/ipa/raspberrypi/controller/rpi/ccm.cpp    | 28 +++---\n src/ipa/raspberrypi/controller/rpi/ccm.hpp    |  4 +-\n .../raspberrypi/controller/rpi/contrast.cpp   | 18 ++--\n .../raspberrypi/controller/rpi/contrast.hpp   |  2 +-\n src/ipa/raspberrypi/controller/rpi/dpc.cpp    |  4 +-\n src/ipa/raspberrypi/controller/rpi/dpc.hpp    |  2 +-\n src/ipa/raspberrypi/controller/rpi/geq.cpp    | 10 +-\n src/ipa/raspberrypi/controller/rpi/geq.hpp    |  2 +-\n src/ipa/raspberrypi/controller/rpi/lux.cpp    | 12 +--\n src/ipa/raspberrypi/controller/rpi/lux.hpp    |  2 +-\n src/ipa/raspberrypi/controller/rpi/noise.cpp  |  6 +-\n src/ipa/raspberrypi/controller/rpi/noise.hpp  |  2 +-\n src/ipa/raspberrypi/controller/rpi/sdn.cpp    |  6 +-\n src/ipa/raspberrypi/controller/rpi/sdn.hpp    |  2 +-\n .../raspberrypi/controller/rpi/sharpen.cpp    |  8 +-\n .../raspberrypi/controller/rpi/sharpen.hpp    |  2 +-\n src/ipa/raspberrypi/meson.build               |  1 -\n src/ipa/raspberrypi/raspberrypi.cpp           |  1 +\n 32 files changed, 241 insertions(+), 240 deletions(-)",
    "diff": "diff --git a/README.rst b/README.rst\nindex b9e72d81b90c..3d4e48ddc8f6 100644\n--- a/README.rst\n+++ b/README.rst\n@@ -71,12 +71,6 @@ for improved debugging: [optional]\n         information, and libunwind is not needed if both libdw and the glibc\n         backtrace() function are available.\n \n-for the Raspberry Pi IPA: [optional]\n-        libboost-dev\n-\n-        Support for Raspberry Pi can be disabled through the meson\n-         'pipelines' option to avoid this dependency.\n-\n for device hotplug enumeration: [optional]\n         libudev-dev\n \ndiff --git a/src/ipa/raspberrypi/controller/algorithm.cpp b/src/ipa/raspberrypi/controller/algorithm.cpp\nindex 43ad0a2be222..4fd36fc1be5b 100644\n--- a/src/ipa/raspberrypi/controller/algorithm.cpp\n+++ b/src/ipa/raspberrypi/controller/algorithm.cpp\n@@ -9,7 +9,7 @@\n \n using namespace RPiController;\n \n-void Algorithm::Read([[maybe_unused]] boost::property_tree::ptree const &params)\n+void Algorithm::Read([[maybe_unused]] const libcamera::YamlObject &params)\n {\n }\n \ndiff --git a/src/ipa/raspberrypi/controller/algorithm.hpp b/src/ipa/raspberrypi/controller/algorithm.hpp\nindex 5123c87bab34..87bfca8d2045 100644\n--- a/src/ipa/raspberrypi/controller/algorithm.hpp\n+++ b/src/ipa/raspberrypi/controller/algorithm.hpp\n@@ -13,9 +13,9 @@\n #include <memory>\n #include <map>\n \n-#include \"controller.hpp\"\n+#include \"libcamera/internal/yaml_parser.h\"\n \n-#include <boost/property_tree/ptree.hpp>\n+#include \"controller.hpp\"\n \n namespace RPiController {\n \n@@ -33,7 +33,7 @@ public:\n \tvirtual bool IsPaused() const { return paused_; }\n \tvirtual void Pause() { paused_ = true; }\n \tvirtual void Resume() { paused_ = false; }\n-\tvirtual void Read(boost::property_tree::ptree const &params);\n+\tvirtual void Read(const libcamera::YamlObject &params);\n \tvirtual void Initialise();\n \tvirtual void SwitchMode(CameraMode const &camera_mode, Metadata *metadata);\n \tvirtual void Prepare(Metadata *image_metadata);\ndiff --git a/src/ipa/raspberrypi/controller/controller.cpp b/src/ipa/raspberrypi/controller/controller.cpp\nindex d3433ad2e7e8..67d650ef0c1b 100644\n--- a/src/ipa/raspberrypi/controller/controller.cpp\n+++ b/src/ipa/raspberrypi/controller/controller.cpp\n@@ -5,14 +5,16 @@\n  * controller.cpp - ISP controller\n  */\n \n+#include <assert.h>\n+\n+#include <libcamera/base/file.h>\n #include <libcamera/base/log.h>\n \n+#include \"libcamera/internal/yaml_parser.h\"\n+\n #include \"algorithm.hpp\"\n #include \"controller.hpp\"\n \n-#include <boost/property_tree/json_parser.hpp>\n-#include <boost/property_tree/ptree.hpp>\n-\n using namespace RPiController;\n using namespace libcamera;\n \n@@ -32,16 +34,23 @@ Controller::~Controller() {}\n \n void Controller::Read(char const *filename)\n {\n-\tboost::property_tree::ptree root;\n-\tboost::property_tree::read_json(filename, root);\n-\tfor (auto const &key_and_value : root) {\n-\t\tAlgorithm *algo = CreateAlgorithm(key_and_value.first.c_str());\n+\tFile file(filename);\n+\tif (!file.open(File::OpenModeFlag::ReadOnly)) {\n+\t\tLOG(RPiController, Warning)\n+\t\t\t<< \"Failed to open tuning file '\" << filename << \"'\";\n+\t\treturn;\n+\t}\n+\n+\tstd::unique_ptr<YamlObject> root = YamlParser::parse(file);\n+\n+\tfor (auto const &[key, value] : root->asDict()) {\n+\t\tAlgorithm *algo = CreateAlgorithm(key.c_str());\n \t\tif (algo) {\n-\t\t\talgo->Read(key_and_value.second);\n+\t\t\talgo->Read(value);\n \t\t\talgorithms_.push_back(AlgorithmPtr(algo));\n \t\t} else\n \t\t\tLOG(RPiController, Warning)\n-\t\t\t\t<< \"No algorithm found for \\\"\" << key_and_value.first << \"\\\"\";\n+\t\t\t\t<< \"No algorithm found for \\\"\" << key << \"\\\"\";\n \t}\n }\n \ndiff --git a/src/ipa/raspberrypi/controller/pwl.cpp b/src/ipa/raspberrypi/controller/pwl.cpp\nindex 130c820b559f..9c7bc94dd484 100644\n--- a/src/ipa/raspberrypi/controller/pwl.cpp\n+++ b/src/ipa/raspberrypi/controller/pwl.cpp\n@@ -12,13 +12,15 @@\n \n using namespace RPiController;\n \n-void Pwl::Read(boost::property_tree::ptree const &params)\n+void Pwl::Read(const libcamera::YamlObject &params)\n {\n-\tfor (auto it = params.begin(); it != params.end(); it++) {\n-\t\tdouble x = it->second.get_value<double>();\n-\t\tassert(it == params.begin() || x > points_.back().x);\n+\tconst auto &list = params.asList();\n+\n+\tfor (auto it = list.begin(); it != list.end(); it++) {\n+\t\tdouble x = it->get<double>(0.0);\n+\t\tassert(it == list.begin() || x > points_.back().x);\n \t\tit++;\n-\t\tdouble y = it->second.get_value<double>();\n+\t\tdouble y = it->get<double>(0.0);\n \t\tpoints_.push_back(Point(x, y));\n \t}\n \tassert(points_.size() >= 2);\ndiff --git a/src/ipa/raspberrypi/controller/pwl.hpp b/src/ipa/raspberrypi/controller/pwl.hpp\nindex 484672f64095..70df4ba0daea 100644\n--- a/src/ipa/raspberrypi/controller/pwl.hpp\n+++ b/src/ipa/raspberrypi/controller/pwl.hpp\n@@ -6,10 +6,11 @@\n  */\n #pragma once\n \n+#include <functional>\n #include <math.h>\n #include <vector>\n \n-#include <boost/property_tree/ptree.hpp>\n+#include \"libcamera/internal/yaml_parser.h\"\n \n namespace RPiController {\n \n@@ -55,7 +56,7 @@ public:\n \t};\n \tPwl() {}\n \tPwl(std::vector<Point> const &points) : points_(points) {}\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n \tvoid Append(double x, double y, const double eps = 1e-6);\n \tvoid Prepend(double x, double y, const double eps = 1e-6);\n \tInterval Domain() const;\ndiff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp\nindex f6a9cb0a2cd8..c82f29600be7 100644\n--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp\n@@ -30,13 +30,13 @@ LOG_DEFINE_CATEGORY(RPiAgc)\n \n #define PIPELINE_BITS 13 // seems to be a 13-bit pipeline\n \n-void AgcMeteringMode::Read(boost::property_tree::ptree const &params)\n+void AgcMeteringMode::Read(const libcamera::YamlObject &params)\n {\n \tint num = 0;\n-\tfor (auto &p : params.get_child(\"weights\")) {\n+\tfor (const auto &p : params[\"weights\"].asList()) {\n \t\tif (num == AGC_STATS_SIZE)\n \t\t\tthrow std::runtime_error(\"AgcConfig: too many weights\");\n-\t\tweights[num++] = p.second.get_value<double>();\n+\t\tweights[num++] = p.get<double>(0.0);\n \t}\n \tif (num != AGC_STATS_SIZE)\n \t\tthrow std::runtime_error(\"AgcConfig: insufficient weights\");\n@@ -44,39 +44,39 @@ void AgcMeteringMode::Read(boost::property_tree::ptree const &params)\n \n static std::string\n read_metering_modes(std::map<std::string, AgcMeteringMode> &metering_modes,\n-\t\t    boost::property_tree::ptree const &params)\n+\t\t    const libcamera::YamlObject &params)\n {\n \tstd::string first;\n-\tfor (auto &p : params) {\n+\tfor (const auto &[key, value] : params.asDict()) {\n \t\tAgcMeteringMode metering_mode;\n-\t\tmetering_mode.Read(p.second);\n-\t\tmetering_modes[p.first] = std::move(metering_mode);\n+\t\tmetering_mode.Read(value);\n+\t\tmetering_modes[key] = std::move(metering_mode);\n \t\tif (first.empty())\n-\t\t\tfirst = p.first;\n+\t\t\tfirst = key;\n \t}\n \treturn first;\n }\n \n static int read_list(std::vector<double> &list,\n-\t\t     boost::property_tree::ptree const &params)\n+\t\t     const libcamera::YamlObject &params)\n {\n-\tfor (auto &p : params)\n-\t\tlist.push_back(p.second.get_value<double>());\n+\tfor (const auto &p : params.asList())\n+\t\tlist.push_back(p.get<double>(0.0));\n \treturn list.size();\n }\n \n static int read_list(std::vector<Duration> &list,\n-\t\t     boost::property_tree::ptree const &params)\n+\t\t     const libcamera::YamlObject &params)\n {\n-\tfor (auto &p : params)\n-\t\tlist.push_back(p.second.get_value<double>() * 1us);\n+\tfor (const auto &p : params.asList())\n+\t\tlist.push_back(p.get<double>(0.0) * 1us);\n \treturn list.size();\n }\n \n-void AgcExposureMode::Read(boost::property_tree::ptree const &params)\n+void AgcExposureMode::Read(const libcamera::YamlObject &params)\n {\n-\tint num_shutters = read_list(shutter, params.get_child(\"shutter\"));\n-\tint num_ags = read_list(gain, params.get_child(\"gain\"));\n+\tint num_shutters = read_list(shutter, params[\"shutter\"]);\n+\tint num_ags = read_list(gain, params[\"gain\"]);\n \tif (num_shutters < 2 || num_ags < 2)\n \t\tthrow std::runtime_error(\n \t\t\t\"AgcConfig: must have at least two entries in exposure profile\");\n@@ -87,40 +87,40 @@ void AgcExposureMode::Read(boost::property_tree::ptree const &params)\n \n static std::string\n read_exposure_modes(std::map<std::string, AgcExposureMode> &exposure_modes,\n-\t\t    boost::property_tree::ptree const &params)\n+\t\t    const libcamera::YamlObject &params)\n {\n \tstd::string first;\n-\tfor (auto &p : params) {\n+\tfor (const auto &[key, value] : params.asDict()) {\n \t\tAgcExposureMode exposure_mode;\n-\t\texposure_mode.Read(p.second);\n-\t\texposure_modes[p.first] = std::move(exposure_mode);\n+\t\texposure_mode.Read(value);\n+\t\texposure_modes[key] = std::move(exposure_mode);\n \t\tif (first.empty())\n-\t\t\tfirst = p.first;\n+\t\t\tfirst = key;\n \t}\n \treturn first;\n }\n \n-void AgcConstraint::Read(boost::property_tree::ptree const &params)\n+void AgcConstraint::Read(const libcamera::YamlObject &params)\n {\n-\tstd::string bound_string = params.get<std::string>(\"bound\", \"\");\n+\tstd::string bound_string = params[\"bound\"].get<std::string>(\"\");\n \ttransform(bound_string.begin(), bound_string.end(),\n \t\t  bound_string.begin(), ::toupper);\n \tif (bound_string != \"UPPER\" && bound_string != \"LOWER\")\n \t\tthrow std::runtime_error(\n \t\t\t\"AGC constraint type should be UPPER or LOWER\");\n \tbound = bound_string == \"UPPER\" ? Bound::UPPER : Bound::LOWER;\n-\tq_lo = params.get<double>(\"q_lo\");\n-\tq_hi = params.get<double>(\"q_hi\");\n-\tY_target.Read(params.get_child(\"y_target\"));\n+\tq_lo = params[\"q_lo\"].get<double>(0.0);\n+\tq_hi = params[\"q_hi\"].get<double>(0.0);\n+\tY_target.Read(params[\"y_target\"]);\n }\n \n static AgcConstraintMode\n-read_constraint_mode(boost::property_tree::ptree const &params)\n+read_constraint_mode(const libcamera::YamlObject &params)\n {\n \tAgcConstraintMode mode;\n-\tfor (auto &p : params) {\n+\tfor (const auto &p : params.asList()) {\n \t\tAgcConstraint constraint;\n-\t\tconstraint.Read(p.second);\n+\t\tconstraint.Read(p);\n \t\tmode.push_back(std::move(constraint));\n \t}\n \treturn mode;\n@@ -128,36 +128,36 @@ read_constraint_mode(boost::property_tree::ptree const &params)\n \n static std::string read_constraint_modes(\n \tstd::map<std::string, AgcConstraintMode> &constraint_modes,\n-\tboost::property_tree::ptree const &params)\n+\tconst libcamera::YamlObject &params)\n {\n \tstd::string first;\n-\tfor (auto &p : params) {\n-\t\tconstraint_modes[p.first] = read_constraint_mode(p.second);\n+\tfor (const auto &[key, value] : params.asDict()) {\n+\t\tconstraint_modes[key] = read_constraint_mode(value);\n \t\tif (first.empty())\n-\t\t\tfirst = p.first;\n+\t\t\tfirst = key;\n \t}\n \treturn first;\n }\n \n-void AgcConfig::Read(boost::property_tree::ptree const &params)\n+void AgcConfig::Read(const libcamera::YamlObject &params)\n {\n \tLOG(RPiAgc, Debug) << \"AgcConfig\";\n \tdefault_metering_mode = read_metering_modes(\n-\t\tmetering_modes, params.get_child(\"metering_modes\"));\n+\t\tmetering_modes, params[\"metering_modes\"]);\n \tdefault_exposure_mode = read_exposure_modes(\n-\t\texposure_modes, params.get_child(\"exposure_modes\"));\n+\t\texposure_modes, params[\"exposure_modes\"]);\n \tdefault_constraint_mode = read_constraint_modes(\n-\t\tconstraint_modes, params.get_child(\"constraint_modes\"));\n-\tY_target.Read(params.get_child(\"y_target\"));\n-\tspeed = params.get<double>(\"speed\", 0.2);\n-\tstartup_frames = params.get<uint16_t>(\"startup_frames\", 10);\n-\tconvergence_frames = params.get<unsigned int>(\"convergence_frames\", 6);\n+\t\tconstraint_modes, params[\"constraint_modes\"]);\n+\tY_target.Read(params[\"y_target\"]);\n+\tspeed = params[\"speed\"].get<double>(0.2);\n+\tstartup_frames = params[\"startup_frames\"].get<uint16_t>(10);\n+\tconvergence_frames = params[\"convergence_frames\"].get<unsigned int>(6);\n \tfast_reduce_threshold =\n-\t\tparams.get<double>(\"fast_reduce_threshold\", 0.4);\n-\tbase_ev = params.get<double>(\"base_ev\", 1.0);\n+\t\tparams[\"fast_reduce_threshold\"].get<double>(0.4);\n+\tbase_ev = params[\"base_ev\"].get<double>(1.0);\n \t// Start with quite a low value as ramping up is easier than ramping down.\n-\tdefault_exposure_time = params.get<double>(\"default_exposure_time\", 1000) * 1us;\n-\tdefault_analogue_gain = params.get<double>(\"default_analogue_gain\", 1.0);\n+\tdefault_exposure_time = params[\"default_exposure_time\"].get<double>(1000) * 1us;\n+\tdefault_analogue_gain = params[\"default_analogue_gain\"].get<double>(1.0);\n }\n \n Agc::ExposureValues::ExposureValues()\n@@ -186,7 +186,7 @@ char const *Agc::Name() const\n \treturn NAME;\n }\n \n-void Agc::Read(boost::property_tree::ptree const &params)\n+void Agc::Read(const libcamera::YamlObject &params)\n {\n \tLOG(RPiAgc, Debug) << \"Agc\";\n \tconfig_.Read(params);\ndiff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp\nindex c100d3128c90..7794ba744efc 100644\n--- a/src/ipa/raspberrypi/controller/rpi/agc.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp\n@@ -26,13 +26,13 @@ namespace RPiController {\n \n struct AgcMeteringMode {\n \tdouble weights[AGC_STATS_SIZE];\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n };\n \n struct AgcExposureMode {\n \tstd::vector<libcamera::utils::Duration> shutter;\n \tstd::vector<double> gain;\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n };\n \n struct AgcConstraint {\n@@ -41,13 +41,13 @@ struct AgcConstraint {\n \tdouble q_lo;\n \tdouble q_hi;\n \tPwl Y_target;\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n };\n \n typedef std::vector<AgcConstraint> AgcConstraintMode;\n \n struct AgcConfig {\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n \tstd::map<std::string, AgcMeteringMode> metering_modes;\n \tstd::map<std::string, AgcExposureMode> exposure_modes;\n \tstd::map<std::string, AgcConstraintMode> constraint_modes;\n@@ -72,7 +72,7 @@ class Agc : public AgcAlgorithm\n public:\n \tAgc(Controller *controller);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \t// AGC handles \"pausing\" for itself.\n \tbool IsPaused() const override;\n \tvoid Pause() override;\ndiff --git a/src/ipa/raspberrypi/controller/rpi/alsc.cpp b/src/ipa/raspberrypi/controller/rpi/alsc.cpp\nindex e575c14a92db..b38b037c7713 100644\n--- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp\n@@ -5,6 +5,7 @@\n  * alsc.cpp - ALSC (auto lens shading correction) control algorithm\n  */\n \n+#include <functional>\n #include <math.h>\n #include <numeric>\n \n@@ -50,12 +51,12 @@ char const *Alsc::Name() const\n \treturn NAME;\n }\n \n-static void generate_lut(double *lut, boost::property_tree::ptree const &params)\n+static void generate_lut(double *lut, const libcamera::YamlObject &params)\n {\n-\tdouble cstrength = params.get<double>(\"corner_strength\", 2.0);\n+\tdouble cstrength = params[\"corner_strength\"].get<double>(2.0);\n \tif (cstrength <= 1.0)\n \t\tthrow std::runtime_error(\"Alsc: corner_strength must be > 1.0\");\n-\tdouble asymmetry = params.get<double>(\"asymmetry\", 1.0);\n+\tdouble asymmetry = params[\"asymmetry\"].get<double>(1.0);\n \tif (asymmetry < 0)\n \t\tthrow std::runtime_error(\"Alsc: asymmetry must be >= 0\");\n \tdouble f1 = cstrength - 1, f2 = 1 + sqrt(cstrength);\n@@ -73,50 +74,43 @@ static void generate_lut(double *lut, boost::property_tree::ptree const &params)\n \t}\n }\n \n-static void read_lut(double *lut, boost::property_tree::ptree const &params)\n+static void read_lut(double *lut, const libcamera::YamlObject &params)\n {\n+\tif (params.size() != XY)\n+\t\tthrow std::runtime_error(\n+\t\t\t\"Alsc: invalid number of entries in LSC table\");\n+\n \tint num = 0;\n-\tconst int max_num = XY;\n-\tfor (auto &p : params) {\n-\t\tif (num == max_num)\n-\t\t\tthrow std::runtime_error(\n-\t\t\t\t\"Alsc: too many entries in LSC table\");\n-\t\tlut[num++] = p.second.get_value<double>();\n-\t}\n-\tif (num < max_num)\n-\t\tthrow std::runtime_error(\"Alsc: too few entries in LSC table\");\n+\tfor (const auto &p : params.asList())\n+\t\tlut[num++] = p.get<double>(0.0);\n }\n \n static void read_calibrations(std::vector<AlscCalibration> &calibrations,\n-\t\t\t      boost::property_tree::ptree const &params,\n+\t\t\t      const libcamera::YamlObject &params,\n \t\t\t      std::string const &name)\n {\n-\tif (params.get_child_optional(name)) {\n+\tif (params.contains(name)) {\n \t\tdouble last_ct = 0;\n-\t\tfor (auto &p : params.get_child(name)) {\n-\t\t\tdouble ct = p.second.get<double>(\"ct\");\n+\t\tfor (const auto &p : params[name].asList()) {\n+\t\t\tdouble ct = p[\"ct\"].get<double>(0.0);\n \t\t\tif (ct <= last_ct)\n \t\t\t\tthrow std::runtime_error(\n \t\t\t\t\t\"Alsc: entries in \" + name +\n \t\t\t\t\t\" must be in increasing ct order\");\n \t\t\tAlscCalibration calibration;\n \t\t\tcalibration.ct = last_ct = ct;\n-\t\t\tboost::property_tree::ptree const &table =\n-\t\t\t\tp.second.get_child(\"table\");\n-\t\t\tint num = 0;\n-\t\t\tfor (auto it = table.begin(); it != table.end(); it++) {\n-\t\t\t\tif (num == XY)\n-\t\t\t\t\tthrow std::runtime_error(\n-\t\t\t\t\t\t\"Alsc: too many values for ct \" +\n-\t\t\t\t\t\tstd::to_string(ct) + \" in \" +\n-\t\t\t\t\t\tname);\n-\t\t\t\tcalibration.table[num++] =\n-\t\t\t\t\tit->second.get_value<double>();\n-\t\t\t}\n-\t\t\tif (num != XY)\n+\n+\t\t\tconst libcamera::YamlObject &table = p[\"table\"];\n+\t\t\tif (table.size() != XY)\n \t\t\t\tthrow std::runtime_error(\n-\t\t\t\t\t\"Alsc: too few values for ct \" +\n-\t\t\t\t\tstd::to_string(ct) + \" in \" + name);\n+\t\t\t\t\t\"Alsc: incorrect number of values for ct \" +\n+\t\t\t\t\tstd::to_string(ct) + \" in \" +\n+\t\t\t\t\tname);\n+\n+\t\t\tint num = 0;\n+\t\t\tfor (const auto &value : table.asList())\n+\t\t\t\tcalibration.table[num++] = value.get<double>(0.0);\n+\n \t\t\tcalibrations.push_back(calibration);\n \t\t\tLOG(RPiAlsc, Debug)\n \t\t\t\t<< \"Read \" << name << \" calibration for ct \" << ct;\n@@ -124,35 +118,35 @@ static void read_calibrations(std::vector<AlscCalibration> &calibrations,\n \t}\n }\n \n-void Alsc::Read(boost::property_tree::ptree const &params)\n+void Alsc::Read(const libcamera::YamlObject &params)\n {\n-\tconfig_.frame_period = params.get<uint16_t>(\"frame_period\", 12);\n-\tconfig_.startup_frames = params.get<uint16_t>(\"startup_frames\", 10);\n-\tconfig_.speed = params.get<double>(\"speed\", 0.05);\n-\tdouble sigma = params.get<double>(\"sigma\", 0.01);\n-\tconfig_.sigma_Cr = params.get<double>(\"sigma_Cr\", sigma);\n-\tconfig_.sigma_Cb = params.get<double>(\"sigma_Cb\", sigma);\n-\tconfig_.min_count = params.get<double>(\"min_count\", 10.0);\n-\tconfig_.min_G = params.get<uint16_t>(\"min_G\", 50);\n-\tconfig_.omega = params.get<double>(\"omega\", 1.3);\n-\tconfig_.n_iter = params.get<uint32_t>(\"n_iter\", X + Y);\n+\tconfig_.frame_period = params[\"frame_period\"].get<uint16_t>(12);\n+\tconfig_.startup_frames = params[\"startup_frames\"].get<uint16_t>(10);\n+\tconfig_.speed = params[\"speed\"].get<double>(0.05);\n+\tdouble sigma = params[\"sigma\"].get<double>(0.01);\n+\tconfig_.sigma_Cr = params[\"sigma_Cr\"].get<double>(sigma);\n+\tconfig_.sigma_Cb = params[\"sigma_Cb\"].get<double>(sigma);\n+\tconfig_.min_count = params[\"min_count\"].get<double>(10.0);\n+\tconfig_.min_G = params[\"min_G\"].get<uint16_t>(50);\n+\tconfig_.omega = params[\"omega\"].get<double>(1.3);\n+\tconfig_.n_iter = params[\"n_iter\"].get<uint32_t>(X + Y);\n \tconfig_.luminance_strength =\n-\t\tparams.get<double>(\"luminance_strength\", 1.0);\n+\t\tparams[\"luminance_strength\"].get<double>(1.0);\n \tfor (int i = 0; i < XY; i++)\n \t\tconfig_.luminance_lut[i] = 1.0;\n-\tif (params.get_child_optional(\"corner_strength\"))\n+\tif (params.contains(\"corner_strength\"))\n \t\tgenerate_lut(config_.luminance_lut, params);\n-\telse if (params.get_child_optional(\"luminance_lut\"))\n+\telse if (params.contains(\"luminance_lut\"))\n \t\tread_lut(config_.luminance_lut,\n-\t\t\t params.get_child(\"luminance_lut\"));\n+\t\t\t params[\"luminance_lut\"]);\n \telse\n \t\tLOG(RPiAlsc, Warning)\n \t\t\t<< \"no luminance table - assume unity everywhere\";\n \tread_calibrations(config_.calibrations_Cr, params, \"calibrations_Cr\");\n \tread_calibrations(config_.calibrations_Cb, params, \"calibrations_Cb\");\n-\tconfig_.default_ct = params.get<double>(\"default_ct\", 4500.0);\n-\tconfig_.threshold = params.get<double>(\"threshold\", 1e-3);\n-\tconfig_.lambda_bound = params.get<double>(\"lambda_bound\", 0.05);\n+\tconfig_.default_ct = params[\"default_ct\"].get<double>(4500.0);\n+\tconfig_.threshold = params[\"threshold\"].get<double>(1e-3);\n+\tconfig_.lambda_bound = params[\"lambda_bound\"].get<double>(0.05);\n }\n \n static double get_ct(Metadata *metadata, double default_ct);\ndiff --git a/src/ipa/raspberrypi/controller/rpi/alsc.hpp b/src/ipa/raspberrypi/controller/rpi/alsc.hpp\nindex d1dbe0d1d22d..9d28c1b49a6d 100644\n--- a/src/ipa/raspberrypi/controller/rpi/alsc.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/alsc.hpp\n@@ -52,7 +52,7 @@ public:\n \tchar const *Name() const override;\n \tvoid Initialise() override;\n \tvoid SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \tvoid Process(StatisticsPtr &stats, Metadata *image_metadata) override;\n \ndiff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp\nindex d4c934473832..1c40bf878cd3 100644\n--- a/src/ipa/raspberrypi/controller/rpi/awb.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/awb.cpp\n@@ -5,6 +5,8 @@\n  * awb.cpp - AWB control algorithm\n  */\n \n+#include <assert.h>\n+\n #include <libcamera/base/log.h>\n \n #include \"../lux_status.h\"\n@@ -24,33 +26,35 @@ LOG_DEFINE_CATEGORY(RPiAwb)\n // todo - the locking in this algorithm needs some tidying up as has been done\n // elsewhere (ALSC and AGC).\n \n-void AwbMode::Read(boost::property_tree::ptree const &params)\n+void AwbMode::Read(const libcamera::YamlObject &params)\n {\n-\tct_lo = params.get<double>(\"lo\");\n-\tct_hi = params.get<double>(\"hi\");\n+\tct_lo = params[\"lo\"].get<double>(0.0);\n+\tct_hi = params[\"hi\"].get<double>(0.0);\n }\n \n-void AwbPrior::Read(boost::property_tree::ptree const &params)\n+void AwbPrior::Read(const libcamera::YamlObject &params)\n {\n-\tlux = params.get<double>(\"lux\");\n-\tprior.Read(params.get_child(\"prior\"));\n+\tlux = params[\"lux\"].get<double>(0.0);\n+\tprior.Read(params[\"prior\"]);\n }\n \n static void read_ct_curve(Pwl &ct_r, Pwl &ct_b,\n-\t\t\t  boost::property_tree::ptree const &params)\n+\t\t\t  const libcamera::YamlObject &params)\n {\n+\tconst auto &list = params.asList();\n \tint num = 0;\n-\tfor (auto it = params.begin(); it != params.end(); it++) {\n-\t\tdouble ct = it->second.get_value<double>();\n-\t\tassert(it == params.begin() || ct != ct_r.Domain().end);\n-\t\tif (++it == params.end())\n+\n+\tfor (auto it = list.begin(); it != list.end(); it++) {\n+\t\tdouble ct = it->get<double>(0.0);\n+\t\tassert(it == list.begin() || ct != ct_r.Domain().end);\n+\t\tif (++it == list.end())\n \t\t\tthrow std::runtime_error(\n \t\t\t\t\"AwbConfig: incomplete CT curve entry\");\n-\t\tct_r.Append(ct, it->second.get_value<double>());\n-\t\tif (++it == params.end())\n+\t\tct_r.Append(ct, it->get<double>(0.0));\n+\t\tif (++it == list.end())\n \t\t\tthrow std::runtime_error(\n \t\t\t\t\"AwbConfig: incomplete CT curve entry\");\n-\t\tct_b.Append(ct, it->second.get_value<double>());\n+\t\tct_b.Append(ct, it->get<double>(0.0));\n \t\tnum++;\n \t}\n \tif (num < 2)\n@@ -58,19 +62,19 @@ static void read_ct_curve(Pwl &ct_r, Pwl &ct_b,\n \t\t\t\"AwbConfig: insufficient points in CT curve\");\n }\n \n-void AwbConfig::Read(boost::property_tree::ptree const &params)\n+void AwbConfig::Read(const libcamera::YamlObject &params)\n {\n-\tbayes = params.get<int>(\"bayes\", 1);\n-\tframe_period = params.get<uint16_t>(\"frame_period\", 10);\n-\tstartup_frames = params.get<uint16_t>(\"startup_frames\", 10);\n-\tconvergence_frames = params.get<unsigned int>(\"convergence_frames\", 3);\n-\tspeed = params.get<double>(\"speed\", 0.05);\n-\tif (params.get_child_optional(\"ct_curve\"))\n-\t\tread_ct_curve(ct_r, ct_b, params.get_child(\"ct_curve\"));\n-\tif (params.get_child_optional(\"priors\")) {\n-\t\tfor (auto &p : params.get_child(\"priors\")) {\n+\tbayes = params[\"bayes\"].get<int>(1);\n+\tframe_period = params[\"frame_period\"].get<uint16_t>(10);\n+\tstartup_frames = params[\"startup_frames\"].get<uint16_t>(10);\n+\tconvergence_frames = params[\"convergence_frames\"].get<unsigned int>(3);\n+\tspeed = params[\"speed\"].get<double>(0.05);\n+\tif (params.contains(\"ct_curve\"))\n+\t\tread_ct_curve(ct_r, ct_b, params[\"ct_curve\"]);\n+\tif (params.contains(\"priors\")) {\n+\t\tfor (const auto &p : params[\"priors\"].asList()) {\n \t\t\tAwbPrior prior;\n-\t\t\tprior.Read(p.second);\n+\t\t\tprior.Read(p);\n \t\t\tif (!priors.empty() && prior.lux <= priors.back().lux)\n \t\t\t\tthrow std::runtime_error(\n \t\t\t\t\t\"AwbConfig: Prior must be ordered in increasing lux value\");\n@@ -80,28 +84,28 @@ void AwbConfig::Read(boost::property_tree::ptree const &params)\n \t\t\tthrow std::runtime_error(\n \t\t\t\t\"AwbConfig: no AWB priors configured\");\n \t}\n-\tif (params.get_child_optional(\"modes\")) {\n-\t\tfor (auto &p : params.get_child(\"modes\")) {\n-\t\t\tmodes[p.first].Read(p.second);\n+\tif (params.contains(\"modes\")) {\n+\t\tfor (const auto &[key, value] : params[\"modes\"].asDict()) {\n+\t\t\tmodes[key].Read(value);\n \t\t\tif (default_mode == nullptr)\n-\t\t\t\tdefault_mode = &modes[p.first];\n+\t\t\t\tdefault_mode = &modes[key];\n \t\t}\n \t\tif (default_mode == nullptr)\n \t\t\tthrow std::runtime_error(\n \t\t\t\t\"AwbConfig: no AWB modes configured\");\n \t}\n-\tmin_pixels = params.get<double>(\"min_pixels\", 16.0);\n-\tmin_G = params.get<uint16_t>(\"min_G\", 32);\n-\tmin_regions = params.get<uint32_t>(\"min_regions\", 10);\n-\tdelta_limit = params.get<double>(\"delta_limit\", 0.2);\n-\tcoarse_step = params.get<double>(\"coarse_step\", 0.2);\n-\ttransverse_pos = params.get<double>(\"transverse_pos\", 0.01);\n-\ttransverse_neg = params.get<double>(\"transverse_neg\", 0.01);\n+\tmin_pixels = params[\"min_pixels\"].get<double>(16.0);\n+\tmin_G = params[\"min_G\"].get<uint16_t>(32);\n+\tmin_regions = params[\"min_regions\"].get<uint32_t>(10);\n+\tdelta_limit = params[\"delta_limit\"].get<double>(0.2);\n+\tcoarse_step = params[\"coarse_step\"].get<double>(0.2);\n+\ttransverse_pos = params[\"transverse_pos\"].get<double>(0.01);\n+\ttransverse_neg = params[\"transverse_neg\"].get<double>(0.01);\n \tif (transverse_pos <= 0 || transverse_neg <= 0)\n \t\tthrow std::runtime_error(\n \t\t\t\"AwbConfig: transverse_pos/neg must be > 0\");\n-\tsensitivity_r = params.get<double>(\"sensitivity_r\", 1.0);\n-\tsensitivity_b = params.get<double>(\"sensitivity_b\", 1.0);\n+\tsensitivity_r = params[\"sensitivity_r\"].get<double>(1.0);\n+\tsensitivity_b = params[\"sensitivity_b\"].get<double>(1.0);\n \tif (bayes) {\n \t\tif (ct_r.Empty() || ct_b.Empty() || priors.empty() ||\n \t\t    default_mode == nullptr) {\n@@ -110,10 +114,9 @@ void AwbConfig::Read(boost::property_tree::ptree const &params)\n \t\t\tbayes = false;\n \t\t}\n \t}\n-\tfast = params.get<int>(\n-\t\t\"fast\", bayes); // default to fast for Bayesian, otherwise slow\n-\twhitepoint_r = params.get<double>(\"whitepoint_r\", 0.0);\n-\twhitepoint_b = params.get<double>(\"whitepoint_b\", 0.0);\n+\tfast = params[fast].get<int>(bayes); // default to fast for Bayesian, otherwise slow\n+\twhitepoint_r = params[\"whitepoint_r\"].get<double>(0.0);\n+\twhitepoint_b = params[\"whitepoint_b\"].get<double>(0.0);\n \tif (bayes == false)\n \t\tsensitivity_r = sensitivity_b =\n \t\t\t1.0; // nor do sensitivities make any sense\n@@ -144,7 +147,7 @@ char const *Awb::Name() const\n \treturn NAME;\n }\n \n-void Awb::Read(boost::property_tree::ptree const &params)\n+void Awb::Read(const libcamera::YamlObject &params)\n {\n \tconfig_.Read(params);\n }\ndiff --git a/src/ipa/raspberrypi/controller/rpi/awb.hpp b/src/ipa/raspberrypi/controller/rpi/awb.hpp\nindex ac3dca6f42fc..41334f798e2f 100644\n--- a/src/ipa/raspberrypi/controller/rpi/awb.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/awb.hpp\n@@ -19,20 +19,20 @@ namespace RPiController {\n // Control algorithm to perform AWB calculations.\n \n struct AwbMode {\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n \tdouble ct_lo; // low CT value for search\n \tdouble ct_hi; // high CT value for search\n };\n \n struct AwbPrior {\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n \tdouble lux; // lux level\n \tPwl prior; // maps CT to prior log likelihood for this lux level\n };\n \n struct AwbConfig {\n \tAwbConfig() : default_mode(nullptr) {}\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n \t// Only repeat the AWB calculation every \"this many\" frames\n \tuint16_t frame_period;\n \t// number of initial frames for which speed taken as 1.0 (maximum)\n@@ -82,7 +82,7 @@ public:\n \t~Awb();\n \tchar const *Name() const override;\n \tvoid Initialise() override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \t// AWB handles \"pausing\" for itself.\n \tbool IsPaused() const override;\n \tvoid Pause() override;\ndiff --git a/src/ipa/raspberrypi/controller/rpi/black_level.cpp b/src/ipa/raspberrypi/controller/rpi/black_level.cpp\nindex 6b3497f13c19..de3a1e98ca1c 100644\n--- a/src/ipa/raspberrypi/controller/rpi/black_level.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/black_level.cpp\n@@ -31,13 +31,13 @@ char const *BlackLevel::Name() const\n \treturn NAME;\n }\n \n-void BlackLevel::Read(boost::property_tree::ptree const &params)\n+void BlackLevel::Read(const libcamera::YamlObject &params)\n {\n-\tuint16_t black_level = params.get<uint16_t>(\n-\t\t\"black_level\", 4096); // 64 in 10 bits scaled to 16 bits\n-\tblack_level_r_ = params.get<uint16_t>(\"black_level_r\", black_level);\n-\tblack_level_g_ = params.get<uint16_t>(\"black_level_g\", black_level);\n-\tblack_level_b_ = params.get<uint16_t>(\"black_level_b\", black_level);\n+\t// 64 in 10 bits scaled to 16 bits\n+\tuint16_t black_level = params[\"black_level\"].get<uint16_t>(4096);\n+\tblack_level_r_ = params[\"black_level_r\"].get<uint16_t>(black_level);\n+\tblack_level_g_ = params[\"black_level_g\"].get<uint16_t>(black_level);\n+\tblack_level_b_ = params[\"black_level_b\"].get<uint16_t>(black_level);\n \tLOG(RPiBlackLevel, Debug)\n \t\t<< \" Read black levels red \" << black_level_r_\n \t\t<< \" green \" << black_level_g_\ndiff --git a/src/ipa/raspberrypi/controller/rpi/black_level.hpp b/src/ipa/raspberrypi/controller/rpi/black_level.hpp\nindex 65ec4d0ed26c..5a63b5faef21 100644\n--- a/src/ipa/raspberrypi/controller/rpi/black_level.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/black_level.hpp\n@@ -18,7 +18,7 @@ class BlackLevel : public Algorithm\n public:\n \tBlackLevel(Controller *controller);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \n private:\ndiff --git a/src/ipa/raspberrypi/controller/rpi/ccm.cpp b/src/ipa/raspberrypi/controller/rpi/ccm.cpp\nindex 821a4c7c98c5..0e02a524c68d 100644\n--- a/src/ipa/raspberrypi/controller/rpi/ccm.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/ccm.cpp\n@@ -37,17 +37,15 @@ Matrix::Matrix(double m0, double m1, double m2, double m3, double m4, double m5,\n \tm[0][0] = m0, m[0][1] = m1, m[0][2] = m2, m[1][0] = m3, m[1][1] = m4,\n \tm[1][2] = m5, m[2][0] = m6, m[2][1] = m7, m[2][2] = m8;\n }\n-void Matrix::Read(boost::property_tree::ptree const &params)\n+void Matrix::Read(const libcamera::YamlObject &params)\n {\n \tdouble *ptr = (double *)m;\n-\tint n = 0;\n-\tfor (auto it = params.begin(); it != params.end(); it++) {\n-\t\tif (n++ == 9)\n-\t\t\tthrow std::runtime_error(\"Ccm: too many values in CCM\");\n-\t\t*ptr++ = it->second.get_value<double>();\n-\t}\n-\tif (n < 9)\n-\t\tthrow std::runtime_error(\"Ccm: too few values in CCM\");\n+\n+\tif (params.size() != 9)\n+\t\tthrow std::runtime_error(\"Ccm: wrong number of values in CCM\");\n+\n+\tfor (const auto &param : params.asList())\n+\t\t*ptr++ = param.get<double>(0.0);\n }\n \n Ccm::Ccm(Controller *controller)\n@@ -58,14 +56,14 @@ char const *Ccm::Name() const\n \treturn NAME;\n }\n \n-void Ccm::Read(boost::property_tree::ptree const &params)\n+void Ccm::Read(const libcamera::YamlObject &params)\n {\n-\tif (params.get_child_optional(\"saturation\"))\n-\t\tconfig_.saturation.Read(params.get_child(\"saturation\"));\n-\tfor (auto &p : params.get_child(\"ccms\")) {\n+\tif (params.contains(\"saturation\"))\n+\t\tconfig_.saturation.Read(params[\"saturation\"]);\n+\tfor (auto &p : params[\"ccms\"].asList()) {\n \t\tCtCcm ct_ccm;\n-\t\tct_ccm.ct = p.second.get<double>(\"ct\");\n-\t\tct_ccm.ccm.Read(p.second.get_child(\"ccm\"));\n+\t\tct_ccm.ct = p[\"ct\"].get<double>(0.0);\n+\t\tct_ccm.ccm.Read(p[\"ccm\"]);\n \t\tif (!config_.ccms.empty() &&\n \t\t    ct_ccm.ct <= config_.ccms.back().ct)\n \t\t\tthrow std::runtime_error(\ndiff --git a/src/ipa/raspberrypi/controller/rpi/ccm.hpp b/src/ipa/raspberrypi/controller/rpi/ccm.hpp\nindex 330ed51fe398..073f02526850 100644\n--- a/src/ipa/raspberrypi/controller/rpi/ccm.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/ccm.hpp\n@@ -20,7 +20,7 @@ struct Matrix {\n \t       double m6, double m7, double m8);\n \tMatrix();\n \tdouble m[3][3];\n-\tvoid Read(boost::property_tree::ptree const &params);\n+\tvoid Read(const libcamera::YamlObject &params);\n };\n static inline Matrix operator*(double d, Matrix const &m)\n {\n@@ -62,7 +62,7 @@ class Ccm : public CcmAlgorithm\n public:\n \tCcm(Controller *controller = NULL);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid SetSaturation(double saturation) override;\n \tvoid Initialise() override;\n \tvoid Prepare(Metadata *image_metadata) override;\ndiff --git a/src/ipa/raspberrypi/controller/rpi/contrast.cpp b/src/ipa/raspberrypi/controller/rpi/contrast.cpp\nindex ae55aad56739..534f8b48a59b 100644\n--- a/src/ipa/raspberrypi/controller/rpi/contrast.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/contrast.cpp\n@@ -36,21 +36,21 @@ char const *Contrast::Name() const\n \treturn NAME;\n }\n \n-void Contrast::Read(boost::property_tree::ptree const &params)\n+void Contrast::Read(const libcamera::YamlObject &params)\n {\n \t// enable adaptive enhancement by default\n-\tconfig_.ce_enable = params.get<int>(\"ce_enable\", 1);\n+\tconfig_.ce_enable = params[\"ce_enable\"].get<int>(1);\n \t// the point near the bottom of the histogram to move\n-\tconfig_.lo_histogram = params.get<double>(\"lo_histogram\", 0.01);\n+\tconfig_.lo_histogram = params[\"lo_histogram\"].get<double>(0.01);\n \t// where in the range to try and move it to\n-\tconfig_.lo_level = params.get<double>(\"lo_level\", 0.015);\n+\tconfig_.lo_level = params[\"lo_level\"].get<double>(0.015);\n \t// but don't move by more than this\n-\tconfig_.lo_max = params.get<double>(\"lo_max\", 500);\n+\tconfig_.lo_max = params[\"lo_max\"].get<double>(500);\n \t// equivalent values for the top of the histogram...\n-\tconfig_.hi_histogram = params.get<double>(\"hi_histogram\", 0.95);\n-\tconfig_.hi_level = params.get<double>(\"hi_level\", 0.95);\n-\tconfig_.hi_max = params.get<double>(\"hi_max\", 2000);\n-\tconfig_.gamma_curve.Read(params.get_child(\"gamma_curve\"));\n+\tconfig_.hi_histogram = params[\"hi_histogram\"].get<double>(0.95);\n+\tconfig_.hi_level = params[\"hi_level\"].get<double>(0.95);\n+\tconfig_.hi_max = params[\"hi_max\"].get<double>(2000);\n+\tconfig_.gamma_curve.Read(params[\"gamma_curve\"]);\n }\n \n void Contrast::SetBrightness(double brightness)\ndiff --git a/src/ipa/raspberrypi/controller/rpi/contrast.hpp b/src/ipa/raspberrypi/controller/rpi/contrast.hpp\nindex 85624539a1da..6b1e41724f5b 100644\n--- a/src/ipa/raspberrypi/controller/rpi/contrast.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/contrast.hpp\n@@ -32,7 +32,7 @@ class Contrast : public ContrastAlgorithm\n public:\n \tContrast(Controller *controller = NULL);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid SetBrightness(double brightness) override;\n \tvoid SetContrast(double contrast) override;\n \tvoid Initialise() override;\ndiff --git a/src/ipa/raspberrypi/controller/rpi/dpc.cpp b/src/ipa/raspberrypi/controller/rpi/dpc.cpp\nindex 110f50560e76..ac8aa78921c6 100644\n--- a/src/ipa/raspberrypi/controller/rpi/dpc.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/dpc.cpp\n@@ -29,9 +29,9 @@ char const *Dpc::Name() const\n \treturn NAME;\n }\n \n-void Dpc::Read(boost::property_tree::ptree const &params)\n+void Dpc::Read(const libcamera::YamlObject &params)\n {\n-\tconfig_.strength = params.get<int>(\"strength\", 1);\n+\tconfig_.strength = params[\"strength\"].get<int>(1);\n \tif (config_.strength < 0 || config_.strength > 2)\n \t\tthrow std::runtime_error(\"Dpc: bad strength value\");\n }\ndiff --git a/src/ipa/raspberrypi/controller/rpi/dpc.hpp b/src/ipa/raspberrypi/controller/rpi/dpc.hpp\nindex d90285c4eb56..382e20a6f1db 100644\n--- a/src/ipa/raspberrypi/controller/rpi/dpc.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/dpc.hpp\n@@ -22,7 +22,7 @@ class Dpc : public Algorithm\n public:\n \tDpc(Controller *controller);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \n private:\ndiff --git a/src/ipa/raspberrypi/controller/rpi/geq.cpp b/src/ipa/raspberrypi/controller/rpi/geq.cpp\nindex 4530cb75792c..cff3bfe01ed6 100644\n--- a/src/ipa/raspberrypi/controller/rpi/geq.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/geq.cpp\n@@ -33,14 +33,14 @@ char const *Geq::Name() const\n \treturn NAME;\n }\n \n-void Geq::Read(boost::property_tree::ptree const &params)\n+void Geq::Read(const libcamera::YamlObject &params)\n {\n-\tconfig_.offset = params.get<uint16_t>(\"offset\", 0);\n-\tconfig_.slope = params.get<double>(\"slope\", 0.0);\n+\tconfig_.offset = params[\"offset\"].get<uint16_t>(0);\n+\tconfig_.slope = params[\"slope\"].get<double>(0.0);\n \tif (config_.slope < 0.0 || config_.slope >= 1.0)\n \t\tthrow std::runtime_error(\"Geq: bad slope value\");\n-\tif (params.get_child_optional(\"strength\"))\n-\t\tconfig_.strength.Read(params.get_child(\"strength\"));\n+\tif (params.contains(\"strength\"))\n+\t\tconfig_.strength.Read(params[\"strength\"]);\n }\n \n void Geq::Prepare(Metadata *image_metadata)\ndiff --git a/src/ipa/raspberrypi/controller/rpi/geq.hpp b/src/ipa/raspberrypi/controller/rpi/geq.hpp\nindex 8ba3046b2a2b..84104be40452 100644\n--- a/src/ipa/raspberrypi/controller/rpi/geq.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/geq.hpp\n@@ -24,7 +24,7 @@ class Geq : public Algorithm\n public:\n \tGeq(Controller *controller);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \n private:\ndiff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp\nindex 4d145b6ff0e9..f10be2014f6a 100644\n--- a/src/ipa/raspberrypi/controller/rpi/lux.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp\n@@ -36,14 +36,14 @@ char const *Lux::Name() const\n \treturn NAME;\n }\n \n-void Lux::Read(boost::property_tree::ptree const &params)\n+void Lux::Read(const libcamera::YamlObject &params)\n {\n \treference_shutter_speed_ =\n-\t\tparams.get<double>(\"reference_shutter_speed\") * 1.0us;\n-\treference_gain_ = params.get<double>(\"reference_gain\");\n-\treference_aperture_ = params.get<double>(\"reference_aperture\", 1.0);\n-\treference_Y_ = params.get<double>(\"reference_Y\");\n-\treference_lux_ = params.get<double>(\"reference_lux\");\n+\t\tparams[\"reference_shutter_speed\"].get<double>(0.0) * 1.0us;\n+\treference_gain_ = params[\"reference_gain\"].get<double>(0.0);\n+\treference_aperture_ = params[\"reference_aperture\"].get<double>(1.0);\n+\treference_Y_ = params[\"reference_Y\"].get<double>(0.0);\n+\treference_lux_ = params[\"reference_lux\"].get<double>(0.0);\n \tcurrent_aperture_ = reference_aperture_;\n }\n \ndiff --git a/src/ipa/raspberrypi/controller/rpi/lux.hpp b/src/ipa/raspberrypi/controller/rpi/lux.hpp\nindex 3ebd35d1e382..7d85199f7def 100644\n--- a/src/ipa/raspberrypi/controller/rpi/lux.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/lux.hpp\n@@ -22,7 +22,7 @@ class Lux : public Algorithm\n public:\n \tLux(Controller *controller);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \tvoid Process(StatisticsPtr &stats, Metadata *image_metadata) override;\n \tvoid SetCurrentAperture(double aperture);\ndiff --git a/src/ipa/raspberrypi/controller/rpi/noise.cpp b/src/ipa/raspberrypi/controller/rpi/noise.cpp\nindex 63cad639f313..66a2a7f3486c 100644\n--- a/src/ipa/raspberrypi/controller/rpi/noise.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/noise.cpp\n@@ -39,10 +39,10 @@ void Noise::SwitchMode(CameraMode const &camera_mode,\n \tmode_factor_ = std::max(1.0, camera_mode.noise_factor);\n }\n \n-void Noise::Read(boost::property_tree::ptree const &params)\n+void Noise::Read(const libcamera::YamlObject &params)\n {\n-\treference_constant_ = params.get<double>(\"reference_constant\");\n-\treference_slope_ = params.get<double>(\"reference_slope\");\n+\treference_constant_ = params[\"reference_constant\"].get<double>(0.0);\n+\treference_slope_ = params[\"reference_slope\"].get<double>(0.0);\n }\n \n void Noise::Prepare(Metadata *image_metadata)\ndiff --git a/src/ipa/raspberrypi/controller/rpi/noise.hpp b/src/ipa/raspberrypi/controller/rpi/noise.hpp\nindex 1c9de5c87d08..353e79fa2a8c 100644\n--- a/src/ipa/raspberrypi/controller/rpi/noise.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/noise.hpp\n@@ -19,7 +19,7 @@ public:\n \tNoise(Controller *controller);\n \tchar const *Name() const override;\n \tvoid SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \n private:\ndiff --git a/src/ipa/raspberrypi/controller/rpi/sdn.cpp b/src/ipa/raspberrypi/controller/rpi/sdn.cpp\nindex 9384550983e7..619a793cbdfb 100644\n--- a/src/ipa/raspberrypi/controller/rpi/sdn.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/sdn.cpp\n@@ -32,10 +32,10 @@ char const *Sdn::Name() const\n \treturn NAME;\n }\n \n-void Sdn::Read(boost::property_tree::ptree const &params)\n+void Sdn::Read(const libcamera::YamlObject &params)\n {\n-\tdeviation_ = params.get<double>(\"deviation\", 3.2);\n-\tstrength_ = params.get<double>(\"strength\", 0.75);\n+\tdeviation_ = params[\"deviation\"].get<double>(3.2);\n+\tstrength_ = params[\"strength\"].get<double>(0.75);\n }\n \n void Sdn::Initialise() {}\ndiff --git a/src/ipa/raspberrypi/controller/rpi/sdn.hpp b/src/ipa/raspberrypi/controller/rpi/sdn.hpp\nindex 2371ce04163f..e69557908cea 100644\n--- a/src/ipa/raspberrypi/controller/rpi/sdn.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/sdn.hpp\n@@ -18,7 +18,7 @@ class Sdn : public DenoiseAlgorithm\n public:\n \tSdn(Controller *controller = NULL);\n \tchar const *Name() const override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid Initialise() override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \tvoid SetMode(DenoiseMode mode) override;\ndiff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp\nindex 18825a43867b..491f88d06c79 100644\n--- a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp\n+++ b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp\n@@ -37,11 +37,11 @@ void Sharpen::SwitchMode(CameraMode const &camera_mode,\n \tmode_factor_ = std::max(1.0, camera_mode.noise_factor);\n }\n \n-void Sharpen::Read(boost::property_tree::ptree const &params)\n+void Sharpen::Read(const libcamera::YamlObject &params)\n {\n-\tthreshold_ = params.get<double>(\"threshold\", 1.0);\n-\tstrength_ = params.get<double>(\"strength\", 1.0);\n-\tlimit_ = params.get<double>(\"limit\", 1.0);\n+\tthreshold_ = params[\"threshold\"].get<double>(1.0);\n+\tstrength_ = params[\"strength\"].get<double>(1.0);\n+\tlimit_ = params[\"limit\"].get<double>(1.0);\n \tLOG(RPiSharpen, Debug)\n \t\t<< \"Read threshold \" << threshold_\n \t\t<< \" strength \" << strength_\ndiff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp b/src/ipa/raspberrypi/controller/rpi/sharpen.hpp\nindex 13a076a86895..6dfc79afb0ac 100644\n--- a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp\n+++ b/src/ipa/raspberrypi/controller/rpi/sharpen.hpp\n@@ -19,7 +19,7 @@ public:\n \tSharpen(Controller *controller);\n \tchar const *Name() const override;\n \tvoid SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;\n-\tvoid Read(boost::property_tree::ptree const &params) override;\n+\tvoid Read(const libcamera::YamlObject &params) override;\n \tvoid SetStrength(double strength) override;\n \tvoid Prepare(Metadata *image_metadata) override;\n \ndiff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build\nindex 32897e07dad9..517d815bb98c 100644\n--- a/src/ipa/raspberrypi/meson.build\n+++ b/src/ipa/raspberrypi/meson.build\n@@ -4,7 +4,6 @@ ipa_name = 'ipa_rpi'\n \n rpi_ipa_deps = [\n     libcamera_private,\n-    dependency('boost'),\n     libatomic,\n ]\n \ndiff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex f8d37b876c54..952a6ace2911 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -7,6 +7,7 @@\n \n #include <algorithm>\n #include <array>\n+#include <cstring>\n #include <fcntl.h>\n #include <math.h>\n #include <stdint.h>\n",
    "prefixes": [
        "libcamera-devel",
        "v4",
        "4/8"
    ]
}