<div dir="ltr"><div dir="ltr">Hi Laurent,<div><br></div><div>Thank you for the update.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 27 Jul 2022 at 18:43, Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com">laurent.pinchart@ideasonboard.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">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>
Tested-by: Naushir Patuck <<a href="mailto:naush@raspberrypi.com" target="_blank">naush@raspberrypi.com</a>><br></blockquote><div><br></div><div>Reviewed-by: Naushir Patuck <<a href="mailto:naush@raspberrypi.com">naush@raspberrypi.com</a>></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">
---<br>
Changes since v7:<br>
<br>
- Guard against invalid number of entries or invalid entries in<br>
  Pwl::read()<br>
- Don't use default value for reference_Y and reference_lux in lux.cpp<br>
<br>
Changes since v6:<br>
<br>
- Propagate tuning data read errors<br>
---<br>
 README.rst                                    |   6 -<br>
 src/ipa/raspberrypi/controller/algorithm.cpp  |   2 +-<br>
 src/ipa/raspberrypi/controller/algorithm.h    |   6 +-<br>
 src/ipa/raspberrypi/controller/controller.cpp |  27 ++--<br>
 src/ipa/raspberrypi/controller/pwl.cpp        |  27 ++--<br>
 src/ipa/raspberrypi/controller/pwl.h          |   4 +-<br>
 src/ipa/raspberrypi/controller/rpi/agc.cpp    | 136 ++++++++++--------<br>
 src/ipa/raspberrypi/controller/rpi/agc.h      |  10 +-<br>
 src/ipa/raspberrypi/controller/rpi/alsc.cpp   | 105 +++++++-------<br>
 src/ipa/raspberrypi/controller/rpi/alsc.h     |   2 +-<br>
 src/ipa/raspberrypi/controller/rpi/awb.cpp    | 134 ++++++++++-------<br>
 src/ipa/raspberrypi/controller/rpi/awb.h      |   8 +-<br>
 .../controller/rpi/black_level.cpp            |  12 +-<br>
 .../raspberrypi/controller/rpi/black_level.h  |   2 +-<br>
 src/ipa/raspberrypi/controller/rpi/ccm.cpp    |  47 +++---<br>
 src/ipa/raspberrypi/controller/rpi/ccm.h      |   4 +-<br>
 .../raspberrypi/controller/rpi/contrast.cpp   |  28 ++--<br>
 src/ipa/raspberrypi/controller/rpi/contrast.h |   2 +-<br>
 src/ipa/raspberrypi/controller/rpi/dpc.cpp    |   7 +-<br>
 src/ipa/raspberrypi/controller/rpi/dpc.h      |   2 +-<br>
 src/ipa/raspberrypi/controller/rpi/geq.cpp    |  10 +-<br>
 src/ipa/raspberrypi/controller/rpi/geq.h      |   2 +-<br>
 src/ipa/raspberrypi/controller/rpi/lux.cpp    |  30 +++-<br>
 src/ipa/raspberrypi/controller/rpi/lux.h      |   2 +-<br>
 src/ipa/raspberrypi/controller/rpi/noise.cpp  |  14 +-<br>
 src/ipa/raspberrypi/controller/rpi/noise.h    |   2 +-<br>
 src/ipa/raspberrypi/controller/rpi/sdn.cpp    |   6 +-<br>
 src/ipa/raspberrypi/controller/rpi/sdn.h      |   2 +-<br>
 .../raspberrypi/controller/rpi/sharpen.cpp    |   8 +-<br>
 src/ipa/raspberrypi/controller/rpi/sharpen.h  |   2 +-<br>
 src/ipa/raspberrypi/meson.build               |   1 -<br>
 src/ipa/raspberrypi/raspberrypi.cpp           |   1 +<br>
 32 files changed, 374 insertions(+), 277 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 d73cb36fe2d6..6d91ee292bd1 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>
-int Algorithm::read([[maybe_unused]] boost::property_tree::ptree const &params)<br>
+int Algorithm::read([[maybe_unused]] const libcamera::YamlObject &params)<br>
 {<br>
        return 0;<br>
 }<br>
diff --git a/src/ipa/raspberrypi/controller/algorithm.h b/src/ipa/raspberrypi/controller/algorithm.h<br>
index 0c5566fda874..cbbb13ba07a3 100644<br>
--- a/src/ipa/raspberrypi/controller/algorithm.h<br>
+++ b/src/ipa/raspberrypi/controller/algorithm.h<br>
@@ -15,10 +15,10 @@<br>
 #include <memory><br>
 #include <map><br>
<br>
+#include "libcamera/internal/yaml_parser.h"<br>
+<br>
 #include "controller.h"<br>
