<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, 27 Jul 2022 at 03:38, Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com" target="_blank">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">When encountering errors, the Algorithm::read() function either uses<br>
LOG(Fatal) or throws exceptions from the boost property_tree functions.<br>
To prepare for replacing boost JSON parse with the YamlParser class,<br>
give the Algorithm::read() function the ability to return an error code,<br>
and propagate it all the way to the IPA module init() function.<br>
<br>
All algorithm classes return a hardcoded 0 value for now, subsequent<br>
commits will change that.<br>
<br>
Signed-off-by: Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com" target="_blank">laurent.pinchart@ideasonboard.com</a>><br>
---<br>
src/ipa/raspberrypi/controller/algorithm.cpp | 3 +-<br>
src/ipa/raspberrypi/controller/algorithm.h | 2 +-<br>
src/ipa/raspberrypi/controller/controller.cpp | 8 +++-<br>
src/ipa/raspberrypi/controller/controller.h | 2 +-<br>
src/ipa/raspberrypi/controller/pwl.cpp | 3 +-<br>
src/ipa/raspberrypi/controller/pwl.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/agc.cpp | 28 ++++++++++----<br>
src/ipa/raspberrypi/controller/rpi/agc.h | 10 ++---<br>
src/ipa/raspberrypi/controller/rpi/alsc.cpp | 38 +++++++++++++------<br>
src/ipa/raspberrypi/controller/rpi/alsc.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/awb.cpp | 35 +++++++++++------<br>
src/ipa/raspberrypi/controller/rpi/awb.h | 8 ++--<br>
.../controller/rpi/black_level.cpp | 3 +-<br>
.../raspberrypi/controller/rpi/black_level.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/ccm.cpp | 22 ++++++++---<br>
src/ipa/raspberrypi/controller/rpi/ccm.h | 4 +-<br>
.../raspberrypi/controller/rpi/contrast.cpp | 4 +-<br>
src/ipa/raspberrypi/controller/rpi/contrast.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/dpc.cpp | 3 +-<br>
src/ipa/raspberrypi/controller/rpi/dpc.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/geq.cpp | 12 ++++--<br>
src/ipa/raspberrypi/controller/rpi/geq.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/lux.cpp | 3 +-<br>
src/ipa/raspberrypi/controller/rpi/lux.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/noise.cpp | 3 +-<br>
src/ipa/raspberrypi/controller/rpi/noise.h | 2 +-<br>
src/ipa/raspberrypi/controller/rpi/sdn.cpp | 3 +-<br>
src/ipa/raspberrypi/controller/rpi/sdn.h | 2 +-<br>
.../raspberrypi/controller/rpi/sharpen.cpp | 3 +-<br>
src/ipa/raspberrypi/controller/rpi/sharpen.h | 2 +-<br>
src/ipa/raspberrypi/raspberrypi.cpp | 9 ++++-<br>
31 files changed, 151 insertions(+), 75 deletions(-)<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/algorithm.cpp b/src/ipa/raspberrypi/controller/algorithm.cpp<br>
index 1a7d20a4731b..d73cb36fe2d6 100644<br>
--- a/src/ipa/raspberrypi/controller/algorithm.cpp<br>
+++ b/src/ipa/raspberrypi/controller/algorithm.cpp<br>
@@ -9,8 +9,9 @@<br>
<br>
using namespace RPiController;<br>
<br>
-void Algorithm::read([[maybe_unused]] boost::property_tree::ptree const ¶ms)<br>
+int Algorithm::read([[maybe_unused]] boost::property_tree::ptree const ¶ms)<br>
{<br>
+ return 0;<br>
}<br>
<br>
void Algorithm::initialise()<br>
diff --git a/src/ipa/raspberrypi/controller/algorithm.h b/src/ipa/raspberrypi/controller/algorithm.h<br>
index 92fd895d2b06..0c5566fda874 100644<br>
--- a/src/ipa/raspberrypi/controller/algorithm.h<br>
+++ b/src/ipa/raspberrypi/controller/algorithm.h<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 void read(boost::property_tree::ptree const ¶ms);<br>
+ virtual int read(boost::property_tree::ptree const ¶ms);<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 872a32302410..d91ac90704cb 100644<br>
--- a/src/ipa/raspberrypi/controller/controller.cpp<br>
+++ b/src/ipa/raspberrypi/controller/controller.cpp<br>
@@ -32,19 +32,23 @@ Controller::Controller(char const *jsonFilename)<br>
<br>
Controller::~Controller() {}<br>
<br>
-void Controller::read(char const *filename)<br>
+int Controller::read(char const *filename)<br></blockquote><div><br></div><div>Since read now returns an error code, we probably ought to remove the</div><div>Controller(char const *jsonFilename) constructor. This never gets used</div><div>anyway. But that can be done on top of this work.</div><div><br></div><div>Reviewed-by: Naushir Patuck <<a href="mailto:naush@raspberrypi.com">naush@raspberrypi.com</a>></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">
{<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>
if (algo) {<br>
- algo->read(keyAndValue.second);<br>
+ int ret = algo->read(keyAndValue.second);<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>
}<br>
+<br>
+ return 0;<br>
}<br>
<br>
Algorithm *Controller::createAlgorithm(char const *name)<br>
diff --git a/src/ipa/raspberrypi/controller/controller.h b/src/ipa/raspberrypi/controller/controller.h<br>
index e28e30d7d574..841783bb7a5c 100644<br>
--- a/src/ipa/raspberrypi/controller/controller.h<br>
+++ b/src/ipa/raspberrypi/controller/controller.h<br>
@@ -41,7 +41,7 @@ public:<br>
Controller(char const *jsonFilename);<br>
~Controller();<br>
Algorithm *createAlgorithm(char const *name);<br>
- void read(char const *filename);<br>
+ int read(char const *filename);<br>
void initialise();<br>
void switchMode(CameraMode const &cameraMode, Metadata *metadata);<br>
void prepare(Metadata *imageMetadata);<br>
diff --git a/src/ipa/raspberrypi/controller/pwl.cpp b/src/ipa/raspberrypi/controller/pwl.cpp<br>
index 8b8db722966b..fde0b298c6ce 100644<br>
--- a/src/ipa/raspberrypi/controller/pwl.cpp<br>
+++ b/src/ipa/raspberrypi/controller/pwl.cpp<br>
@@ -12,7 +12,7 @@<br>
<br>
using namespace RPiController;<br>
<br>
-void Pwl::read(boost::property_tree::ptree const ¶ms)<br>
+int Pwl::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
for (auto it = params.begin(); it != params.end(); it++) {<br>
double x = it->second.get_value<double>();<br>
@@ -22,6 +22,7 @@ void Pwl::read(boost::property_tree::ptree const ¶ms)<br>
points_.push_back(Point(x, y));<br>
}<br>
assert(points_.size() >= 2);<br>
+ return 0;<br>
}<br>
<br>
void Pwl::append(double x, double y, const double eps)<br>
diff --git a/src/ipa/raspberrypi/controller/pwl.h b/src/ipa/raspberrypi/controller/pwl.h<br>
index 973efdf59945..ef1cc2ed113a 100644<br>
--- a/src/ipa/raspberrypi/controller/pwl.h<br>
+++ b/src/ipa/raspberrypi/controller/pwl.h<br>
@@ -57,7 +57,7 @@ public:<br>
};<br>
Pwl() {}<br>
Pwl(std::vector<Point> const &points) : points_(points) {}<br>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<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 adec8592626d..130c606d4136 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
@@ -30,7 +30,7 @@ LOG_DEFINE_CATEGORY(RPiAgc)<br>
<br>
static constexpr unsigned int PipelineBits = 13; /* seems to be a 13-bit pipeline */<br>
<br>
-void AgcMeteringMode::read(boost::property_tree::ptree const ¶ms)<br>
+int AgcMeteringMode::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
int num = 0;<br>
for (auto &p : params.get_child("weights")) {<br>
@@ -40,6 +40,7 @@ void AgcMeteringMode::read(boost::property_tree::ptree const ¶ms)<br>
}<br>
if (num != AgcStatsSize)<br>
LOG(RPiAgc, Fatal) << "AgcMeteringMode: insufficient weights";<br>
+ return 0;<br>
}<br>
<br>
static std::string<br>
@@ -73,7 +74,7 @@ static int readList(std::vector<Duration> &list,<br>
return list.size();<br>
}<br>
<br>
-void AgcExposureMode::read(boost::property_tree::ptree const ¶ms)<br>
+int AgcExposureMode::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
int numShutters = readList(shutter, params.get_child("shutter"));<br>
int numAgs = readList(gain, params.get_child("gain"));<br>
@@ -83,6 +84,7 @@ void AgcExposureMode::read(boost::property_tree::ptree const ¶ms)<br>
if (numShutters != numAgs)<br>
LOG(RPiAgc, Fatal)<br>
<< "AgcExposureMode: expect same number of exposure and gain entries in exposure profile";<br>
+ return 0;<br>
}<br>
<br>
static std::string<br>
@@ -100,7 +102,7 @@ readExposureModes(std::map<std::string, AgcExposureMode> &exposureModes,<br>
return first;<br>
}<br>
<br>
-void AgcConstraint::read(boost::property_tree::ptree const ¶ms)<br>
+int AgcConstraint::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
std::string boundString = params.get<std::string>("bound", "");<br>
transform(boundString.begin(), boundString.end(),<br>
@@ -110,7 +112,7 @@ void AgcConstraint::read(boost::property_tree::ptree const ¶ms)<br>
bound = boundString == "UPPER" ? Bound::UPPER : Bound::LOWER;<br>
qLo = params.get<double>("q_lo");<br>
qHi = params.get<double>("q_hi");<br>
- yTarget.read(params.get_child("y_target"));<br>
+ return yTarget.read(params.get_child("y_target"));<br>
}<br>
<br>
static AgcConstraintMode<br>
@@ -137,13 +139,17 @@ static std::string readConstraintModes(std::map<std::string, AgcConstraintMode><br>
return first;<br>
}<br>
<br>
-void AgcConfig::read(boost::property_tree::ptree const ¶ms)<br>
+int AgcConfig::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
LOG(RPiAgc, Debug) << "AgcConfig";<br>
defaultMeteringMode = readMeteringModes(meteringModes, params.get_child("metering_modes"));<br>
defaultExposureMode = readExposureModes(exposureModes, params.get_child("exposure_modes"));<br>
defaultConstraintMode = readConstraintModes(constraintModes, params.get_child("constraint_modes"));<br>
- yTarget.read(params.get_child("y_target"));<br>
+<br>
+ int ret = yTarget.read(params.get_child("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>
@@ -152,6 +158,7 @@ void AgcConfig::read(boost::property_tree::ptree const ¶ms)<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>
+ return 0;<br>
}<br>
<br>
Agc::ExposureValues::ExposureValues()<br>
@@ -182,10 +189,14 @@ char const *Agc::name() const<br>
return NAME;<br>
}<br>
<br>
-void Agc::read(boost::property_tree::ptree const ¶ms)<br>
+int Agc::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
LOG(RPiAgc, Debug) << "Agc";<br>
- config_.read(params);<br>
+<br>
+ int ret = config_.read(params);<br>
+ if (ret)<br>
+ return ret;<br>
+<br>
/*<br>
* Set the config's defaults (which are the first ones it read) as our<br>
* current modes, until someone changes them. (they're all known to<br>
@@ -200,6 +211,7 @@ void Agc::read(boost::property_tree::ptree const ¶ms)<br>
/* Set up the "last shutter/gain" values, in case AGC starts "disabled". */<br>
status_.shutterTime = config_.defaultExposureTime;<br>
status_.analogueGain = config_.defaultAnalogueGain;<br>
+ return 0;<br>
}<br>
<br>
bool Agc::isPaused() const<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.h b/src/ipa/raspberrypi/controller/rpi/agc.h<br>
index f57afa6dc80c..1351b0ee079c 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>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<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 ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<br>
};<br>
<br>
struct AgcConstraint {<br>
@@ -43,13 +43,13 @@ struct AgcConstraint {<br>
double qLo;<br>
double qHi;<br>
Pwl yTarget;<br>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<br>
};<br>
<br>
typedef std::vector<AgcConstraint> AgcConstraintMode;<br>
<br>
struct AgcConfig {<br>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 03ae33501dc0..b36277696a52 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp<br>
@@ -50,7 +50,7 @@ char const *Alsc::name() const<br>
return NAME;<br>
}<br>
<br>
-static void generateLut(double *lut, boost::property_tree::ptree const ¶ms)<br>
+static int generateLut(double *lut, boost::property_tree::ptree const ¶ms)<br>
{<br>
double cstrength = params.get<double>("corner_strength", 2.0);<br>
if (cstrength <= 1.0)<br>
@@ -71,9 +71,10 @@ static void generateLut(double *lut, boost::property_tree::ptree const ¶ms)<br>
(f2 * f2); /* this reproduces the cos^4 rule */<br>
}<br>
}<br>
+ return 0;<br>
}<br>
<br>
-static void readLut(double *lut, boost::property_tree::ptree const ¶ms)<br>
+static int readLut(double *lut, boost::property_tree::ptree const ¶ms)<br>
{<br>
int num = 0;<br>
const int maxNum = XY;<br>
@@ -84,11 +85,12 @@ static void readLut(double *lut, boost::property_tree::ptree const ¶ms)<br>
}<br>
if (num < maxNum)<br>
LOG(RPiAlsc, Fatal) << "Alsc: too few entries in LSC table";<br>
+ return 0;<br>
}<br>
<br>
-static void readCalibrations(std::vector<AlscCalibration> &calibrations,<br>
- boost::property_tree::ptree const ¶ms,<br>
- std::string const &name)<br>
+static int readCalibrations(std::vector<AlscCalibration> &calibrations,<br>
+ boost::property_tree::ptree const ¶ms,<br>
+ std::string const &name)<br>
{<br>
if (params.get_child_optional(name)) {<br>
double lastCt = 0;<br>
@@ -117,9 +119,10 @@ static void readCalibrations(std::vector<AlscCalibration> &calibrations,<br>
<< "Read " << name << " calibration for ct " << ct;<br>
}<br>
}<br>
+ return 0;<br>
}<br>
<br>
-void Alsc::read(boost::property_tree::ptree const ¶ms)<br>
+int Alsc::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
config_.framePeriod = params.get<uint16_t>("frame_period", 12);<br>
config_.startupFrames = params.get<uint16_t>("startup_frames", 10);<br>
@@ -135,19 +138,32 @@ void Alsc::read(boost::property_tree::ptree const ¶ms)<br>
params.get<double>("luminance_strength", 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>
- generateLut(config_.luminanceLut, params);<br>
+ ret = generateLut(config_.luminanceLut, params);<br>
else if (params.get_child_optional("luminance_lut"))<br>
- readLut(config_.luminanceLut,<br>
- params.get_child("luminance_lut"));<br>
+ ret = readLut(config_.luminanceLut,<br>
+ params.get_child("luminance_lut"));<br>
else<br>
LOG(RPiAlsc, Warning)<br>
<< "no luminance table - assume unity everywhere";<br>
- readCalibrations(config_.calibrationsCr, params, "calibrations_Cr");<br>
- readCalibrations(config_.calibrationsCb, params, "calibrations_Cb");<br>
+ if (ret)<br>
+ return ret;<br>
+<br>
+ ret = readCalibrations(config_.calibrationsCr, params, "calibrations_Cr");<br>
+ if (ret)<br>
+ return ret;<br>
+ ret = readCalibrations(config_.calibrationsCb, params, "calibrations_Cb");<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>
+<br>
+ return 0;<br>
}<br>
<br>
static double getCt(Metadata *metadata, double defaultCt);<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.h b/src/ipa/raspberrypi/controller/rpi/alsc.h<br>
index 4e9a715ae0ab..773fd338ea8e 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 ad75d55f0976..a9e776a344a1 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/awb.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/awb.cpp<br>
@@ -26,20 +26,21 @@ static constexpr unsigned int AwbStatsSizeY = DEFAULT_AWB_REGIONS_Y;<br>
* elsewhere (ALSC and AGC).<br>
*/<br>
<br>
-void AwbMode::read(boost::property_tree::ptree const ¶ms)<br>
+int AwbMode::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
ctLo = params.get<double>("lo");<br>
ctHi = params.get<double>("hi");<br>
+ return 0;<br>
}<br>
<br>
-void AwbPrior::read(boost::property_tree::ptree const ¶ms)<br>
+int AwbPrior::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
lux = params.get<double>("lux");<br>
- prior.read(params.get_child("prior"));<br>
+ return prior.read(params.get_child("prior"));<br>
}<br>
<br>
-static void readCtCurve(Pwl &ctR, Pwl &ctB,<br>
- boost::property_tree::ptree const ¶ms)<br>
+static int readCtCurve(Pwl &ctR, Pwl &ctB,<br>
+ boost::property_tree::ptree const ¶ms)<br>
{<br>
int num = 0;<br>
for (auto it = params.begin(); it != params.end(); it++) {<br>
@@ -55,21 +56,28 @@ static void readCtCurve(Pwl &ctR, Pwl &ctB,<br>
}<br>
if (num < 2)<br>
LOG(RPiAwb, Fatal) << "AwbConfig: insufficient points in CT curve";<br>
+ return 0;<br>
}<br>
<br>
-void AwbConfig::read(boost::property_tree::ptree const ¶ms)<br>
+int AwbConfig::read(boost::property_tree::ptree const ¶ms)<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>
- readCtCurve(ctR, ctB, params.get_child("ct_curve"));<br>
+ if (params.get_child_optional("ct_curve")) {<br>
+ ret = readCtCurve(ctR, ctB, params.get_child("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>
AwbPrior prior;<br>
- prior.read(p.second);<br>
+ ret = prior.read(p.second);<br>
+ if (ret)<br>
+ return ret;<br>
if (!priors.empty() && prior.lux <= priors.back().lux)<br>
LOG(RPiAwb, Fatal) << "AwbConfig: Prior must be ordered in increasing lux value";<br>
priors.push_back(prior);<br>
@@ -79,7 +87,9 @@ void AwbConfig::read(boost::property_tree::ptree const ¶ms)<br>
}<br>
if (params.get_child_optional("modes")) {<br>
for (auto &p : params.get_child("modes")) {<br>
- modes[p.first].read(p.second);<br>
+ ret = modes[p.first].read(p.second);<br>
+ if (ret)<br>
+ return ret;<br>
if (defaultMode == nullptr)<br>
defaultMode = &modes[p.first];<br>
}<br>
@@ -110,6 +120,7 @@ void AwbConfig::read(boost::property_tree::ptree const ¶ms)<br>
whitepointB = params.get<double>("whitepoint_b", 0.0);<br>
if (bayes == false)<br>
sensitivityR = sensitivityB = 1.0; /* nor do sensitivities make any sense */<br>
+ return 0;<br>
}<br>
<br>
Awb::Awb(Controller *controller)<br>
@@ -137,9 +148,9 @@ char const *Awb::name() const<br>
return NAME;<br>
}<br>
<br>
-void Awb::read(boost::property_tree::ptree const ¶ms)<br>
+int Awb::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
- config_.read(params);<br>
+ return config_.read(params);<br>
}<br>
<br>
void Awb::initialise()<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.h b/src/ipa/raspberrypi/controller/rpi/awb.h<br>
index 9e075624c429..fa0715735fcf 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>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<br>
double ctLo; /* low CT value for search */<br>
double ctHi; /* high CT value for search */<br>
};<br>
<br>
struct AwbPrior {<br>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<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>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<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>
@@ -92,7 +92,7 @@ public:<br>
~Awb();<br>
char const *name() const override;<br>
void initialise() override;<br>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 0799d7b9195a..aa6f602acd7d 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/black_level.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/black_level.cpp<br>
@@ -31,7 +31,7 @@ char const *BlackLevel::name() const<br>
return NAME;<br>
}<br>
<br>
-void BlackLevel::read(boost::property_tree::ptree const ¶ms)<br>
+int BlackLevel::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
uint16_t blackLevel = params.get<uint16_t>(<br>
"black_level", 4096); /* 64 in 10 bits scaled to 16 bits */<br>
@@ -42,6 +42,7 @@ void BlackLevel::read(boost::property_tree::ptree const ¶ms)<br>
<< " Read black levels red " << blackLevelR_<br>
<< " green " << blackLevelG_<br>
<< " blue " << blackLevelB_;<br>
+ return 0;<br>
}<br>
<br>
void BlackLevel::prepare(Metadata *imageMetadata)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/black_level.h b/src/ipa/raspberrypi/controller/rpi/black_level.h<br>
index 7789f261cf03..6ec8c4f9ba8f 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 cf0c85d26cf9..f0110d38f548 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/ccm.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/ccm.cpp<br>
@@ -39,7 +39,7 @@ 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 ¶ms)<br>
+int Matrix::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
double *ptr = (double *)m;<br>
int n = 0;<br>
@@ -50,6 +50,7 @@ void Matrix::read(boost::property_tree::ptree const ¶ms)<br>
}<br>
if (n < 9)<br>
LOG(RPiCcm, Fatal) << "Ccm: too few values in CCM";<br>
+ return 0;<br>
}<br>
<br>
Ccm::Ccm(Controller *controller)<br>
@@ -60,21 +61,32 @@ char const *Ccm::name() const<br>
return NAME;<br>
}<br>
<br>
-void Ccm::read(boost::property_tree::ptree const ¶ms)<br>
+int Ccm::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
- if (params.get_child_optional("saturation"))<br>
- config_.saturation.read(params.get_child("saturation"));<br>
+ int ret;<br>
+<br>
+ if (params.get_child_optional("saturation")) {<br>
+ ret = config_.saturation.read(params.get_child("saturation"));<br>
+ if (ret)<br>
+ return ret;<br>
+ }<br>
+<br>
for (auto &p : params.get_child("ccms")) {<br>
CtCcm ctCcm;<br>
ctCcm.ct = p.second.get<double>("ct");<br>
- ctCcm.ccm.read(p.second.get_child("ccm"));<br>
+ ret = ctCcm.ccm.read(p.second.get_child("ccm"));<br>
+ if (ret)<br>
+ return ret;<br>
if (!config_.ccms.empty() &&<br>
ctCcm.ct <= config_.ccms.back().ct)<br>
LOG(RPiCcm, Fatal) << "Ccm: CCM not in increasing colour temperature order";<br>
config_.ccms.push_back(std::move(ctCcm));<br>
}<br>
+<br>
if (config_.ccms.empty())<br>
LOG(RPiCcm, Fatal) << "Ccm: no CCMs specified";<br>
+<br>
+ return 0;<br>
}<br>
<br>
void Ccm::setSaturation(double saturation)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/ccm.h b/src/ipa/raspberrypi/controller/rpi/ccm.h<br>
index b44f1576528f..6b65c7aea8a6 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>
- void read(boost::property_tree::ptree const ¶ms);<br>
+ int read(boost::property_tree::ptree const ¶ms);<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 ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 9e60dc5d47e7..d76dc43b837f 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/contrast.cpp<br>
@@ -38,7 +38,7 @@ char const *Contrast::name() const<br>
return NAME;<br>
}<br>
<br>
-void Contrast::read(boost::property_tree::ptree const ¶ms)<br>
+int Contrast::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
/* enable adaptive enhancement by default */<br>
config_.ceEnable = params.get<int>("ce_enable", 1);<br>
@@ -52,7 +52,7 @@ void Contrast::read(boost::property_tree::ptree const ¶ms)<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>
- config_.gammaCurve.read(params.get_child("gamma_curve"));<br>
+ return config_.gammaCurve.read(params.get_child("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 b1375d819dbc..5c3d2f56b310 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 d5d784e7ca64..be014a05fd41 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/dpc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/dpc.cpp<br>
@@ -31,11 +31,12 @@ char const *Dpc::name() const<br>
return NAME;<br>
}<br>
<br>
-void Dpc::read(boost::property_tree::ptree const ¶ms)<br>
+int Dpc::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
config_.strength = params.get<int>("strength", 1);<br>
if (config_.strength < 0 || config_.strength > 2)<br>
LOG(RPiDpc, Fatal) << "Dpc: bad strength value";<br>
+ return 0;<br>
}<br>
<br>
void Dpc::prepare(Metadata *imageMetadata)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/dpc.h b/src/ipa/raspberrypi/controller/rpi/dpc.h<br>
index 4c1bdec6dd87..2bb6cef565a7 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 696da4aeea59..a74447877bf8 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/geq.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/geq.cpp<br>
@@ -35,14 +35,20 @@ char const *Geq::name() const<br>
return NAME;<br>
}<br>
<br>
-void Geq::read(boost::property_tree::ptree const ¶ms)<br>
+int Geq::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
config_.offset = params.get<uint16_t>("offset", 0);<br>
config_.slope = params.get<double>("slope", 0.0);<br>
if (config_.slope < 0.0 || config_.slope >= 1.0)<br>
LOG(RPiGeq, Fatal) << "Geq: bad slope value";<br>
- if (params.get_child_optional("strength"))<br>
- config_.strength.read(params.get_child("strength"));<br>
+<br>
+ if (params.get_child_optional("strength")) {<br>
+ int ret = config_.strength.read(params.get_child("strength"));<br>
+ if (ret)<br>
+ return ret;<br>
+ }<br>
+<br>
+ return 0;<br>
}<br>
<br>
void Geq::prepare(Metadata *imageMetadata)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/geq.h b/src/ipa/raspberrypi/controller/rpi/geq.h<br>
index 5d06b9cbd529..677a0510c6ac 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 95c0a93b2810..ca1e827191fd 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/lux.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp<br>
@@ -38,7 +38,7 @@ char const *Lux::name() const<br>
return NAME;<br>
}<br>
<br>
-void Lux::read(boost::property_tree::ptree const ¶ms)<br>
+int Lux::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
referenceShutterSpeed_ =<br>
params.get<double>("reference_shutter_speed") * 1.0us;<br>
@@ -47,6 +47,7 @@ void Lux::read(boost::property_tree::ptree const ¶ms)<br>
referenceY_ = params.get<double>("reference_Y");<br>
referenceLux_ = params.get<double>("reference_lux");<br>
currentAperture_ = referenceAperture_;<br>
+ return 0;<br>
}<br>
<br>
void Lux::setCurrentAperture(double aperture)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/lux.h b/src/ipa/raspberrypi/controller/rpi/lux.h<br>
index 26af8185911c..6416dfb52553 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 5d2c85ad3e74..74fa99bafe48 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/noise.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/noise.cpp<br>
@@ -41,10 +41,11 @@ void Noise::switchMode(CameraMode const &cameraMode,<br>
modeFactor_ = std::max(1.0, cameraMode.noiseFactor);<br>
}<br>
<br>
-void Noise::read(boost::property_tree::ptree const ¶ms)<br>
+int Noise::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
referenceConstant_ = params.get<double>("reference_constant");<br>
referenceSlope_ = params.get<double>("reference_slope");<br>
+ return 0;<br>
}<br>
<br>
void Noise::prepare(Metadata *imageMetadata)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/noise.h b/src/ipa/raspberrypi/controller/rpi/noise.h<br>
index 144e36529f4c..b33a5fc75ec7 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 af31bd0881f0..03d9f119a338 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sdn.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sdn.cpp<br>
@@ -34,10 +34,11 @@ char const *Sdn::name() const<br>
return NAME;<br>
}<br>
<br>
-void Sdn::read(boost::property_tree::ptree const ¶ms)<br>
+int Sdn::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
deviation_ = params.get<double>("deviation", 3.2);<br>
strength_ = params.get<double>("strength", 0.75);<br>
+ return 0;<br>
}<br>
<br>
void Sdn::initialise()<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/sdn.h b/src/ipa/raspberrypi/controller/rpi/sdn.h<br>
index 90ea37ff5550..4287ef08a79f 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) 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 36b75f69afce..9c4cffa4128c 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp<br>
@@ -37,7 +37,7 @@ void Sharpen::switchMode(CameraMode const &cameraMode,<br>
modeFactor_ = std::max(1.0, cameraMode.noiseFactor);<br>
}<br>
<br>
-void Sharpen::read(boost::property_tree::ptree const ¶ms)<br>
+int Sharpen::read(boost::property_tree::ptree const ¶ms)<br>
{<br>
threshold_ = params.get<double>("threshold", 1.0);<br>
strength_ = params.get<double>("strength", 1.0);<br>
@@ -46,6 +46,7 @@ void Sharpen::read(boost::property_tree::ptree const ¶ms)<br>
<< "Read threshold " << threshold_<br>
<< " strength " << strength_<br>
<< " limit " << limit_;<br>
+ return 0;<br>
}<br>
<br>
void Sharpen::setStrength(double strength)<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.h b/src/ipa/raspberrypi/controller/rpi/sharpen.h<br>
index 8846f2ae09a2..0cd8b92f2224 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>
- void read(boost::property_tree::ptree const ¶ms) override;<br>
+ int read(boost::property_tree::ptree const ¶ms) override;<br>
void setStrength(double strength) override;<br>
void prepare(Metadata *imageMetadata) override;<br>
<br>
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp<br>
index 9d550354d78e..b9e9b814e886 100644<br>
--- a/src/ipa/raspberrypi/raspberrypi.cpp<br>
+++ b/src/ipa/raspberrypi/raspberrypi.cpp<br>
@@ -229,7 +229,14 @@ int IPARPi::init(const IPASettings &settings, IPAInitResult *result)<br>
result->sensorConfig.sensorMetadata = sensorMetadata;<br>
<br>
/* Load the tuning file for this sensor. */<br>
- controller_.read(settings.configurationFile.c_str());<br>
+ int ret = controller_.read(settings.configurationFile.c_str());<br>
+ if (ret) {<br>
+ LOG(IPARPI, Error)<br>
+ << "Failed to load tuning data file "<br>
+ << settings.configurationFile;<br>
+ return ret;<br>
+ }<br>
+<br>
controller_.initialise();<br>
<br>
/* Return the controls handled by the IPA */<br>
-- <br>
Regards,<br>
<br>
Laurent Pinchart<br>
<br>
</blockquote></div></div>