<div dir="ltr"><div dir="ltr">Hi Laurent,<div><br></div><div>Thank you for your patch.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 13 Jul 2022 at 10:22, Naushir Patuck <<a href="mailto:naush@raspberrypi.com">naush@raspberrypi.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com" target="_blank">laurent.pinchart@ideasonboard.com</a>><br>
<br>
The Raspberry Pi IPA module depends on boost only to parse the JSON<br>
tuning data files. As libcamera depends on libyaml, use the YamlParser<br>
class to parse those files and drop the dependency on boost.<br>
<br>
Signed-off-by: Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com" target="_blank">laurent.pinchart@ideasonboard.com</a>><br>
---<br>
 README.rst                                    |  6 --<br>
 src/ipa/raspberrypi/controller/algorithm.cpp  |  2 +-<br>
 src/ipa/raspberrypi/controller/algorithm.hpp  |  6 +-<br>
 src/ipa/raspberrypi/controller/controller.cpp | 27 ++++--<br>
 src/ipa/raspberrypi/controller/pwl.cpp        | 12 ++-<br>
 src/ipa/raspberrypi/controller/pwl.hpp        |  5 +-<br>
 src/ipa/raspberrypi/controller/rpi/agc.cpp    | 94 +++++++++----------<br>
 src/ipa/raspberrypi/controller/rpi/agc.hpp    | 10 +-<br>
 src/ipa/raspberrypi/controller/rpi/alsc.cpp   | 94 +++++++++----------<br>
 src/ipa/raspberrypi/controller/rpi/alsc.hpp   |  2 +-<br>
 src/ipa/raspberrypi/controller/rpi/awb.cpp    | 89 +++++++++---------<br>
 src/ipa/raspberrypi/controller/rpi/awb.hpp    |  8 +-<br>
 .../controller/rpi/black_level.cpp            | 12 +--<br>
 .../controller/rpi/black_level.hpp            |  2 +-<br>
 src/ipa/raspberrypi/controller/rpi/ccm.cpp    | 28 +++---<br>
 src/ipa/raspberrypi/controller/rpi/ccm.hpp    |  4 +-<br>
 .../raspberrypi/controller/rpi/contrast.cpp   | 18 ++--<br>
 .../raspberrypi/controller/rpi/contrast.hpp   |  2 +-<br>
 src/ipa/raspberrypi/controller/rpi/dpc.cpp    |  4 +-<br>
 src/ipa/raspberrypi/controller/rpi/dpc.hpp    |  2 +-<br>
 src/ipa/raspberrypi/controller/rpi/geq.cpp    | 10 +-<br>
 src/ipa/raspberrypi/controller/rpi/geq.hpp    |  2 +-<br>
 src/ipa/raspberrypi/controller/rpi/lux.cpp    | 12 +--<br>
 src/ipa/raspberrypi/controller/rpi/lux.hpp    |  2 +-<br>
 src/ipa/raspberrypi/controller/rpi/noise.cpp  |  6 +-<br>
 src/ipa/raspberrypi/controller/rpi/noise.hpp  |  2 +-<br>
 src/ipa/raspberrypi/controller/rpi/sdn.cpp    |  6 +-<br>
 src/ipa/raspberrypi/controller/rpi/sdn.hpp    |  2 +-<br>
 .../raspberrypi/controller/rpi/sharpen.cpp    |  8 +-<br>
 .../raspberrypi/controller/rpi/sharpen.hpp    |  2 +-<br>
 src/ipa/raspberrypi/meson.build               |  1 -<br>
 src/ipa/raspberrypi/raspberrypi.cpp           |  1 +<br>
 32 files changed, 241 insertions(+), 240 deletions(-)<br>
<br>
diff --git a/README.rst b/README.rst<br>
index b9e72d81b90c..3d4e48ddc8f6 100644<br>
--- a/README.rst<br>
+++ b/README.rst<br>
@@ -71,12 +71,6 @@ for improved debugging: [optional]<br>
         information, and libunwind is not needed if both libdw and the glibc<br>
         backtrace() function are available.<br>
<br>
-for the Raspberry Pi IPA: [optional]<br>
-        libboost-dev<br>
-<br>
-        Support for Raspberry Pi can be disabled through the meson<br>
-         'pipelines' option to avoid this dependency.<br>
-<br>
 for device hotplug enumeration: [optional]<br>
         libudev-dev<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/algorithm.cpp b/src/ipa/raspberrypi/controller/algorithm.cpp<br>
index 43ad0a2be222..4fd36fc1be5b 100644<br>
--- a/src/ipa/raspberrypi/controller/algorithm.cpp<br>
+++ b/src/ipa/raspberrypi/controller/algorithm.cpp<br>
@@ -9,7 +9,7 @@<br>
<br>
 using namespace RPiController;<br>
<br>
-void Algorithm::Read([[maybe_unused]] boost::property_tree::ptree const &params)<br>
+void Algorithm::Read([[maybe_unused]] const libcamera::YamlObject &params)<br>
 {<br>
 }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/algorithm.hpp b/src/ipa/raspberrypi/controller/algorithm.hpp<br>
index 5123c87bab34..87bfca8d2045 100644<br>
--- a/src/ipa/raspberrypi/controller/algorithm.hpp<br>
+++ b/src/ipa/raspberrypi/controller/algorithm.hpp<br>
@@ -13,9 +13,9 @@<br>
 #include <memory><br>
 #include <map><br>