<br>
-#include <boost/property_tree/ptree.hpp><br>
-<br>
 namespace RPiController {<br>
<br>
 /* This defines the basic interface for all control algorithms. */<br>
@@ -35,7 +35,7 @@ public:<br>
        virtual bool isPaused() const { return paused_; }<br>
        virtual void pause() { paused_ = true; }<br>
        virtual void resume() { paused_ = false; }<br>
-       virtual int read(boost::property_tree::ptree const &params);<br>
+       virtual int read(const libcamera::YamlObject &params);<br>
        virtual void initialise();<br>
        virtual void switchMode(CameraMode const &cameraMode, Metadata *metadata);<br>
        virtual void prepare(Metadata *imageMetadata);<br>
diff --git a/src/ipa/raspberrypi/controller/controller.cpp b/src/ipa/raspberrypi/controller/controller.cpp<br>
index d91ac90704cb..bceb62540dbd 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.h"<br>
 #include "controller.h"<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>
@@ -34,18 +36,25 @@ Controller::~Controller() {}<br>
<br>
 int Controller::read(char const *filename)<br>
 {<br>
-       boost::property_tree::ptree root;<br>
-       boost::property_tree::read_json(filename, root);<br>
-       for (auto const &keyAndValue : root) {<br>
-               Algorithm *algo = createAlgorithm(keyAndValue.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 -EINVAL;<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>
-                       int ret = algo->read(keyAndValue.second);<br>
+                       int ret = algo->read(value);<br>
                        if (ret)<br>
                                return ret;<br>
                        algorithms_.push_back(AlgorithmPtr(algo));<br>
                } else<br>
                        LOG(RPiController, Warning)<br>
-                               << "No algorithm found for \"" << keyAndValue.first << "\"";<br>
+                               << "No algorithm found for \"" << key << "\"";<br>
        }<br>
<br>
        return 0;<br>
diff --git a/src/ipa/raspberrypi/controller/pwl.cpp b/src/ipa/raspberrypi/controller/pwl.cpp<br>
index fde0b298c6ce..c59f5fa131e3 100644<br>
--- a/src/ipa/raspberrypi/controller/pwl.cpp<br>
+++ b/src/ipa/raspberrypi/controller/pwl.cpp<br>
@@ -12,16 +12,27 @@<br>
<br>
 using namespace RPiController;<br>
<br>
-int Pwl::read(boost::property_tree::ptree const &params)<br>
+int 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>
-               it++;<br>
-               double y = it->second.get_value<double>();<br>
-               points_.push_back(Point(x, y));<br>
+       if (!params.size() || params.size() % 2)<br>
+               return -EINVAL;<br>
+<br>
+       const auto &list = params.asList();<br>
+<br>
+       for (auto it = list.begin(); it != list.end(); it++) {<br>
+               auto x = it->get<double>();<br>
+               if (!x)<br>
+                       return -EINVAL;<br>
+               if (it != list.begin() && *x <= points_.back().x)<br>
+                       return -EINVAL;<br>
+<br>
+               auto y = (++it)->get<double>();<br>
+               if (!y)<br>
+                       return -EINVAL;<br>
+<br>
+               points_.push_back(Point(*x, *y));<br>
        }<br>
-       assert(points_.size() >= 2);<br>
+<br>
        return 0;<br>
 }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/pwl.h b/src/ipa/raspberrypi/controller/pwl.h<br>
index ef1cc2ed113a..546482cd04d7 100644<br>
--- a/src/ipa/raspberrypi/controller/pwl.h<br>
+++ b/src/ipa/raspberrypi/controller/pwl.h<br>
@@ -9,7 +9,7 @@<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>
@@ -57,7 +57,7 @@ public:<br>
        };<br>
        Pwl() {}<br>
        Pwl(std::vector<Point> const &points) : points_(points) {}<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int 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 7fd5d18b9a22..5037f9008117 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
@@ -31,67 +31,76 @@ LOG_DEFINE_CATEGORY(RPiAgc)<br>
<br>
 static constexpr unsigned int PipelineBits = 13; /* seems to be a 13-bit pipeline */<br>
<br>
-int AgcMeteringMode::read(boost::property_tree::ptree const &params)<br>
+int AgcMeteringMode::read(const libcamera::YamlObject &params)<br>
 {<br>
-       int num = 0;<br>
-<br>
-       for (auto &p : params.get_child("weights")) {<br>
-               if (num == AgcStatsSize) {<br>
-                       LOG(RPiAgc, Error) << "AgcMeteringMode: too many weights";<br>
-                       return -EINVAL;<br>
-               }<br>
-               weights[num++] = p.second.get_value<double>();<br>
-       }<br>
-<br>
-       if (num != AgcStatsSize) {<br>
-               LOG(RPiAgc, Error) << "AgcMeteringMode: insufficient weights";<br>
+       const YamlObject &yamlWeights = params["weights"];<br>
+       if (yamlWeights.size() != AgcStatsSize) {<br>
+               LOG(RPiAgc, Error) << "AgcMeteringMode: Incorrect number of weights";<br>
                return -EINVAL;<br>
        }<br>
<br>
+       unsigned int num = 0;<br>
+       for (const auto &p : yamlWeights.asList()) {<br>
+               auto value = p.get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+               weights[num++] = *value;<br>
+       }<br>
+<br>
        return 0;<br>
 }<br>
<br>
 static std::tuple<int, std::string><br>
-readMeteringModes(std::map<std::string, AgcMeteringMode> &meteringModes,<br>
-                 boost::property_tree::ptree const &params)<br>
+readMeteringModes(std::map<std::string, AgcMeteringMode> &metering_modes,<br>
+                 const libcamera::YamlObject &params)<br>
 {<br>
        std::string first;<br>
        int ret;<br>
<br>
-       for (auto &p : params) {<br>
+       for (const auto &[key, value] : params.asDict()) {<br>
                AgcMeteringMode meteringMode;<br>
-               ret = meteringMode.read(p.second);<br>
+               ret = meteringMode.read(value);<br>
                if (ret)<br>
                        return { ret, {} };<br>
<br>
-               meteringModes[p.first] = std::move(meteringMode);<br>
+               metering_modes[key] = std::move(meteringMode);<br>
                if (first.empty())<br>
-                       first = p.first;<br>
+                       first = key;<br>
        }<br>
<br>
        return { 0, first };<br>
 }<br>
<br>
 static int readList(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>
+               auto value = p.get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+               list.push_back(*value);<br>
+       }<br>
+<br>
        return list.size();<br>
 }<br>
<br>
 static int readList(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>
+               auto value = p.get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+               list.push_back(*value * 1us);<br>
+       }<br>
+<br>
        return list.size();<br>
 }<br>
<br>
-int AgcExposureMode::read(boost::property_tree::ptree const &params)<br>
+int AgcExposureMode::read(const libcamera::YamlObject &params)<br>
 {<br>
-       int numShutters = readList(shutter, params.get_child("shutter"));<br>
-       int numAgs = readList(gain, params.get_child("gain"));<br>
+       int numShutters = readList(shutter, params["shutter"]);<br>
+       int numAgs = readList(gain, params["gain"]);<br>
<br>
        if (numShutters < 2 || numAgs < 2) {<br>
                LOG(RPiAgc, Error)<br>
@@ -110,28 +119,28 @@ int AgcExposureMode::read(boost::property_tree::ptree const &params)<br>
<br>
 static std::tuple<int, std::string><br>
 readExposureModes(std::map<std::string, AgcExposureMode> &exposureModes,<br>
-                 boost::property_tree::ptree const &params)<br>
+                 const libcamera::YamlObject &params)<br>
 {<br>
        std::string first;<br>
        int ret;<br>
<br>
-       for (auto &p : params) {<br>
+       for (const auto &[key, value] : params.asDict()) {<br>
                AgcExposureMode exposureMode;<br>
-               ret = exposureMode.read(p.second);<br>
+               ret = exposureMode.read(value);<br>
                if (ret)<br>
                        return { ret, {} };<br>
<br>
-               exposureModes[p.first] = std::move(exposureMode);<br>
+               exposureModes[key] = std::move(exposureMode);<br>
                if (first.empty())<br>
-                       first = p.first;<br>
+                       first = key;<br>
        }<br>
<br>
        return { 0, first };<br>
 }<br>
<br>
-int AgcConstraint::read(boost::property_tree::ptree const &params)<br>
+int AgcConstraint::read(const libcamera::YamlObject &params)<br>
 {<br>
-       std::string boundString = params.get<std::string>("bound", "");<br>
+       std::string boundString = params["bound"].get<std::string>("");<br>
        transform(boundString.begin(), boundString.end(),<br>
                  boundString.begin(), ::toupper);<br>
        if (boundString != "UPPER" && boundString != "LOWER") {<br>
@@ -139,20 +148,29 @@ int AgcConstraint::read(boost::property_tree::ptree const &params)<br>
                return -EINVAL;<br>
        }<br>
        bound = boundString == "UPPER" ? Bound::UPPER : Bound::LOWER;<br>
-       qLo = params.get<double>("q_lo");<br>
-       qHi = params.get<double>("q_hi");<br>
-       return yTarget.read(params.get_child("y_target"));<br>
+<br>
+       auto value = params["q_lo"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       qLo = *value;<br>
+<br>
+       value = params["q_hi"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       qHi = *value;<br>
+<br>
+       return yTarget.read(params["y_target"]);<br>
 }<br>
<br>
 static std::tuple<int, AgcConstraintMode><br>
-readConstraintMode(boost::property_tree::ptree const &params)<br>
+readConstraintMode(const libcamera::YamlObject &params)<br>
 {<br>
        AgcConstraintMode mode;<br>
        int ret;<br>
<br>
-       for (auto &p : params) {<br>
+       for (const auto &p : params.asList()) {<br>
                AgcConstraint constraint;<br>
-               ret = constraint.read(p.second);<br>
+               ret = constraint.read(p);<br>
                if (ret)<br>
                        return { ret, {} };<br>
<br>
@@ -164,53 +182,55 @@ readConstraintMode(boost::property_tree::ptree const &params)<br>
<br>
 static std::tuple<int, std::string><br>
 readConstraintModes(std::map<std::string, AgcConstraintMode> &constraintModes,<br>
-                   boost::property_tree::ptree const &params)<br>
+                   const libcamera::YamlObject &params)<br>
 {<br>
        std::string first;<br>
        int ret;<br>
<br>
-       for (auto &p : params) {<br>
-               std::tie(ret, constraintModes[p.first]) = readConstraintMode(p.second);<br>
+       for (const auto &[key, value] : params.asDict()) {<br>
+               std::tie(ret, constraintModes[key]) = readConstraintMode(value);<br>
                if (ret)<br>
                        return { ret, {} };<br>
<br>
                if (first.empty())<br>
-                       first = p.first;<br>
+                       first = key;<br>
        }<br>
<br>
        return { 0, first };<br>
 }<br>
<br>
-int AgcConfig::read(boost::property_tree::ptree const &params)<br>
+int AgcConfig::read(const libcamera::YamlObject &params)<br>
 {<br>
        LOG(RPiAgc, Debug) << "AgcConfig";<br>
        int ret;<br>
<br>
        std::tie(ret, defaultMeteringMode) =<br>
-               readMeteringModes(meteringModes, params.get_child("metering_modes"));<br>
+               readMeteringModes(meteringModes, params["metering_modes"]);<br>
        if (ret)<br>
                return ret;<br>
        std::tie(ret, defaultExposureMode) =<br>
-               readExposureModes(exposureModes, params.get_child("exposure_modes"));<br>
+               readExposureModes(exposureModes, params["exposure_modes"]);<br>
        if (ret)<br>
                return ret;<br>
        std::tie(ret, defaultConstraintMode) =<br>
-               readConstraintModes(constraintModes, params.get_child("constraint_modes"));<br>
+               readConstraintModes(constraintModes, params["constraint_modes"]);<br>
        if (ret)<br>
                return ret;<br>
<br>
-       ret = yTarget.read(params.get_child("y_target"));<br>
+       ret = yTarget.read(params["y_target"]);<br>
        if (ret)<br>
                return ret;<br>
<br>
-       speed = params.get<double>("speed", 0.2);<br>
-       startupFrames = params.get<uint16_t>("startup_frames", 10);<br>
-       convergenceFrames = params.get<unsigned int>("convergence_frames", 6);<br>
-       fastReduceThreshold = params.get<double>("fast_reduce_threshold", 0.4);<br>
-       baseEv = params.get<double>("base_ev", 1.0);<br>
+       speed = params["speed"].get<double>(0.2);<br>
+       startupFrames = params["startup_frames"].get<uint16_t>(10);<br>
+       convergenceFrames = params["convergence_frames"].get<unsigned int>(6);<br>
+       fastReduceThreshold = params["fast_reduce_threshold"].get<double>(0.4);<br>
+       baseEv = params["base_ev"].get<double>(1.0);<br>
+<br>
        /* Start with quite a low value as ramping up is easier than ramping down. */<br>
-       defaultExposureTime = params.get<double>("default_exposure_time", 1000) * 1us;<br>
-       defaultAnalogueGain = params.get<double>("default_analogueGain", 1.0);<br>
+       defaultExposureTime = params["default_exposure_time"].get<double>(1000) * 1us;<br>
+       defaultAnalogueGain = params["default_analogue_gain"].get<double>(1.0);<br>
+<br>
        return 0;<br>
 }<br>
<br>
@@ -242,7 +262,7 @@ char const *Agc::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Agc::read(boost::property_tree::ptree const &params)<br>
+int Agc::read(const libcamera::YamlObject &params)<br>
 {<br>
        LOG(RPiAgc, Debug) << "Agc";<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.h b/src/ipa/raspberrypi/controller/rpi/agc.h<br>
index 1351b0ee079c..6d6b0e5ad857 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/agc.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/agc.h<br>
@@ -28,13 +28,13 @@ namespace RPiController {<br>
<br>
 struct AgcMeteringMode {<br>
        double weights[AgcStatsSize];<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int read(const libcamera::YamlObject &params);<br>
 };<br>
<br>
 struct AgcExposureMode {<br>
        std::vector<libcamera::utils::Duration> shutter;<br>
        std::vector<double> gain;<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int read(const libcamera::YamlObject &params);<br>
 };<br>
<br>
 struct AgcConstraint {<br>
@@ -43,13 +43,13 @@ struct AgcConstraint {<br>
        double qLo;<br>
        double qHi;<br>
        Pwl yTarget;<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int read(const libcamera::YamlObject &params);<br>
 };<br>
<br>
 typedef std::vector<AgcConstraint> AgcConstraintMode;<br>
<br>
 struct AgcConfig {<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int read(const libcamera::YamlObject &params);<br>
        std::map<std::string, AgcMeteringMode> meteringModes;<br>
        std::map<std::string, AgcExposureMode> exposureModes;<br>
        std::map<std::string, AgcConstraintMode> constraintModes;<br>
@@ -74,7 +74,7 @@ class Agc : public AgcAlgorithm<br>
 public:<br>
        Agc(Controller *controller);<br>
        char const *name() const override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int 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 49aaf6b74603..a4afaf841c41 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,15 +51,15 @@ char const *Alsc::name() const<br>
        return NAME;<br>
 }<br>
<br>
-static int generateLut(double *lut, boost::property_tree::ptree const &params)<br>
+static int generateLut(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>
                LOG(RPiAlsc, Error) << "corner_strength must be > 1.0";<br>
                return -EINVAL;<br>
        }<br>
<br>
-       double asymmetry = params.get<double>("asymmetry", 1.0);<br>
+       double asymmetry = params["asymmetry"].get<double>(1.0);<br>
        if (asymmetry < 0) {<br>
                LOG(RPiAlsc, Error) << "asymmetry must be >= 0";<br>
                return -EINVAL;<br>
@@ -80,34 +81,35 @@ static int generateLut(double *lut, boost::property_tree::ptree const &params)<br>
        return 0;<br>
 }<br>
<br>
-static int readLut(double *lut, boost::property_tree::ptree const &params)<br>
+static int readLut(double *lut, const libcamera::YamlObject &params)<br>
 {<br>
-       int num = 0;<br>
-       const int maxNum = XY;<br>
+       if (params.size() != XY) {<br>
+               LOG(RPiAlsc, Error) << "Invalid number of entries in LSC table";<br>
+               return -EINVAL;<br>
+       }<br>
<br>
-       for (auto &p : params) {<br>
-               if (num == maxNum) {<br>
-                       LOG(RPiAlsc, Error) << "Too many entries in LSC table";<br>
+       int num = 0;<br>
+       for (const auto &p : params.asList()) {<br>
+               auto value = p.get<double>();<br>
+               if (!value)<br>
                        return -EINVAL;<br>
-               }<br>
-               lut[num++] = p.second.get_value<double>();<br>
+               lut[num++] = *value;<br>
        }<br>
<br>
-       if (num < maxNum) {<br>
-               LOG(RPiAlsc, Error) << "Too few entries in LSC table";<br>
-               return -EINVAL;<br>
-       }<br>
        return 0;<br>
 }<br>
<br>
 static int readCalibrations(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 lastCt = 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>
+                       auto value = p["ct"].get<double>();<br>
+                       if (!value)<br>
+                               return -EINVAL;<br>
+                       double ct = *value;<br>
                        if (ct <= lastCt) {<br>
                                LOG(RPiAlsc, Error)<br>
                                        << "Entries in " << name << " must be in increasing ct order";<br>
@@ -115,23 +117,23 @@ static int readCalibrations(std::vector<AlscCalibration> &calibrations,<br>
                        }<br>
                        AlscCalibration calibration;<br>
                        calibration.ct = lastCt = ct;<br>
-                       boost::property_tree::ptree const &table =<br>
-                               p.second.get_child("table");<br>
+<br>
+                       const libcamera::YamlObject &table = p["table"];<br>
+                       if (table.size() != XY) {<br>
+                               LOG(RPiAlsc, Error)<br>
+                                       << "Incorrect number of values for ct "<br>
+                                       << ct << " in " << name;<br>
+                               return -EINVAL;<br>
+                       }<br>
+<br>
                        int num = 0;<br>
-                       for (auto it = table.begin(); it != table.end(); it++) {<br>
-                               if (num == XY) {<br>
-                                       LOG(RPiAlsc, Error)<br>
-                                               << "Too many values for ct " << ct << " in " << name;<br>
+                       for (const auto &elem : table.asList()) {<br>
+                               value = elem.get<double>();<br>
+                               if (!value)<br>
                                        return -EINVAL;<br>
-                               }<br>
-                               calibration.table[num++] =<br>
-                                       it->second.get_value<double>();<br>
-                       }<br>
-                       if (num != XY) {<br>
-                               LOG(RPiAlsc, Error)<br>
-                                       << "Too few values for ct " << ct << " in " << name;<br>
-                               return -EINVAL;<br>
+                               calibration.table[num++] = *value;<br>
                        }<br>
+<br>
                        calibrations.push_back(calibration);<br>
                        LOG(RPiAlsc, Debug)<br>
                                << "Read " << name << " calibration for ct " << ct;<br>
@@ -140,30 +142,29 @@ static int readCalibrations(std::vector<AlscCalibration> &calibrations,<br>
        return 0;<br>
 }<br>
<br>
-int Alsc::read(boost::property_tree::ptree const &params)<br>
+int Alsc::read(const libcamera::YamlObject &params)<br>
 {<br>
-       config_.framePeriod = params.get<uint16_t>("frame_period", 12);<br>
-       config_.startupFrames = 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_.sigmaCr = params.get<double>("sigma_Cr", sigma);<br>
-       config_.sigmaCb = params.get<double>("sigma_Cb", sigma);<br>
-       config_.minCount = params.get<double>("min_count", 10.0);<br>
-       config_.minG = params.get<uint16_t>("min_G", 50);<br>
-       config_.omega = params.get<double>("omega", 1.3);<br>
-       config_.nIter = params.get<uint32_t>("n_iter", X + Y);<br>
+       config_.framePeriod = params["frame_period"].get<uint16_t>(12);<br>
+       config_.startupFrames = 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_.sigmaCr = params["sigma_Cr"].get<double>(sigma);<br>
+       config_.sigmaCb = params["sigma_Cb"].get<double>(sigma);<br>
+       config_.minCount = params["min_count"].get<double>(10.0);<br>
+       config_.minG = params["min_G"].get<uint16_t>(50);<br>
+       config_.omega = params["omega"].get<double>(1.3);<br>
+       config_.nIter = params["n_iter"].get<uint32_t>(X + Y);<br>
        config_.luminanceStrength =<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_.luminanceLut[i] = 1.0;<br>
<br>
        int ret = 0;<br>
<br>
-       if (params.get_child_optional("corner_strength"))<br>
+       if (params.contains("corner_strength"))<br>
                ret = generateLut(config_.luminanceLut, params);<br>
-       else if (params.get_child_optional("luminance_lut"))<br>
-               ret = readLut(config_.luminanceLut,<br>
-                             params.get_child("luminance_lut"));<br>
+       else if (params.contains("luminance_lut"))<br>
+               ret = readLut(config_.luminanceLut, params["luminance_lut"]);<br>
        else<br>
                LOG(RPiAlsc, Warning)<br>
                        << "no luminance table - assume unity everywhere";<br>
@@ -177,9 +178,9 @@ int Alsc::read(boost::property_tree::ptree const &params)<br>
        if (ret)<br>
                return ret;<br>
<br>
-       config_.defaultCt = params.get<double>("default_ct", 4500.0);<br>
-       config_.threshold = params.get<double>("threshold", 1e-3);<br>
-       config_.lambdaBound = params.get<double>("lambda_bound", 0.05);<br>
+       config_.defaultCt = params["default_ct"].get<double>(4500.0);<br>
+       config_.threshold = params["threshold"].get<double>(1e-3);<br>
+       config_.lambdaBound = params["lambda_bound"].get<double>(0.05);<br>
<br>
        return 0;<br>
 }<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.h b/src/ipa/raspberrypi/controller/rpi/alsc.h<br>
index 773fd338ea8e..a858ef5a6551 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/alsc.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/alsc.h<br>
@@ -52,7 +52,7 @@ public:<br>
        char const *name() const override;<br>
        void initialise() override;<br>
        void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void prepare(Metadata *imageMetadata) override;<br>
        void process(StatisticsPtr &stats, Metadata *imageMetadata) override;<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp<br>
index d8c9665445f9..a16e04a07ff8 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>
@@ -26,62 +28,87 @@ static constexpr unsigned int AwbStatsSizeY = DEFAULT_AWB_REGIONS_Y;<br>
  * elsewhere (ALSC and AGC).<br>
  */<br>
<br>
-int AwbMode::read(boost::property_tree::ptree const &params)<br>
+int AwbMode::read(const libcamera::YamlObject &params)<br>
 {<br>
-       ctLo = params.get<double>("lo");<br>
-       ctHi = params.get<double>("hi");<br>
+       auto value = params["lo"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       ctLo = *value;<br>
+<br>
+       value = params["hi"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       ctHi = *value;<br>
+<br>
        return 0;<br>
 }<br>
<br>
-int AwbPrior::read(boost::property_tree::ptree const &params)<br>
+int AwbPrior::read(const libcamera::YamlObject &params)<br>
 {<br>
-       lux = params.get<double>("lux");<br>
-       return prior.read(params.get_child("prior"));<br>
+       auto value = params["lux"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       lux = *value;<br>
+<br>
+       return prior.read(params["prior"]);<br>
 }<br>
<br>
-static int readCtCurve(Pwl &ctR, Pwl &ctB,<br>
-                      boost::property_tree::ptree const &params)<br>
+static int readCtCurve(Pwl &ctR, Pwl &ctB, const libcamera::YamlObject &params)<br>
 {<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 != ctR.domain().end);<br>
-               if (++it == params.end()) {<br>
-                       LOG(RPiAwb, Error) << "AwbConfig: incomplete CT curve entry";<br>
-                       return -EINVAL;<br>
-               }<br>
-               ctR.append(ct, it->second.get_value<double>());<br>
-               if (++it == params.end()) {<br>
-                       LOG(RPiAwb, Error) << "AwbConfig: incomplete CT curve entry";<br>
-                       return -EINVAL;<br>
-               }<br>
-               ctB.append(ct, it->second.get_value<double>());<br>
-               num++;<br>
+       if (params.size() % 3) {<br>
+               LOG(RPiAwb, Error) << "AwbConfig: incomplete CT curve entry";<br>
+               return -EINVAL;<br>
        }<br>
-       if (num < 2) {<br>
+<br>
+       if (params.size() < 6) {<br>
                LOG(RPiAwb, Error) << "AwbConfig: insufficient points in CT curve";<br>
                return -EINVAL;<br>
        }<br>
+<br>
+       const auto &list = params.asList();<br>
+<br>
+       for (auto it = list.begin(); it != list.end(); it++) {<br>
+               auto value = it->get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+               double ct = *value;<br>
+<br>
+               assert(it == list.begin() || ct != ctR.domain().end);<br>
+<br>
+               value = (++it)->get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+               ctR.append(ct, *value);<br>
+<br>
+               value = (++it)->get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+               ctB.append(ct, *value);<br>
+       }<br>
+<br>
        return 0;<br>
 }<br>
<br>
-int AwbConfig::read(boost::property_tree::ptree const &params)<br>
+int AwbConfig::read(const libcamera::YamlObject &params)<br>
 {<br>
        int ret;<br>
-       bayes = params.get<int>("bayes", 1);<br>
-       framePeriod = params.get<uint16_t>("framePeriod", 10);<br>
-       startupFrames = params.get<uint16_t>("startupFrames", 10);<br>
-       convergenceFrames = params.get<unsigned int>("convergence_frames", 3);<br>
-       speed = params.get<double>("speed", 0.05);<br>
-       if (params.get_child_optional("ct_curve")) {<br>
-               ret = readCtCurve(ctR, ctB, params.get_child("ct_curve"));<br>
+<br>
+       bayes = params["bayes"].get<int>(1);<br>
+       framePeriod = params["frame_period"].get<uint16_t>(10);<br>
+       startupFrames = params["startup_frames"].get<uint16_t>(10);<br>
+       convergenceFrames = params["convergence_frames"].get<unsigned int>(3);<br>
+       speed = params["speed"].get<double>(0.05);<br>
+<br>
+       if (params.contains("ct_curve")) {<br>
+               ret = readCtCurve(ctR, ctB, params["ct_curve"]);<br>
                if (ret)<br>
                        return ret;<br>
        }<br>
-       if (params.get_child_optional("priors")) {<br>
-               for (auto &p : params.get_child("priors")) {<br>
+<br>
+       if (params.contains("priors")) {<br>
+               for (const auto &p : params["priors"].asList()) {<br>
                        AwbPrior prior;<br>
-                       ret = prior.read(p.second);<br>
+                       ret = prior.read(p);<br>
                        if (ret)<br>
                                return ret;<br>
                        if (!priors.empty() && prior.lux <= priors.back().lux) {<br>
@@ -95,32 +122,35 @@ int AwbConfig::read(boost::property_tree::ptree const &params)<br>
                        return ret;<br>
                }<br>
        }<br>
-       if (params.get_child_optional("modes")) {<br>
-               for (auto &p : params.get_child("modes")) {<br>
-                       ret = modes[p.first].read(p.second);<br>
+       if (params.contains("modes")) {<br>
+               for (const auto &[key, value] : params["modes"].asDict()) {<br>
+                       ret = modes[key].read(value);<br>
                        if (ret)<br>
                                return ret;<br>
                        if (defaultMode == nullptr)<br>
-                               defaultMode = &modes[p.first];<br>
+                               defaultMode = &modes[key];<br>
                }<br>
                if (defaultMode == nullptr) {<br>
                        LOG(RPiAwb, Error) << "AwbConfig: no AWB modes configured";<br>
                        return -EINVAL;<br>
                }<br>
        }<br>
-       minPixels = params.get<double>("min_pixels", 16.0);<br>
-       minG = params.get<uint16_t>("min_G", 32);<br>
-       minRegions = params.get<uint32_t>("min_regions", 10);<br>
-       deltaLimit = params.get<double>("delta_limit", 0.2);<br>
-       coarseStep = params.get<double>("coarse_step", 0.2);<br>
-       transversePos = params.get<double>("transverse_pos", 0.01);<br>
-       transverseNeg = params.get<double>("transverse_neg", 0.01);<br>
+<br>
+       minPixels = params["min_pixels"].get<double>(16.0);<br>
+       minG = params["min_G"].get<uint16_t>(32);<br>
+       minRegions = params["min_regions"].get<uint32_t>(10);<br>
+       deltaLimit = params["delta_limit"].get<double>(0.2);<br>
+       coarseStep = params["coarse_step"].get<double>(0.2);<br>
+       transversePos = params["transverse_pos"].get<double>(0.01);<br>
+       transverseNeg = params["transverse_neg"].get<double>(0.01);<br>
        if (transversePos <= 0 || transverseNeg <= 0) {<br>
                LOG(RPiAwb, Error) << "AwbConfig: transverse_pos/neg must be > 0";<br>
                return -EINVAL;<br>
        }<br>
-       sensitivityR = params.get<double>("sensitivity_r", 1.0);<br>
-       sensitivityB = params.get<double>("sensitivity_b", 1.0);<br>
+<br>
+       sensitivityR = params["sensitivity_r"].get<double>(1.0);<br>
+       sensitivityB = params["sensitivity_b"].get<double>(1.0);<br>
+<br>
        if (bayes) {<br>
                if (ctR.empty() || ctB.empty() || priors.empty() ||<br>
                    defaultMode == nullptr) {<br>
@@ -129,9 +159,9 @@ int AwbConfig::read(boost::property_tree::ptree const &params)<br>
                        bayes = false;<br>
                }<br>
        }<br>
-       fast = params.get<int>("fast", bayes); /* default to fast for Bayesian, otherwise slow */<br>
-       whitepointR = params.get<double>("whitepoint_r", 0.0);<br>
-       whitepointB = params.get<double>("whitepoint_b", 0.0);<br>
+       fast = params[fast].get<int>(bayes); /* default to fast for Bayesian, otherwise slow */<br>
+       whitepointR = params["whitepoint_r"].get<double>(0.0);<br>
+       whitepointB = params["whitepoint_b"].get<double>(0.0);<br>
        if (bayes == false)<br>
                sensitivityR = sensitivityB = 1.0; /* nor do sensitivities make any sense */<br>
        return 0;<br>
@@ -162,7 +192,7 @@ char const *Awb::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Awb::read(boost::property_tree::ptree const &params)<br>
+int Awb::read(const libcamera::YamlObject &params)<br>
 {<br>
        return config_.read(params);<br>
 }<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.h b/src/ipa/raspberrypi/controller/rpi/awb.h<br>
index 9c5cf4eaaaaf..cb4cfd1be2e8 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/awb.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/awb.h<br>
@@ -19,20 +19,20 @@ namespace RPiController {<br>
 /* Control algorithm to perform AWB calculations. */<br>
<br>
 struct AwbMode {<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int read(const libcamera::YamlObject &params);<br>
        double ctLo; /* low CT value for search */<br>
        double ctHi; /* high CT value for search */<br>
 };<br>
<br>
 struct AwbPrior {<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int 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() : defaultMode(nullptr) {}<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int read(const libcamera::YamlObject &params);<br>
        /* Only repeat the AWB calculation every "this many" frames */<br>
        uint16_t framePeriod;<br>
        /* number of initial frames for which speed taken as 1.0 (maximum) */<br>
@@ -90,7 +90,7 @@ public:<br>
        ~Awb();<br>
        char const *name() const override;<br>
        void initialise() override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int 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 749fcd7cdf8c..85baec3fcbdd 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>
-int BlackLevel::read(boost::property_tree::ptree const &params)<br>
+int BlackLevel::read(const libcamera::YamlObject &params)<br>
 {<br>
-       uint16_t blackLevel = params.get<uint16_t>(<br>
-               "black_level", 4096); /* 64 in 10 bits scaled to 16 bits */<br>
-       blackLevelR_ = params.get<uint16_t>("black_level_r", blackLevel);<br>
-       blackLevelG_ = params.get<uint16_t>("black_level_g", blackLevel);<br>
-       blackLevelB_ = params.get<uint16_t>("black_level_b", blackLevel);<br>
+       /* 64 in 10 bits scaled to 16 bits */<br>
+       uint16_t blackLevel = params["black_level"].get<uint16_t>(4096);<br>
+       blackLevelR_ = params["black_level_r"].get<uint16_t>(blackLevel);<br>
+       blackLevelG_ = params["black_level_g"].get<uint16_t>(blackLevel);<br>
+       blackLevelB_ = params["black_level_b"].get<uint16_t>(blackLevel);<br>
        LOG(RPiBlackLevel, Debug)<br>
                << " Read black levels red " << blackLevelR_<br>
                << " green " << blackLevelG_<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/black_level.h b/src/ipa/raspberrypi/controller/rpi/black_level.h<br>
index 6ec8c4f9ba8f..2403f7f77625 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/black_level.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/black_level.h<br>
@@ -18,7 +18,7 @@ class BlackLevel : public Algorithm<br>
 public:<br>
        BlackLevel(Controller *controller);<br>
        char const *name() const override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void prepare(Metadata *imageMetadata) 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 9588e94adeb1..2e2e66647e86 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/ccm.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/ccm.cpp<br>
@@ -39,21 +39,22 @@ 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>
-int Matrix::read(boost::property_tree::ptree const &params)<br>
+int 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>
-                       LOG(RPiCcm, Error) << "Too many values in CCM";<br>
-                       return -EINVAL;<br>
-               }<br>
-               *ptr++ = it->second.get_value<double>();<br>
-       }<br>
-       if (n < 9) {<br>
-               LOG(RPiCcm, Error) << "Too few values in CCM";<br>
+<br>
+       if (params.size() != 9) {<br>
+               LOG(RPiCcm, Error) << "Wrong number of values in CCM";<br>
                return -EINVAL;<br>
        }<br>
+<br>
+       for (const auto &param : params.asList()) {<br>
+               auto value = param.get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+               *ptr++ = *value;<br>
+       }<br>
+<br>
        return 0;<br>
 }<br>
<br>
@@ -65,27 +66,33 @@ char const *Ccm::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Ccm::read(boost::property_tree::ptree const &params)<br>
+int Ccm::read(const libcamera::YamlObject &params)<br>
 {<br>
        int ret;<br>
<br>
-       if (params.get_child_optional("saturation")) {<br>
-               ret = config_.saturation.read(params.get_child("saturation"));<br>
+       if (params.contains("saturation")) {<br>
+               ret = config_.saturation.read(params["saturation"]);<br>
                if (ret)<br>
                        return ret;<br>
        }<br>
<br>
-       for (auto &p : params.get_child("ccms")) {<br>
+       for (auto &p : params["ccms"].asList()) {<br>
+               auto value = p["ct"].get<double>();<br>
+               if (!value)<br>
+                       return -EINVAL;<br>
+<br>
                CtCcm ctCcm;<br>
-               ctCcm.ct = p.second.get<double>("ct");<br>
-               ret = ctCcm.ccm.read(p.second.get_child("ccm"));<br>
+               ctCcm.ct = *value;<br>
+               ret = ctCcm.ccm.read(p["ccm"]);<br>
                if (ret)<br>
                        return ret;<br>
-               if (!config_.ccms.empty() &&<br>
-                   ctCcm.ct <= config_.ccms.back().ct) {<br>
-                       LOG(RPiCcm, Error) << "CCM not in increasing colour temperature order";<br>
+<br>
+               if (!config_.ccms.empty() && ctCcm.ct <= config_.ccms.back().ct) {<br>
+                       LOG(RPiCcm, Error)<br>
+                               << "CCM not in increasing colour temperature order";<br>
                        return -EINVAL;<br>
                }<br>
+<br>
                config_.ccms.push_back(std::move(ctCcm));<br>
        }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/ccm.h b/src/ipa/raspberrypi/controller/rpi/ccm.h<br>
index 6b65c7aea8a6..286d0b33e72f 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/ccm.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/ccm.h<br>
@@ -20,7 +20,7 @@ struct Matrix {<br>
               double m6, double m7, double m8);<br>
        Matrix();<br>
        double m[3][3];<br>
-       int read(boost::property_tree::ptree const &params);<br>
+       int 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>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void setSaturation(double saturation) override;<br>
        void initialise() override;<br>
        void prepare(Metadata *imageMetadata) override;<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.cpp b/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
index d76dc43b837f..5b37edcbd46a 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
@@ -38,21 +38,21 @@ char const *Contrast::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Contrast::read(boost::property_tree::ptree const &params)<br>
+int Contrast::read(const libcamera::YamlObject &params)<br>
 {<br>
-       /* enable adaptive enhancement by default */<br>
-       config_.ceEnable = params.get<int>("ce_enable", 1);<br>
-       /* the point near the bottom of the histogram to move */<br>
-       config_.loHistogram = params.get<double>("lo_histogram", 0.01);<br>
-       /* where in the range to try and move it to */<br>
-       config_.loLevel = params.get<double>("lo_level", 0.015);<br>
-       /* but don't move by more than this */<br>
-       config_.loMax = params.get<double>("lo_max", 500);<br>
-       /* equivalent values for the top of the histogram... */<br>
-       config_.hiHistogram = params.get<double>("hi_histogram", 0.95);<br>
-       config_.hiLevel = params.get<double>("hi_level", 0.95);<br>
-       config_.hiMax = params.get<double>("hi_max", 2000);<br>
-       return config_.gammaCurve.read(params.get_child("gamma_curve"));<br>
+       // enable adaptive enhancement by default<br>
+       config_.ceEnable = params["ce_enable"].get<int>(1);<br>
+       // the point near the bottom of the histogram to move<br>
+       config_.loHistogram = params["lo_histogram"].get<double>(0.01);<br>
+       // where in the range to try and move it to<br>
+       config_.loLevel = params["lo_level"].get<double>(0.015);<br>
+       // but don't move by more than this<br>
+       config_.loMax = params["lo_max"].get<double>(500);<br>
+       // equivalent values for the top of the histogram...<br>
+       config_.hiHistogram = params["hi_histogram"].get<double>(0.95);<br>
+       config_.hiLevel = params["hi_level"].get<double>(0.95);<br>
+       config_.hiMax = params["hi_max"].get<double>(2000);<br>
+       return config_.gammaCurve.read(params["gamma_curve"]);<br>
 }<br>
<br>
 void Contrast::setBrightness(double brightness)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.h b/src/ipa/raspberrypi/controller/rpi/contrast.h<br>
index 5c3d2f56b310..c68adbc9e463 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/contrast.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/contrast.h<br>
@@ -34,7 +34,7 @@ class Contrast : public ContrastAlgorithm<br>
 public:<br>
        Contrast(Controller *controller = NULL);<br>
        char const *name() const override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int 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 def39bb7416a..be3871dffe28 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/dpc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/dpc.cpp<br>
@@ -31,13 +31,14 @@ char const *Dpc::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Dpc::read(boost::property_tree::ptree const &params)<br>
+int 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>
-               LOG(RPiDpc, Error) << "bad strength value";<br>
+               LOG(RPiDpc, Error) << "Bad strength value";<br>
                return -EINVAL;<br>
        }<br>
+<br>
        return 0;<br>
 }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/dpc.h b/src/ipa/raspberrypi/controller/rpi/dpc.h<br>
index 2bb6cef565a7..84a05604394d 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/dpc.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/dpc.h<br>
@@ -22,7 +22,7 @@ class Dpc : public Algorithm<br>
 public:<br>
        Dpc(Controller *controller);<br>
        char const *name() const override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void prepare(Metadata *imageMetadata) 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 106f0a40dfc1..510870e9edbf 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/geq.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/geq.cpp<br>
@@ -35,17 +35,17 @@ char const *Geq::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Geq::read(boost::property_tree::ptree const &params)<br>
+int 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>
                LOG(RPiGeq, Error) << "Bad slope value";<br>
                return -EINVAL;<br>
        }<br>
<br>
-       if (params.get_child_optional("strength")) {<br>
-               int ret = config_.strength.read(params.get_child("strength"));<br>
+       if (params.contains("strength")) {<br>
+               int ret = config_.strength.read(params["strength"]);<br>
                if (ret)<br>
                        return ret;<br>
        }<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/geq.h b/src/ipa/raspberrypi/controller/rpi/geq.h<br>
index 677a0510c6ac..ee3a52ff50f5 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/geq.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/geq.h<br>
@@ -24,7 +24,7 @@ class Geq : public Algorithm<br>
 public:<br>
        Geq(Controller *controller);<br>
        char const *name() const override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void prepare(Metadata *imageMetadata) 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 ca1e827191fd..9759186afacf 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/lux.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp<br>
@@ -38,14 +38,30 @@ char const *Lux::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Lux::read(boost::property_tree::ptree const &params)<br>
+int Lux::read(const libcamera::YamlObject &params)<br>
 {<br>
-       referenceShutterSpeed_ =<br>
-               params.get<double>("reference_shutter_speed") * 1.0us;<br>
-       referenceGain_ = params.get<double>("reference_gain");<br>
-       referenceAperture_ = params.get<double>("reference_aperture", 1.0);<br>
-       referenceY_ = params.get<double>("reference_Y");<br>
-       referenceLux_ = params.get<double>("reference_lux");<br>
+       auto value = params["reference_shutter_speed"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       referenceShutterSpeed_ = *value * 1.0us;<br>
+<br>
+       value = params["reference_gain"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       referenceGain_ = *value;<br>
+<br>
+       referenceAperture_ = params["reference_aperture"].get<double>(1.0);<br>
+<br>
+       value = params["reference_Y"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       referenceY_ = *value;<br>
+<br>
+       value = params["reference_lux"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       referenceLux_ = *value;<br>
+<br>
        currentAperture_ = referenceAperture_;<br>
        return 0;<br>
 }<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/lux.h b/src/ipa/raspberrypi/controller/rpi/lux.h<br>
index 6416dfb52553..89411a5432b4 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/lux.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/lux.h<br>
@@ -22,7 +22,7 @@ class Lux : public Algorithm<br>
 public:<br>
        Lux(Controller *controller);<br>
        char const *name() const override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void prepare(Metadata *imageMetadata) override;<br>
        void process(StatisticsPtr &stats, Metadata *imageMetadata) 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 74fa99bafe48..bcd8b9edaebe 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/noise.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/noise.cpp<br>
@@ -41,10 +41,18 @@ void Noise::switchMode(CameraMode const &cameraMode,<br>
        modeFactor_ = std::max(1.0, cameraMode.noiseFactor);<br>
 }<br>
<br>
-int Noise::read(boost::property_tree::ptree const &params)<br>
+int Noise::read(const libcamera::YamlObject &params)<br>
 {<br>
-       referenceConstant_ = params.get<double>("reference_constant");<br>
-       referenceSlope_ = params.get<double>("reference_slope");<br>
+       auto value = params["reference_constant"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       referenceConstant_ = *value;<br>
+<br>
+       value = params["reference_slope"].get<double>();<br>
+       if (!value)<br>
+               return -EINVAL;<br>
+       referenceSlope_ = *value;<br>
+<br>
        return 0;<br>
 }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/noise.h b/src/ipa/raspberrypi/controller/rpi/noise.h<br>
index b33a5fc75ec7..74c31e640c3f 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/noise.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/noise.h<br>
@@ -19,7 +19,7 @@ public:<br>
        Noise(Controller *controller);<br>
        char const *name() const override;<br>
        void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void prepare(Metadata *imageMetadata) 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 03d9f119a338..b6b662518f2c 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sdn.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sdn.cpp<br>
@@ -34,10 +34,10 @@ char const *Sdn::name() const<br>
        return NAME;<br>
 }<br>
<br>
-int Sdn::read(boost::property_tree::ptree const &params)<br>
+int 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>
        return 0;<br>
 }<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/sdn.h b/src/ipa/raspberrypi/controller/rpi/sdn.h<br>
index 4287ef08a79f..9dd73c388edb 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sdn.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sdn.h<br>
@@ -18,7 +18,7 @@ class Sdn : public DenoiseAlgorithm<br>
 public:<br>
        Sdn(Controller *controller = NULL);<br>
        char const *name() const override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void initialise() override;<br>
        void prepare(Metadata *imageMetadata) 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 9c4cffa4128c..4f6f020a417b 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 &cameraMode,<br>
        modeFactor_ = std::max(1.0, cameraMode.noiseFactor);<br>
 }<br>
<br>
-int Sharpen::read(boost::property_tree::ptree const &params)<br>
+int 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.h b/src/ipa/raspberrypi/controller/rpi/sharpen.h<br>
index 0cd8b92f2224..8bb7631e916b 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sharpen.h<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sharpen.h<br>
@@ -19,7 +19,7 @@ public:<br>
        Sharpen(Controller *controller);<br>
        char const *name() const override;<br>
        void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;<br>
-       int read(boost::property_tree::ptree const &params) override;<br>
+       int read(const libcamera::YamlObject &params) override;<br>
        void setStrength(double strength) override;<br>
        void prepare(Metadata *imageMetadata) 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 b9e9b814e886..6befdd71433d 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>
 #include <fcntl.h><br>
 #include <math.h><br>
 #include <stdint.h><br>
-- <br>
Regards,<br>
<br>
Laurent Pinchart<br>
<br>
</blockquote></div></div>