<br>
-#include "controller.hpp"<br>
+#include "libcamera/internal/yaml_parser.h"<br>
<br>
-#include <boost/property_tree/ptree.hpp><br>
+#include "controller.hpp"<br>
<br>
 namespace RPiController {<br>
<br>
@@ -33,7 +33,7 @@ public:<br>
        virtual bool IsPaused() const { return paused_; }<br>
        virtual void Pause() { paused_ = true; }<br>
        virtual void Resume() { paused_ = false; }<br>
-       virtual void Read(boost::property_tree::ptree const &params);<br>
+       virtual void Read(const libcamera::YamlObject &params);<br>
        virtual void Initialise();<br>
        virtual void SwitchMode(CameraMode const &camera_mode, Metadata *metadata);<br>
        virtual void Prepare(Metadata *image_metadata);<br>
diff --git a/src/ipa/raspberrypi/controller/controller.cpp b/src/ipa/raspberrypi/controller/controller.cpp<br>
index d3433ad2e7e8..67d650ef0c1b 100644<br>
--- a/src/ipa/raspberrypi/controller/controller.cpp<br>
+++ b/src/ipa/raspberrypi/controller/controller.cpp<br>
@@ -5,14 +5,16 @@<br>
  * controller.cpp - ISP controller<br>
  */<br>
<br>
+#include <assert.h><br>
+<br>
+#include <libcamera/base/file.h><br>
 #include <libcamera/base/log.h><br>
<br>
+#include "libcamera/internal/yaml_parser.h"<br>
+<br>
 #include "algorithm.hpp"<br>
 #include "controller.hpp"<br>
<br>
-#include <boost/property_tree/json_parser.hpp><br>
-#include <boost/property_tree/ptree.hpp><br>
-<br>
 using namespace RPiController;<br>
 using namespace libcamera;<br>
<br>
@@ -32,16 +34,23 @@ Controller::~Controller() {}<br>
<br>
 void Controller::Read(char const *filename)<br>
 {<br>
-       boost::property_tree::ptree root;<br>
-       boost::property_tree::read_json(filename, root);<br>
-       for (auto const &key_and_value : root) {<br>
-               Algorithm *algo = CreateAlgorithm(key_and_value.first.c_str());<br>
+       File file(filename);<br>
+       if (!file.open(File::OpenModeFlag::ReadOnly)) {<br>
+               LOG(RPiController, Warning)<br>
+                       << "Failed to open tuning file '" << filename << "'";<br>
+               return;<br>
+       }<br>
+<br>
+       std::unique_ptr<YamlObject> root = YamlParser::parse(file);<br>
+<br>
+       for (auto const &[key, value] : root->asDict()) {<br>
+               Algorithm *algo = CreateAlgorithm(key.c_str());<br>
                if (algo) {<br>
-                       algo->Read(key_and_value.second);<br>
+                       algo->Read(value);<br>
                        algorithms_.push_back(AlgorithmPtr(algo));<br>
                } else<br>
                        LOG(RPiController, Warning)<br>
-                               << "No algorithm found for \"" << key_and_value.first << "\"";<br>
+                               << "No algorithm found for \"" << key << "\"";<br>
        }<br>
 }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/pwl.cpp b/src/ipa/raspberrypi/controller/pwl.cpp<br>
index 130c820b559f..9c7bc94dd484 100644<br>
--- a/src/ipa/raspberrypi/controller/pwl.cpp<br>
+++ b/src/ipa/raspberrypi/controller/pwl.cpp<br>
@@ -12,13 +12,15 @@<br>
<br>
 using namespace RPiController;<br>
<br>
-void Pwl::Read(boost::property_tree::ptree const &params)<br>
+void Pwl::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       for (auto it = params.begin(); it != params.end(); it++) {<br>
-               double x = it->second.get_value<double>();<br>
-               assert(it == params.begin() || x > points_.back().x);<br>
+       const auto &list = params.asList();<br>
+<br>
+       for (auto it = list.begin(); it != list.end(); it++) {<br>
+               double x = it->get<double>(0.0);<br>
+               assert(it == list.begin() || x > points_.back().x);<br>
                it++;<br>
-               double y = it->second.get_value<double>();<br>
+               double y = it->get<double>(0.0);<br></blockquote><div><br></div><div>Only one minor point of concern here (and throughout this patch) for me is the<br>use of default values. In the Boost parser, if a default value was not passed<br>into the get_value() call, there would be an exception thrown. This behavior<br>may be desirable since it would catch if some vital parameters were missing.<br><br>With libyaml, we always provide  default values so we cannot catch if vital<br>parameters are missing.  Perhaps we should use the "ok" return value to flag<br>this?  Not sure how much of a problem this will be in practice, perhaps David<br>(when he is back from holiday) can give his thoughts?<br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                points_.push_back(Point(x, y));<br>
        }<br>
        assert(points_.size() >= 2);<br>
diff --git a/src/ipa/raspberrypi/controller/pwl.hpp b/src/ipa/raspberrypi/controller/pwl.hpp<br>
index 484672f64095..70df4ba0daea 100644<br>
--- a/src/ipa/raspberrypi/controller/pwl.hpp<br>
+++ b/src/ipa/raspberrypi/controller/pwl.hpp<br>
@@ -6,10 +6,11 @@<br>
  */<br>
 #pragma once<br>
<br>
+#include <functional><br>
 #include <math.h><br>
 #include <vector><br>
<br>
-#include <boost/property_tree/ptree.hpp><br>
+#include "libcamera/internal/yaml_parser.h"<br>
<br>
 namespace RPiController {<br>
<br>
@@ -55,7 +56,7 @@ public:<br>
        };<br>
        Pwl() {}<br>
        Pwl(std::vector<Point> const &points) : points_(points) {}<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
        void Append(double x, double y, const double eps = 1e-6);<br>
        void Prepend(double x, double y, const double eps = 1e-6);<br>
        Interval Domain() const;<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
index f6a9cb0a2cd8..c82f29600be7 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
@@ -30,13 +30,13 @@ LOG_DEFINE_CATEGORY(RPiAgc)<br>
<br>
 #define PIPELINE_BITS 13 // seems to be a 13-bit pipeline<br>
<br>
-void AgcMeteringMode::Read(boost::property_tree::ptree const &params)<br>
+void AgcMeteringMode::Read(const libcamera::YamlObject &params)<br>
 {<br>
        int num = 0;<br>
-       for (auto &p : params.get_child("weights")) {<br>
+       for (const auto &p : params["weights"].asList()) {<br>
                if (num == AGC_STATS_SIZE)<br>
                        throw std::runtime_error("AgcConfig: too many weights");<br>
-               weights[num++] = p.second.get_value<double>();<br>
+               weights[num++] = p.get<double>(0.0);<br>
        }<br>
        if (num != AGC_STATS_SIZE)<br>
                throw std::runtime_error("AgcConfig: insufficient weights");<br>
@@ -44,39 +44,39 @@ void AgcMeteringMode::Read(boost::property_tree::ptree const &params)<br>
<br>
 static std::string<br>
 read_metering_modes(std::map<std::string, AgcMeteringMode> &metering_modes,<br>
-                   boost::property_tree::ptree const &params)<br>
+                   const libcamera::YamlObject &params)<br>
 {<br>
        std::string first;<br>
-       for (auto &p : params) {<br>
+       for (const auto &[key, value] : params.asDict()) {<br>
                AgcMeteringMode metering_mode;<br>
-               metering_mode.Read(p.second);<br>
-               metering_modes[p.first] = std::move(metering_mode);<br>
+               metering_mode.Read(value);<br>
+               metering_modes[key] = std::move(metering_mode);<br>
                if (first.empty())<br>
-                       first = p.first;<br>
+                       first = key;<br>
        }<br>
        return first;<br>
 }<br>
<br>
 static int read_list(std::vector<double> &list,<br>
-                    boost::property_tree::ptree const &params)<br>
+                    const libcamera::YamlObject &params)<br>
 {<br>
-       for (auto &p : params)<br>
-               list.push_back(p.second.get_value<double>());<br>
+       for (const auto &p : params.asList())<br>
+               list.push_back(p.get<double>(0.0));<br>
        return list.size();<br>
 }<br>
<br>
 static int read_list(std::vector<Duration> &list,<br>
-                    boost::property_tree::ptree const &params)<br>
+                    const libcamera::YamlObject &params)<br>
 {<br>
-       for (auto &p : params)<br>
-               list.push_back(p.second.get_value<double>() * 1us);<br>
+       for (const auto &p : params.asList())<br>
+               list.push_back(p.get<double>(0.0) * 1us);<br>
        return list.size();<br>
 }<br>
<br>
-void AgcExposureMode::Read(boost::property_tree::ptree const &params)<br>
+void AgcExposureMode::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       int num_shutters = read_list(shutter, params.get_child("shutter"));<br>
-       int num_ags = read_list(gain, params.get_child("gain"));<br>
+       int num_shutters = read_list(shutter, params["shutter"]);<br>
+       int num_ags = read_list(gain, params["gain"]);<br>
        if (num_shutters < 2 || num_ags < 2)<br>
                throw std::runtime_error(<br>
                        "AgcConfig: must have at least two entries in exposure profile");<br>
@@ -87,40 +87,40 @@ void AgcExposureMode::Read(boost::property_tree::ptree const &params)<br>
<br>
 static std::string<br>
 read_exposure_modes(std::map<std::string, AgcExposureMode> &exposure_modes,<br>
-                   boost::property_tree::ptree const &params)<br>
+                   const libcamera::YamlObject &params)<br>
 {<br>
        std::string first;<br>
-       for (auto &p : params) {<br>
+       for (const auto &[key, value] : params.asDict()) {<br>
                AgcExposureMode exposure_mode;<br>
-               exposure_mode.Read(p.second);<br>
-               exposure_modes[p.first] = std::move(exposure_mode);<br>
+               exposure_mode.Read(value);<br>
+               exposure_modes[key] = std::move(exposure_mode);<br>
                if (first.empty())<br>
-                       first = p.first;<br>
+                       first = key;<br>
        }<br>
        return first;<br>
 }<br>
<br>
-void AgcConstraint::Read(boost::property_tree::ptree const &params)<br>
+void AgcConstraint::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       std::string bound_string = params.get<std::string>("bound", "");<br>
+       std::string bound_string = params["bound"].get<std::string>("");<br>
        transform(bound_string.begin(), bound_string.end(),<br>
                  bound_string.begin(), ::toupper);<br>
        if (bound_string != "UPPER" && bound_string != "LOWER")<br>
                throw std::runtime_error(<br>
                        "AGC constraint type should be UPPER or LOWER");<br>
        bound = bound_string == "UPPER" ? Bound::UPPER : Bound::LOWER;<br>
-       q_lo = params.get<double>("q_lo");<br>
-       q_hi = params.get<double>("q_hi");<br>
-       Y_target.Read(params.get_child("y_target"));<br>
+       q_lo = params["q_lo"].get<double>(0.0);<br>
+       q_hi = params["q_hi"].get<double>(0.0);<br>
+       Y_target.Read(params["y_target"]);<br>
 }<br>
<br>
 static AgcConstraintMode<br>
-read_constraint_mode(boost::property_tree::ptree const &params)<br>
+read_constraint_mode(const libcamera::YamlObject &params)<br>
 {<br>
        AgcConstraintMode mode;<br>
-       for (auto &p : params) {<br>
+       for (const auto &p : params.asList()) {<br>
                AgcConstraint constraint;<br>
-               constraint.Read(p.second);<br>
+               constraint.Read(p);<br>
                mode.push_back(std::move(constraint));<br>
        }<br>
        return mode;<br>
@@ -128,36 +128,36 @@ read_constraint_mode(boost::property_tree::ptree const &params)<br>
<br>
 static std::string read_constraint_modes(<br>
        std::map<std::string, AgcConstraintMode> &constraint_modes,<br>
-       boost::property_tree::ptree const &params)<br>
+       const libcamera::YamlObject &params)<br>
 {<br>
        std::string first;<br>
-       for (auto &p : params) {<br>
-               constraint_modes[p.first] = read_constraint_mode(p.second);<br>
+       for (const auto &[key, value] : params.asDict()) {<br>
+               constraint_modes[key] = read_constraint_mode(value);<br>
                if (first.empty())<br>
-                       first = p.first;<br>
+                       first = key;<br>
        }<br>
        return first;<br>
 }<br>
<br>
-void AgcConfig::Read(boost::property_tree::ptree const &params)<br>
+void AgcConfig::Read(const libcamera::YamlObject &params)<br>
 {<br>
        LOG(RPiAgc, Debug) << "AgcConfig";<br>
        default_metering_mode = read_metering_modes(<br>
-               metering_modes, params.get_child("metering_modes"));<br>
+               metering_modes, params["metering_modes"]);<br>
        default_exposure_mode = read_exposure_modes(<br>
-               exposure_modes, params.get_child("exposure_modes"));<br>
+               exposure_modes, params["exposure_modes"]);<br>
        default_constraint_mode = read_constraint_modes(<br>
-               constraint_modes, params.get_child("constraint_modes"));<br>
-       Y_target.Read(params.get_child("y_target"));<br>
-       speed = params.get<double>("speed", 0.2);<br>
-       startup_frames = params.get<uint16_t>("startup_frames", 10);<br>
-       convergence_frames = params.get<unsigned int>("convergence_frames", 6);<br>
+               constraint_modes, params["constraint_modes"]);<br>
+       Y_target.Read(params["y_target"]);<br>
+       speed = params["speed"].get<double>(0.2);<br>
+       startup_frames = params["startup_frames"].get<uint16_t>(10);<br>
+       convergence_frames = params["convergence_frames"].get<unsigned int>(6);<br>
        fast_reduce_threshold =<br>
-               params.get<double>("fast_reduce_threshold", 0.4);<br>
-       base_ev = params.get<double>("base_ev", 1.0);<br>
+               params["fast_reduce_threshold"].get<double>(0.4);<br>
+       base_ev = params["base_ev"].get<double>(1.0);<br>
        // Start with quite a low value as ramping up is easier than ramping down.<br>
-       default_exposure_time = params.get<double>("default_exposure_time", 1000) * 1us;<br>
-       default_analogue_gain = params.get<double>("default_analogue_gain", 1.0);<br>
+       default_exposure_time = params["default_exposure_time"].get<double>(1000) * 1us;<br>
+       default_analogue_gain = params["default_analogue_gain"].get<double>(1.0);<br>
 }<br>
<br>
 Agc::ExposureValues::ExposureValues()<br>
@@ -186,7 +186,7 @@ char const *Agc::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Agc::Read(boost::property_tree::ptree const &params)<br>
+void Agc::Read(const libcamera::YamlObject &params)<br>
 {<br>
        LOG(RPiAgc, Debug) << "Agc";<br>
        config_.Read(params);<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp<br>
index c100d3128c90..7794ba744efc 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/agc.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp<br>
@@ -26,13 +26,13 @@ namespace RPiController {<br>
<br>
 struct AgcMeteringMode {<br>
        double weights[AGC_STATS_SIZE];<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
 };<br>
<br>
 struct AgcExposureMode {<br>
        std::vector<libcamera::utils::Duration> shutter;<br>
        std::vector<double> gain;<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
 };<br>
<br>
 struct AgcConstraint {<br>
@@ -41,13 +41,13 @@ struct AgcConstraint {<br>
        double q_lo;<br>
        double q_hi;<br>
        Pwl Y_target;<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
 };<br>
<br>
 typedef std::vector<AgcConstraint> AgcConstraintMode;<br>
<br>
 struct AgcConfig {<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
        std::map<std::string, AgcMeteringMode> metering_modes;<br>
        std::map<std::string, AgcExposureMode> exposure_modes;<br>
        std::map<std::string, AgcConstraintMode> constraint_modes;<br>
@@ -72,7 +72,7 @@ class Agc : public AgcAlgorithm<br>
 public:<br>
        Agc(Controller *controller);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        // AGC handles "pausing" for itself.<br>
        bool IsPaused() const override;<br>
        void Pause() override;<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.cpp b/src/ipa/raspberrypi/controller/rpi/alsc.cpp<br>
index e575c14a92db..b38b037c7713 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp<br>
@@ -5,6 +5,7 @@<br>
  * alsc.cpp - ALSC (auto lens shading correction) control algorithm<br>
  */<br>
<br>
+#include <functional><br>
 #include <math.h><br>
 #include <numeric><br>
<br>
@@ -50,12 +51,12 @@ char const *Alsc::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-static void generate_lut(double *lut, boost::property_tree::ptree const &params)<br>
+static void generate_lut(double *lut, const libcamera::YamlObject &params)<br>
 {<br>
-       double cstrength = params.get<double>("corner_strength", 2.0);<br>
+       double cstrength = params["corner_strength"].get<double>(2.0);<br>
        if (cstrength <= 1.0)<br>
                throw std::runtime_error("Alsc: corner_strength must be > 1.0");<br>
-       double asymmetry = params.get<double>("asymmetry", 1.0);<br>
+       double asymmetry = params["asymmetry"].get<double>(1.0);<br>
        if (asymmetry < 0)<br>
                throw std::runtime_error("Alsc: asymmetry must be >= 0");<br>
        double f1 = cstrength - 1, f2 = 1 + sqrt(cstrength);<br>
@@ -73,50 +74,43 @@ static void generate_lut(double *lut, boost::property_tree::ptree const &params)<br>
        }<br>
 }<br>
<br>
-static void read_lut(double *lut, boost::property_tree::ptree const &params)<br>
+static void read_lut(double *lut, const libcamera::YamlObject &params)<br>
 {<br>
+       if (params.size() != XY)<br>
+               throw std::runtime_error(<br>
+                       "Alsc: invalid number of entries in LSC table");<br>
+<br>
        int num = 0;<br>
-       const int max_num = XY;<br>
-       for (auto &p : params) {<br>
-               if (num == max_num)<br>
-                       throw std::runtime_error(<br>
-                               "Alsc: too many entries in LSC table");<br>
-               lut[num++] = p.second.get_value<double>();<br>
-       }<br>
-       if (num < max_num)<br>
-               throw std::runtime_error("Alsc: too few entries in LSC table");<br>
+       for (const auto &p : params.asList())<br>
+               lut[num++] = p.get<double>(0.0);<br>
 }<br>
<br>
 static void read_calibrations(std::vector<AlscCalibration> &calibrations,<br>
-                             boost::property_tree::ptree const &params,<br>
+                             const libcamera::YamlObject &params,<br>
                              std::string const &name)<br>
 {<br>
-       if (params.get_child_optional(name)) {<br>
+       if (params.contains(name)) {<br>
                double last_ct = 0;<br>
-               for (auto &p : params.get_child(name)) {<br>
-                       double ct = p.second.get<double>("ct");<br>
+               for (const auto &p : params[name].asList()) {<br>
+                       double ct = p["ct"].get<double>(0.0);<br>
                        if (ct <= last_ct)<br>
                                throw std::runtime_error(<br>
                                        "Alsc: entries in " + name +<br>
                                        " must be in increasing ct order");<br>
                        AlscCalibration calibration;<br>
                        calibration.ct = last_ct = ct;<br>
-                       boost::property_tree::ptree const &table =<br>
-                               p.second.get_child("table");<br>
-                       int num = 0;<br>
-                       for (auto it = table.begin(); it != table.end(); it++) {<br>
-                               if (num == XY)<br>
-                                       throw std::runtime_error(<br>
-                                               "Alsc: too many values for ct " +<br>
-                                               std::to_string(ct) + " in " +<br>
-                                               name);<br>
-                               calibration.table[num++] =<br>
-                                       it->second.get_value<double>();<br>
-                       }<br>
-                       if (num != XY)<br>
+<br>
+                       const libcamera::YamlObject &table = p["table"];<br>
+                       if (table.size() != XY)<br>
                                throw std::runtime_error(<br>
-                                       "Alsc: too few values for ct " +<br>
-                                       std::to_string(ct) + " in " + name);<br>
+                                       "Alsc: incorrect number of values for ct " +<br>
+                                       std::to_string(ct) + " in " +<br>
+                                       name);<br>
+<br>
+                       int num = 0;<br>
+                       for (const auto &value : table.asList())<br>
+                               calibration.table[num++] = value.get<double>(0.0);<br>
+<br>
                        calibrations.push_back(calibration);<br>
                        LOG(RPiAlsc, Debug)<br>
                                << "Read " << name << " calibration for ct " << ct;<br>
@@ -124,35 +118,35 @@ static void read_calibrations(std::vector<AlscCalibration> &calibrations,<br>
        }<br>
 }<br>
<br>
-void Alsc::Read(boost::property_tree::ptree const &params)<br>
+void Alsc::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       config_.frame_period = params.get<uint16_t>("frame_period", 12);<br>
-       config_.startup_frames = params.get<uint16_t>("startup_frames", 10);<br>
-       config_.speed = params.get<double>("speed", 0.05);<br>
-       double sigma = params.get<double>("sigma", 0.01);<br>
-       config_.sigma_Cr = params.get<double>("sigma_Cr", sigma);<br>
-       config_.sigma_Cb = params.get<double>("sigma_Cb", sigma);<br>
-       config_.min_count = params.get<double>("min_count", 10.0);<br>
-       config_.min_G = params.get<uint16_t>("min_G", 50);<br>
-       config_.omega = params.get<double>("omega", 1.3);<br>
-       config_.n_iter = params.get<uint32_t>("n_iter", X + Y);<br>
+       config_.frame_period = params["frame_period"].get<uint16_t>(12);<br>
+       config_.startup_frames = params["startup_frames"].get<uint16_t>(10);<br>
+       config_.speed = params["speed"].get<double>(0.05);<br>
+       double sigma = params["sigma"].get<double>(0.01);<br>
+       config_.sigma_Cr = params["sigma_Cr"].get<double>(sigma);<br>
+       config_.sigma_Cb = params["sigma_Cb"].get<double>(sigma);<br>
+       config_.min_count = params["min_count"].get<double>(10.0);<br>
+       config_.min_G = params["min_G"].get<uint16_t>(50);<br>
+       config_.omega = params["omega"].get<double>(1.3);<br>
+       config_.n_iter = params["n_iter"].get<uint32_t>(X + Y);<br>
        config_.luminance_strength =<br>
-               params.get<double>("luminance_strength", 1.0);<br>
+               params["luminance_strength"].get<double>(1.0);<br>
        for (int i = 0; i < XY; i++)<br>
                config_.luminance_lut[i] = 1.0;<br>
-       if (params.get_child_optional("corner_strength"))<br>
+       if (params.contains("corner_strength"))<br>
                generate_lut(config_.luminance_lut, params);<br>
-       else if (params.get_child_optional("luminance_lut"))<br>
+       else if (params.contains("luminance_lut"))<br>
                read_lut(config_.luminance_lut,<br>
-                        params.get_child("luminance_lut"));<br>
+                        params["luminance_lut"]);<br>
        else<br>
                LOG(RPiAlsc, Warning)<br>
                        << "no luminance table - assume unity everywhere";<br>
        read_calibrations(config_.calibrations_Cr, params, "calibrations_Cr");<br>
        read_calibrations(config_.calibrations_Cb, params, "calibrations_Cb");<br>
-       config_.default_ct = params.get<double>("default_ct", 4500.0);<br>
-       config_.threshold = params.get<double>("threshold", 1e-3);<br>
-       config_.lambda_bound = params.get<double>("lambda_bound", 0.05);<br>
+       config_.default_ct = params["default_ct"].get<double>(4500.0);<br>
+       config_.threshold = params["threshold"].get<double>(1e-3);<br>
+       config_.lambda_bound = params["lambda_bound"].get<double>(0.05);<br>
 }<br>
<br>
 static double get_ct(Metadata *metadata, double default_ct);<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.hpp b/src/ipa/raspberrypi/controller/rpi/alsc.hpp<br>
index d1dbe0d1d22d..9d28c1b49a6d 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/alsc.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/alsc.hpp<br>
@@ -52,7 +52,7 @@ public:<br>
        char const *Name() const override;<br>
        void Initialise() override;<br>
        void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
        void Process(StatisticsPtr &stats, Metadata *image_metadata) override;<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp<br>
index d4c934473832..1c40bf878cd3 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/awb.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/awb.cpp<br>
@@ -5,6 +5,8 @@<br>
  * awb.cpp - AWB control algorithm<br>
  */<br>
<br>
+#include <assert.h><br>
+<br>
 #include <libcamera/base/log.h><br>
<br>
 #include "../lux_status.h"<br>
@@ -24,33 +26,35 @@ LOG_DEFINE_CATEGORY(RPiAwb)<br>
 // todo - the locking in this algorithm needs some tidying up as has been done<br>
 // elsewhere (ALSC and AGC).<br>
<br>
-void AwbMode::Read(boost::property_tree::ptree const &params)<br>
+void AwbMode::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       ct_lo = params.get<double>("lo");<br>
-       ct_hi = params.get<double>("hi");<br>
+       ct_lo = params["lo"].get<double>(0.0);<br>
+       ct_hi = params["hi"].get<double>(0.0);<br>
 }<br>
<br>
-void AwbPrior::Read(boost::property_tree::ptree const &params)<br>
+void AwbPrior::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       lux = params.get<double>("lux");<br>
-       prior.Read(params.get_child("prior"));<br>
+       lux = params["lux"].get<double>(0.0);<br>
+       prior.Read(params["prior"]);<br>
 }<br>
<br>
 static void read_ct_curve(Pwl &ct_r, Pwl &ct_b,<br>
-                         boost::property_tree::ptree const &params)<br>
+                         const libcamera::YamlObject &params)<br>
 {<br>
+       const auto &list = params.asList();<br>
        int num = 0;<br>
-       for (auto it = params.begin(); it != params.end(); it++) {<br>
-               double ct = it->second.get_value<double>();<br>
-               assert(it == params.begin() || ct != ct_r.Domain().end);<br>
-               if (++it == params.end())<br>
+<br>
+       for (auto it = list.begin(); it != list.end(); it++) {<br>
+               double ct = it->get<double>(0.0);<br>
+               assert(it == list.begin() || ct != ct_r.Domain().end);<br>
+               if (++it == list.end())<br>
                        throw std::runtime_error(<br>
                                "AwbConfig: incomplete CT curve entry");<br>
-               ct_r.Append(ct, it->second.get_value<double>());<br>
-               if (++it == params.end())<br>
+               ct_r.Append(ct, it->get<double>(0.0));<br>
+               if (++it == list.end())<br>
                        throw std::runtime_error(<br>
                                "AwbConfig: incomplete CT curve entry");<br>
-               ct_b.Append(ct, it->second.get_value<double>());<br>
+               ct_b.Append(ct, it->get<double>(0.0));<br>
                num++;<br>
        }<br>
        if (num < 2)<br>
@@ -58,19 +62,19 @@ static void read_ct_curve(Pwl &ct_r, Pwl &ct_b,<br>
                        "AwbConfig: insufficient points in CT curve");<br>
 }<br>
<br>
-void AwbConfig::Read(boost::property_tree::ptree const &params)<br>
+void AwbConfig::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       bayes = params.get<int>("bayes", 1);<br>
-       frame_period = params.get<uint16_t>("frame_period", 10);<br>
-       startup_frames = params.get<uint16_t>("startup_frames", 10);<br>
-       convergence_frames = params.get<unsigned int>("convergence_frames", 3);<br>
-       speed = params.get<double>("speed", 0.05);<br>
-       if (params.get_child_optional("ct_curve"))<br>
-               read_ct_curve(ct_r, ct_b, params.get_child("ct_curve"));<br>
-       if (params.get_child_optional("priors")) {<br>
-               for (auto &p : params.get_child("priors")) {<br>
+       bayes = params["bayes"].get<int>(1);<br>
+       frame_period = params["frame_period"].get<uint16_t>(10);<br>
+       startup_frames = params["startup_frames"].get<uint16_t>(10);<br>
+       convergence_frames = params["convergence_frames"].get<unsigned int>(3);<br>
+       speed = params["speed"].get<double>(0.05);<br>
+       if (params.contains("ct_curve"))<br>
+               read_ct_curve(ct_r, ct_b, params["ct_curve"]);<br>
+       if (params.contains("priors")) {<br>
+               for (const auto &p : params["priors"].asList()) {<br>
                        AwbPrior prior;<br>
-                       prior.Read(p.second);<br>
+                       prior.Read(p);<br>
                        if (!priors.empty() && prior.lux <= priors.back().lux)<br>
                                throw std::runtime_error(<br>
                                        "AwbConfig: Prior must be ordered in increasing lux value");<br>
@@ -80,28 +84,28 @@ void AwbConfig::Read(boost::property_tree::ptree const &params)<br>
                        throw std::runtime_error(<br>
                                "AwbConfig: no AWB priors configured");<br>
        }<br>
-       if (params.get_child_optional("modes")) {<br>
-               for (auto &p : params.get_child("modes")) {<br>
-                       modes[p.first].Read(p.second);<br>
+       if (params.contains("modes")) {<br>
+               for (const auto &[key, value] : params["modes"].asDict()) {<br>
+                       modes[key].Read(value);<br>
                        if (default_mode == nullptr)<br>
-                               default_mode = &modes[p.first];<br>
+                               default_mode = &modes[key];<br>
                }<br>
                if (default_mode == nullptr)<br>
                        throw std::runtime_error(<br>
                                "AwbConfig: no AWB modes configured");<br>
        }<br>
-       min_pixels = params.get<double>("min_pixels", 16.0);<br>
-       min_G = params.get<uint16_t>("min_G", 32);<br>
-       min_regions = params.get<uint32_t>("min_regions", 10);<br>
-       delta_limit = params.get<double>("delta_limit", 0.2);<br>
-       coarse_step = params.get<double>("coarse_step", 0.2);<br>
-       transverse_pos = params.get<double>("transverse_pos", 0.01);<br>
-       transverse_neg = params.get<double>("transverse_neg", 0.01);<br>
+       min_pixels = params["min_pixels"].get<double>(16.0);<br>
+       min_G = params["min_G"].get<uint16_t>(32);<br>
+       min_regions = params["min_regions"].get<uint32_t>(10);<br>
+       delta_limit = params["delta_limit"].get<double>(0.2);<br>
+       coarse_step = params["coarse_step"].get<double>(0.2);<br>
+       transverse_pos = params["transverse_pos"].get<double>(0.01);<br>
+       transverse_neg = params["transverse_neg"].get<double>(0.01);<br>
        if (transverse_pos <= 0 || transverse_neg <= 0)<br>
                throw std::runtime_error(<br>
                        "AwbConfig: transverse_pos/neg must be > 0");<br>
-       sensitivity_r = params.get<double>("sensitivity_r", 1.0);<br>
-       sensitivity_b = params.get<double>("sensitivity_b", 1.0);<br>
+       sensitivity_r = params["sensitivity_r"].get<double>(1.0);<br>
+       sensitivity_b = params["sensitivity_b"].get<double>(1.0);<br>
        if (bayes) {<br>
                if (ct_r.Empty() || ct_b.Empty() || priors.empty() ||<br>
                    default_mode == nullptr) {<br>
@@ -110,10 +114,9 @@ void AwbConfig::Read(boost::property_tree::ptree const &params)<br>
                        bayes = false;<br>
                }<br>
        }<br>
-       fast = params.get<int>(<br>
-               "fast", bayes); // default to fast for Bayesian, otherwise slow<br>
-       whitepoint_r = params.get<double>("whitepoint_r", 0.0);<br>
-       whitepoint_b = params.get<double>("whitepoint_b", 0.0);<br>
+       fast = params[fast].get<int>(bayes); // default to fast for Bayesian, otherwise slow<br>
+       whitepoint_r = params["whitepoint_r"].get<double>(0.0);<br>
+       whitepoint_b = params["whitepoint_b"].get<double>(0.0);<br>
        if (bayes == false)<br>
                sensitivity_r = sensitivity_b =<br>
                        1.0; // nor do sensitivities make any sense<br>
@@ -144,7 +147,7 @@ char const *Awb::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Awb::Read(boost::property_tree::ptree const &params)<br>
+void Awb::Read(const libcamera::YamlObject &params)<br>
 {<br>
        config_.Read(params);<br>
 }<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.hpp b/src/ipa/raspberrypi/controller/rpi/awb.hpp<br>
index ac3dca6f42fc..41334f798e2f 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/awb.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/awb.hpp<br>
@@ -19,20 +19,20 @@ namespace RPiController {<br>
 // Control algorithm to perform AWB calculations.<br>
<br>
 struct AwbMode {<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
        double ct_lo; // low CT value for search<br>
        double ct_hi; // high CT value for search<br>
 };<br>
<br>
 struct AwbPrior {<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
        double lux; // lux level<br>
        Pwl prior; // maps CT to prior log likelihood for this lux level<br>
 };<br>
<br>
 struct AwbConfig {<br>
        AwbConfig() : default_mode(nullptr) {}<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
        // Only repeat the AWB calculation every "this many" frames<br>
        uint16_t frame_period;<br>
        // number of initial frames for which speed taken as 1.0 (maximum)<br>
@@ -82,7 +82,7 @@ public:<br>
        ~Awb();<br>
        char const *Name() const override;<br>
        void Initialise() override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        // AWB handles "pausing" for itself.<br>
        bool IsPaused() const override;<br>
        void Pause() override;<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/black_level.cpp b/src/ipa/raspberrypi/controller/rpi/black_level.cpp<br>
index 6b3497f13c19..de3a1e98ca1c 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/black_level.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/black_level.cpp<br>
@@ -31,13 +31,13 @@ char const *BlackLevel::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void BlackLevel::Read(boost::property_tree::ptree const &params)<br>
+void BlackLevel::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       uint16_t black_level = params.get<uint16_t>(<br>
-               "black_level", 4096); // 64 in 10 bits scaled to 16 bits<br>
-       black_level_r_ = params.get<uint16_t>("black_level_r", black_level);<br>
-       black_level_g_ = params.get<uint16_t>("black_level_g", black_level);<br>
-       black_level_b_ = params.get<uint16_t>("black_level_b", black_level);<br>
+       // 64 in 10 bits scaled to 16 bits<br>
+       uint16_t black_level = params["black_level"].get<uint16_t>(4096);<br>
+       black_level_r_ = params["black_level_r"].get<uint16_t>(black_level);<br>
+       black_level_g_ = params["black_level_g"].get<uint16_t>(black_level);<br>
+       black_level_b_ = params["black_level_b"].get<uint16_t>(black_level);<br>
        LOG(RPiBlackLevel, Debug)<br>
                << " Read black levels red " << black_level_r_<br>
                << " green " << black_level_g_<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/black_level.hpp b/src/ipa/raspberrypi/controller/rpi/black_level.hpp<br>
index 65ec4d0ed26c..5a63b5faef21 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/black_level.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/black_level.hpp<br>
@@ -18,7 +18,7 @@ class BlackLevel : public Algorithm<br>
 public:<br>
        BlackLevel(Controller *controller);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
<br>
 private:<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/ccm.cpp b/src/ipa/raspberrypi/controller/rpi/ccm.cpp<br>
index 821a4c7c98c5..0e02a524c68d 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/ccm.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/ccm.cpp<br>
@@ -37,17 +37,15 @@ Matrix::Matrix(double m0, double m1, double m2, double m3, double m4, double m5,<br>
        m[0][0] = m0, m[0][1] = m1, m[0][2] = m2, m[1][0] = m3, m[1][1] = m4,<br>
        m[1][2] = m5, m[2][0] = m6, m[2][1] = m7, m[2][2] = m8;<br>
 }<br>
-void Matrix::Read(boost::property_tree::ptree const &params)<br>
+void Matrix::Read(const libcamera::YamlObject &params)<br>
 {<br>
        double *ptr = (double *)m;<br>
-       int n = 0;<br>
-       for (auto it = params.begin(); it != params.end(); it++) {<br>
-               if (n++ == 9)<br>
-                       throw std::runtime_error("Ccm: too many values in CCM");<br>
-               *ptr++ = it->second.get_value<double>();<br>
-       }<br>
-       if (n < 9)<br>
-               throw std::runtime_error("Ccm: too few values in CCM");<br>
+<br>
+       if (params.size() != 9)<br>
+               throw std::runtime_error("Ccm: wrong number of values in CCM");<br>
+<br>
+       for (const auto &param : params.asList())<br>
+               *ptr++ = param.get<double>(0.0);<br>
 }<br>
<br>
 Ccm::Ccm(Controller *controller)<br>
@@ -58,14 +56,14 @@ char const *Ccm::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Ccm::Read(boost::property_tree::ptree const &params)<br>
+void Ccm::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       if (params.get_child_optional("saturation"))<br>
-               config_.saturation.Read(params.get_child("saturation"));<br>
-       for (auto &p : params.get_child("ccms")) {<br>
+       if (params.contains("saturation"))<br>
+               config_.saturation.Read(params["saturation"]);<br>
+       for (auto &p : params["ccms"].asList()) {<br>
                CtCcm ct_ccm;<br>
-               ct_ccm.ct = p.second.get<double>("ct");<br>
-               ct_ccm.ccm.Read(p.second.get_child("ccm"));<br>
+               ct_ccm.ct = p["ct"].get<double>(0.0);<br>
+               ct_ccm.ccm.Read(p["ccm"]);<br>
                if (!config_.ccms.empty() &&<br>
                    ct_ccm.ct <= config_.ccms.back().ct)<br>
                        throw std::runtime_error(<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/ccm.hpp b/src/ipa/raspberrypi/controller/rpi/ccm.hpp<br>
index 330ed51fe398..073f02526850 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/ccm.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/ccm.hpp<br>
@@ -20,7 +20,7 @@ struct Matrix {<br>
               double m6, double m7, double m8);<br>
        Matrix();<br>
        double m[3][3];<br>
-       void Read(boost::property_tree::ptree const &params);<br>
+       void Read(const libcamera::YamlObject &params);<br>
 };<br>
 static inline Matrix operator*(double d, Matrix const &m)<br>
 {<br>
@@ -62,7 +62,7 @@ class Ccm : public CcmAlgorithm<br>
 public:<br>
        Ccm(Controller *controller = NULL);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void SetSaturation(double saturation) override;<br>
        void Initialise() override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.cpp b/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
index ae55aad56739..534f8b48a59b 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
@@ -36,21 +36,21 @@ char const *Contrast::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Contrast::Read(boost::property_tree::ptree const &params)<br>
+void Contrast::Read(const libcamera::YamlObject &params)<br>
 {<br>
        // enable adaptive enhancement by default<br>
-       config_.ce_enable = params.get<int>("ce_enable", 1);<br>
+       config_.ce_enable = params["ce_enable"].get<int>(1);<br>
        // the point near the bottom of the histogram to move<br>
-       config_.lo_histogram = params.get<double>("lo_histogram", 0.01);<br>
+       config_.lo_histogram = params["lo_histogram"].get<double>(0.01);<br>
        // where in the range to try and move it to<br>
-       config_.lo_level = params.get<double>("lo_level", 0.015);<br>
+       config_.lo_level = params["lo_level"].get<double>(0.015);<br>
        // but don't move by more than this<br>
-       config_.lo_max = params.get<double>("lo_max", 500);<br>
+       config_.lo_max = params["lo_max"].get<double>(500);<br>
        // equivalent values for the top of the histogram...<br>
-       config_.hi_histogram = params.get<double>("hi_histogram", 0.95);<br>
-       config_.hi_level = params.get<double>("hi_level", 0.95);<br>
-       config_.hi_max = params.get<double>("hi_max", 2000);<br>
-       config_.gamma_curve.Read(params.get_child("gamma_curve"));<br>
+       config_.hi_histogram = params["hi_histogram"].get<double>(0.95);<br>
+       config_.hi_level = params["hi_level"].get<double>(0.95);<br>
+       config_.hi_max = params["hi_max"].get<double>(2000);<br>
+       config_.gamma_curve.Read(params["gamma_curve"]);<br>
 }<br>
<br>
 void Contrast::SetBrightness(double brightness)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.hpp b/src/ipa/raspberrypi/controller/rpi/contrast.hpp<br>
index 85624539a1da..6b1e41724f5b 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/contrast.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/contrast.hpp<br>
@@ -32,7 +32,7 @@ class Contrast : public ContrastAlgorithm<br>
 public:<br>
        Contrast(Controller *controller = NULL);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void SetBrightness(double brightness) override;<br>
        void SetContrast(double contrast) override;<br>
        void Initialise() override;<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/dpc.cpp b/src/ipa/raspberrypi/controller/rpi/dpc.cpp<br>
index 110f50560e76..ac8aa78921c6 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/dpc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/dpc.cpp<br>
@@ -29,9 +29,9 @@ char const *Dpc::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Dpc::Read(boost::property_tree::ptree const &params)<br>
+void Dpc::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       config_.strength = params.get<int>("strength", 1);<br>
+       config_.strength = params["strength"].get<int>(1);<br>
        if (config_.strength < 0 || config_.strength > 2)<br>
                throw std::runtime_error("Dpc: bad strength value");<br>
 }<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/dpc.hpp b/src/ipa/raspberrypi/controller/rpi/dpc.hpp<br>
index d90285c4eb56..382e20a6f1db 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/dpc.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/dpc.hpp<br>
@@ -22,7 +22,7 @@ class Dpc : public Algorithm<br>
 public:<br>
        Dpc(Controller *controller);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
<br>
 private:<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/geq.cpp b/src/ipa/raspberrypi/controller/rpi/geq.cpp<br>
index 4530cb75792c..cff3bfe01ed6 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/geq.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/geq.cpp<br>
@@ -33,14 +33,14 @@ char const *Geq::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Geq::Read(boost::property_tree::ptree const &params)<br>
+void Geq::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       config_.offset = params.get<uint16_t>("offset", 0);<br>
-       config_.slope = params.get<double>("slope", 0.0);<br>
+       config_.offset = params["offset"].get<uint16_t>(0);<br>
+       config_.slope = params["slope"].get<double>(0.0);<br>
        if (config_.slope < 0.0 || config_.slope >= 1.0)<br>
                throw std::runtime_error("Geq: bad slope value");<br>
-       if (params.get_child_optional("strength"))<br>
-               config_.strength.Read(params.get_child("strength"));<br>
+       if (params.contains("strength"))<br>
+               config_.strength.Read(params["strength"]);<br>
 }<br>
<br>
 void Geq::Prepare(Metadata *image_metadata)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/geq.hpp b/src/ipa/raspberrypi/controller/rpi/geq.hpp<br>
index 8ba3046b2a2b..84104be40452 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/geq.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/geq.hpp<br>
@@ -24,7 +24,7 @@ class Geq : public Algorithm<br>
 public:<br>
        Geq(Controller *controller);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
<br>
 private:<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp<br>
index 4d145b6ff0e9..f10be2014f6a 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/lux.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp<br>
@@ -36,14 +36,14 @@ char const *Lux::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Lux::Read(boost::property_tree::ptree const &params)<br>
+void Lux::Read(const libcamera::YamlObject &params)<br>
 {<br>
        reference_shutter_speed_ =<br>
-               params.get<double>("reference_shutter_speed") * 1.0us;<br>
-       reference_gain_ = params.get<double>("reference_gain");<br>
-       reference_aperture_ = params.get<double>("reference_aperture", 1.0);<br>
-       reference_Y_ = params.get<double>("reference_Y");<br>
-       reference_lux_ = params.get<double>("reference_lux");<br>
+               params["reference_shutter_speed"].get<double>(0.0) * 1.0us;<br>
+       reference_gain_ = params["reference_gain"].get<double>(0.0);<br>
+       reference_aperture_ = params["reference_aperture"].get<double>(1.0);<br>
+       reference_Y_ = params["reference_Y"].get<double>(0.0);<br>
+       reference_lux_ = params["reference_lux"].get<double>(0.0);<br>
        current_aperture_ = reference_aperture_;<br>
 }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/lux.hpp b/src/ipa/raspberrypi/controller/rpi/lux.hpp<br>
index 3ebd35d1e382..7d85199f7def 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/lux.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/lux.hpp<br>
@@ -22,7 +22,7 @@ class Lux : public Algorithm<br>
 public:<br>
        Lux(Controller *controller);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
        void Process(StatisticsPtr &stats, Metadata *image_metadata) override;<br>
        void SetCurrentAperture(double aperture);<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/noise.cpp b/src/ipa/raspberrypi/controller/rpi/noise.cpp<br>
index 63cad639f313..66a2a7f3486c 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/noise.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/noise.cpp<br>
@@ -39,10 +39,10 @@ void Noise::SwitchMode(CameraMode const &camera_mode,<br>
        mode_factor_ = std::max(1.0, camera_mode.noise_factor);<br>
 }<br>
<br>
-void Noise::Read(boost::property_tree::ptree const &params)<br>
+void Noise::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       reference_constant_ = params.get<double>("reference_constant");<br>
-       reference_slope_ = params.get<double>("reference_slope");<br>
+       reference_constant_ = params["reference_constant"].get<double>(0.0);<br>
+       reference_slope_ = params["reference_slope"].get<double>(0.0);<br>
 }<br>
<br>
 void Noise::Prepare(Metadata *image_metadata)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/noise.hpp b/src/ipa/raspberrypi/controller/rpi/noise.hpp<br>
index 1c9de5c87d08..353e79fa2a8c 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/noise.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/noise.hpp<br>
@@ -19,7 +19,7 @@ public:<br>
        Noise(Controller *controller);<br>
        char const *Name() const override;<br>
        void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
<br>
 private:<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/sdn.cpp b/src/ipa/raspberrypi/controller/rpi/sdn.cpp<br>
index 9384550983e7..619a793cbdfb 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sdn.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sdn.cpp<br>
@@ -32,10 +32,10 @@ char const *Sdn::Name() const<br>
        return NAME;<br>
 }<br>
<br>
-void Sdn::Read(boost::property_tree::ptree const &params)<br>
+void Sdn::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       deviation_ = params.get<double>("deviation", 3.2);<br>
-       strength_ = params.get<double>("strength", 0.75);<br>
+       deviation_ = params["deviation"].get<double>(3.2);<br>
+       strength_ = params["strength"].get<double>(0.75);<br>
 }<br>
<br>
 void Sdn::Initialise() {}<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/sdn.hpp b/src/ipa/raspberrypi/controller/rpi/sdn.hpp<br>
index 2371ce04163f..e69557908cea 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sdn.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sdn.hpp<br>
@@ -18,7 +18,7 @@ class Sdn : public DenoiseAlgorithm<br>
 public:<br>
        Sdn(Controller *controller = NULL);<br>
        char const *Name() const override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void Initialise() override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
        void SetMode(DenoiseMode mode) override;<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp<br>
index 18825a43867b..491f88d06c79 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp<br>
@@ -37,11 +37,11 @@ void Sharpen::SwitchMode(CameraMode const &camera_mode,<br>
        mode_factor_ = std::max(1.0, camera_mode.noise_factor);<br>
 }<br>
<br>
-void Sharpen::Read(boost::property_tree::ptree const &params)<br>
+void Sharpen::Read(const libcamera::YamlObject &params)<br>
 {<br>
-       threshold_ = params.get<double>("threshold", 1.0);<br>
-       strength_ = params.get<double>("strength", 1.0);<br>
-       limit_ = params.get<double>("limit", 1.0);<br>
+       threshold_ = params["threshold"].get<double>(1.0);<br>
+       strength_ = params["strength"].get<double>(1.0);<br>
+       limit_ = params["limit"].get<double>(1.0);<br>
        LOG(RPiSharpen, Debug)<br>
                << "Read threshold " << threshold_<br>
                << " strength " << strength_<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp b/src/ipa/raspberrypi/controller/rpi/sharpen.hpp<br>
index 13a076a86895..6dfc79afb0ac 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sharpen.hpp<br>
@@ -19,7 +19,7 @@ public:<br>
        Sharpen(Controller *controller);<br>
        char const *Name() const override;<br>
        void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;<br>
-       void Read(boost::property_tree::ptree const &params) override;<br>
+       void Read(const libcamera::YamlObject &params) override;<br>
        void SetStrength(double strength) override;<br>
        void Prepare(Metadata *image_metadata) override;<br>
<br>
diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build<br>
index 32897e07dad9..517d815bb98c 100644<br>
--- a/src/ipa/raspberrypi/meson.build<br>
+++ b/src/ipa/raspberrypi/meson.build<br>
@@ -4,7 +4,6 @@ ipa_name = 'ipa_rpi'<br>
<br>
 rpi_ipa_deps = [<br>
     libcamera_private,<br>
-    dependency('boost'),<br>
     libatomic,<br>
 ]<br>
<br>
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp<br>
index f8d37b876c54..952a6ace2911 100644<br>
--- a/src/ipa/raspberrypi/raspberrypi.cpp<br>
+++ b/src/ipa/raspberrypi/raspberrypi.cpp<br>
@@ -7,6 +7,7 @@<br>
<br>
 #include <algorithm><br>
 #include <array><br>
+#include <cstring><br></blockquote><div><br></div><div>Looks unrelated to this work.</div><div>I'm ok to have it in this patch, but perhaps a comment in the commit message saying</div><div>it's a drive-by?</div><div><br></div><div>Regards,</div><div>Naush</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
 #include <fcntl.h><br>
 #include <math.h><br>
 #include <stdint.h><br>
-- <br>
2.25.1<br>
<br>
</blockquote></div></div>