[{"id":35721,"web_url":"https://patchwork.libcamera.org/comment/35721/","msgid":"<175732715099.2066996.108100931143731256@neptunite.rasen.tech>","date":"2025-09-08T10:25:50","subject":"Re: [PATCH v16 04/12] config: Look up rpi configuration in the\n\tconfiguration file","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"Hi Milan,\n\nThanks for the patch.\n\nQuoting Milan Zamazal (2025-07-29 16:31:52)\n> Let's make rpi configuration available in the global configuration file.\n> It may be arguable whether pipeline specific configurations belong to\n> the global configuration file.  But:\n> \n> - Having a single configuration file is generally easier for the user.\n> - The original configuration via environment variables can be already\n>   considered global.\n> - This option points to other configuration files and it makes little\n>   sense to add another configuration file to the chain.\n> \n> The rpi configuration is currently placed in a separate file, specified\n> by LIBCAMERA_RPI_CONFIG_FILE environment variable.  Let's support the\n> content of the file in the global configuration file.  `version' field\n> is omitted as the global configuration file has its own version and the\n> required version in the original file has been 1.0 anyway.\n> \n> The configuration snippet:\n> \n>   configuration:\n>     pipelines:\n>       rpi:\n>         bcm2835:\n>           pipeline_handler:\n>             ...\n>         pisp:\n>           pipeline_handler:\n>             ...\n> \n> To not break current user setups, LIBCAMERA_RPI_CONFIG_FILE environment\n> variable is still supported and works as before, pointing to a separate\n> configuration file.  Just the duplicate check for the configuration file\n> version in platformPipelineConfigure methods is removed.\n> \n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n\nThe commit title should be s/config:/pipeline: rpi:/ , as this touches rpi code\nand not global_configuration code.\n\n> ---\n>  .../pipeline/rpi/common/pipeline_base.cpp     | 59 +++++++++++--------\n>  .../pipeline/rpi/common/pipeline_base.h       |  3 +-\n>  src/libcamera/pipeline/rpi/pisp/pisp.cpp      | 26 +++-----\n>  src/libcamera/pipeline/rpi/vc4/vc4.cpp        | 26 +++-----\n>  4 files changed, 56 insertions(+), 58 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> index 563df198e..1effa85cd 100644\n> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> @@ -20,8 +20,10 @@\n>  #include <libcamera/property_ids.h>\n>  \n>  #include \"libcamera/internal/camera_lens.h\"\n> +#include \"libcamera/internal/global_configuration.h\"\n>  #include \"libcamera/internal/ipa_manager.h\"\n>  #include \"libcamera/internal/v4l2_subdevice.h\"\n> +#include \"libcamera/internal/yaml_parser.h\"\n>  \n>  using namespace std::chrono_literals;\n>  \n> @@ -1091,35 +1093,46 @@ int CameraData::loadPipelineConfiguration()\n>         /* Initial configuration of the platform, in case no config file is present */\n>         platformPipelineConfigure({});\n>  \n> +       std::unique_ptr<YamlObject> root;\n>         char const *configFromEnv = utils::secure_getenv(\"LIBCAMERA_RPI_CONFIG_FILE\");\n> -       if (!configFromEnv || *configFromEnv == '\\0')\n> -               return 0;\n> -\n> -       std::string filename = std::string(configFromEnv);\n> -       File file(filename);\n> +       if (configFromEnv && *configFromEnv != '\\0') {\n> +               std::string filename = std::string(configFromEnv);\n> +               File file(filename);\n> +\n> +               if (!file.open(File::OpenModeFlag::ReadOnly)) {\n> +                       LOG(RPI, Warning) << \"Failed to open configuration file '\" << filename << \"'\"\n> +                                         << \", using defaults\";\n> +                       return 0;\n> +               }\n>  \n> -       if (!file.open(File::OpenModeFlag::ReadOnly)) {\n> -               LOG(RPI, Warning) << \"Failed to open configuration file '\" << filename << \"'\"\n> -                                 << \", using defaults\";\n> -               return 0;\n> -       }\n> +               LOG(RPI, Info) << \"Using configuration file '\" << filename << \"'\";\n>  \n> -       LOG(RPI, Info) << \"Using configuration file '\" << filename << \"'\";\n> +               root = YamlParser::parse(file);\n> +               if (!root) {\n> +                       LOG(RPI, Warning) << \"Failed to parse configuration file, using defaults\";\n> +                       return 0;\n> +               }\n>  \n> -       std::unique_ptr<YamlObject> root = YamlParser::parse(file);\n> -       if (!root) {\n> -               LOG(RPI, Warning) << \"Failed to parse configuration file, using defaults\";\n> -               return 0;\n> -       }\n> +               std::optional<double> ver = (*root)[\"version\"].get<double>();\n> +               if (!ver || *ver != 1.0) {\n> +                       LOG(RPI, Warning) << \"Unexpected configuration file version reported: \"\n> +                                         << *ver;\n> +                       return 0;\n> +               }\n>  \n> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n> -       if (!ver || *ver != 1.0) {\n> -               LOG(RPI, Warning) << \"Unexpected configuration file version reported: \"\n> -                                 << *ver;\n> -               return 0;\n> +               std::optional<std::string> t = (*root)[\"target\"].get<std::string>();\n> +               if (t != target()) {\n> +                       LOG(RPI, Error) << \"Unexpected target reported: expected \\\"\"\n> +                                       << target() << \"\\\", got \" << (t ? t->c_str() : \"(unknown)\");\n> +                       return -EINVAL;\n> +               }\n>         }\n>  \n> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n> +       GlobalConfiguration::Configuration config =\n> +               pipe()->cameraManager()->_d()->configuration().configuration()[\"pipelines\"][\"rpi\"];\n\nDon't we need to check if configuration()[\"pipelines\"] and configuration()[\"pipelines\"][\"rpi\"] exist?\n\n> +       const YamlObject &phConfig = (root\n> +                                             ? (*root)[\"pipeline_handler\"]\n> +                                             : config[target()][\"pipeline_handler\"]);\n\nSame here, for config[target()] and config[target()][\"pipeline_handler\"] ?\n\nIt looks like the raspberry pi config takes precedence. I suppose that's fine,\nsince it will be removed. Maybe we should add a warning message that it is\ndeprecated and should be removed or moved to the main configuration file.\n\n\nThe rest looks good.\n\n\nThanks,\n\nPaul\n\n>  \n>         if (phConfig.contains(\"disable_startup_frame_drops\"))\n>                 LOG(RPI, Warning)\n> @@ -1135,7 +1148,7 @@ int CameraData::loadPipelineConfiguration()\n>                 frontendDevice()->setDequeueTimeout(config_.cameraTimeoutValue * 1ms);\n>         }\n>  \n> -       return platformPipelineConfigure(root);\n> +       return platformPipelineConfigure(phConfig);\n>  }\n>  \n>  int CameraData::loadIPA(ipa::RPi::InitResult *result)\n> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> index 4bce4ec4f..ffbede798 100644\n> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> @@ -95,8 +95,9 @@ public:\n>         virtual V4L2VideoDevice::Formats ispFormats() const = 0;\n>         virtual V4L2VideoDevice::Formats rawFormats() const = 0;\n>         virtual V4L2VideoDevice *frontendDevice() = 0;\n> +       virtual const std::string &target() const = 0;\n>  \n> -       virtual int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) = 0;\n> +       virtual int platformPipelineConfigure(const YamlObject &phConfig) = 0;\n>  \n>         std::unique_ptr<ipa::RPi::IPAProxyRPi> ipa_;\n>  \n> diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n> index 082724c5a..0fb7c3fe8 100644\n> --- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n> +++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n> @@ -740,10 +740,16 @@ public:\n>                 return cfe_[Cfe::Output0].dev();\n>         }\n>  \n> +       const std::string &target() const override\n> +       {\n> +               static const std::string target = \"pisp\";\n> +               return target;\n> +       }\n> +\n>         CameraConfiguration::Status\n>         platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const override;\n>  \n> -       int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) override;\n> +       int platformPipelineConfigure(const YamlObject &phConfig) override;\n>  \n>         void platformStart() override;\n>         void platformStop() override;\n> @@ -1331,7 +1337,7 @@ PiSPCameraData::platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const\n>         return status;\n>  }\n>  \n> -int PiSPCameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &root)\n> +int PiSPCameraData::platformPipelineConfigure(const YamlObject &phConfig)\n>  {\n>         config_ = {\n>                 .numCfeConfigStatsBuffers = 12,\n> @@ -1340,23 +1346,9 @@ int PiSPCameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject>\n>                 .disableHdr = false,\n>         };\n>  \n> -       if (!root)\n> +       if (!phConfig)\n>                 return 0;\n>  \n> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n> -       if (!ver || *ver != 1.0) {\n> -               LOG(RPI, Error) << \"Unexpected configuration file version reported\";\n> -               return -EINVAL;\n> -       }\n> -\n> -       std::optional<std::string> target = (*root)[\"target\"].get<std::string>();\n> -       if (target != \"pisp\") {\n> -               LOG(RPI, Error) << \"Unexpected target reported: expected \\\"pisp\\\", got \"\n> -                               << (target ? target->c_str() : \"(unknown)\");\n> -               return -EINVAL;\n> -       }\n> -\n> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n>         config_.numCfeConfigStatsBuffers =\n>                 phConfig[\"num_cfe_config_stats_buffers\"].get<unsigned int>(config_.numCfeConfigStatsBuffers);\n>         config_.numCfeConfigQueue =\n> diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> index 99d43bd0a..71c425373 100644\n> --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> @@ -61,13 +61,19 @@ public:\n>                 return unicam_[Unicam::Image].dev();\n>         }\n>  \n> +       const std::string &target() const override\n> +       {\n> +               static const std::string target = \"bcm2835\";\n> +               return target;\n> +       }\n> +\n>         void platformFreeBuffers() override\n>         {\n>         }\n>  \n>         CameraConfiguration::Status platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const override;\n>  \n> -       int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) override;\n> +       int platformPipelineConfigure(const YamlObject &phConfig) override;\n>  \n>         void platformStart() override;\n>         void platformStop() override;\n> @@ -493,30 +499,16 @@ CameraConfiguration::Status Vc4CameraData::platformValidate(RPi::RPiCameraConfig\n>         return status;\n>  }\n>  \n> -int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &root)\n> +int Vc4CameraData::platformPipelineConfigure(const YamlObject &phConfig)\n>  {\n>         config_ = {\n>                 .minUnicamBuffers = 2,\n>                 .minTotalUnicamBuffers = 4,\n>         };\n>  \n> -       if (!root)\n> +       if (!phConfig)\n>                 return 0;\n>  \n> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n> -       if (!ver || *ver != 1.0) {\n> -               LOG(RPI, Error) << \"Unexpected configuration file version reported\";\n> -               return -EINVAL;\n> -       }\n> -\n> -       std::optional<std::string> target = (*root)[\"target\"].get<std::string>();\n> -       if (target != \"bcm2835\") {\n> -               LOG(RPI, Error) << \"Unexpected target reported: expected \\\"bcm2835\\\", got \"\n> -                               << (target ? target->c_str() : \"(unknown)\");\n> -               return -EINVAL;\n> -       }\n> -\n> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n>         config_.minUnicamBuffers =\n>                 phConfig[\"min_unicam_buffers\"].get<unsigned int>(config_.minUnicamBuffers);\n>         config_.minTotalUnicamBuffers =\n> -- \n> 2.50.1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CF08CC324E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  8 Sep 2025 10:25:59 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7A31669359;\n\tMon,  8 Sep 2025 12:25:59 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id F1FC069345\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  8 Sep 2025 12:25:57 +0200 (CEST)","from neptunite.rasen.tech (unknown\n\t[IPv6:2404:7a81:160:2100:60ea:3a39:598b:6db8])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 5480F10BE; \n\tMon,  8 Sep 2025 12:24:45 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"VGTxYGb4\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1757327085;\n\tbh=aHfbhApJp9YrHb2q+Pw7E3lVeMIXVPi8J5J7qPexmCE=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=VGTxYGb41edMgHw+5kSW1gJglQCCZXmhWkFeesqBQ/qaKY76rz3JRWib4TO1/j4Ir\n\tIO8/2aD025Xi0EpQZ13kIWsngBumINRsmpeFMMvHihCqtCJxnBG+zsz4BagzuXeFh6\n\tnc45WwgAxvsiA9tkZaoSk2RDuggPNuN8fc6LeKEo=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20250729073201.5369-5-mzamazal@redhat.com>","References":"<20250729073201.5369-1-mzamazal@redhat.com>\n\t<20250729073201.5369-5-mzamazal@redhat.com>","Subject":"Re: [PATCH v16 04/12] config: Look up rpi configuration in the\n\tconfiguration file","From":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"Milan Zamazal <mzamazal@redhat.com>, Kieran Bingham\n\t<kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?=\n\t<barnabas.pocze@ideasonboard.com>, Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>","To":"Milan Zamazal <mzamazal@redhat.com>, libcamera-devel@lists.libcamera.org","Date":"Mon, 08 Sep 2025 19:25:50 +0900","Message-ID":"<175732715099.2066996.108100931143731256@neptunite.rasen.tech>","User-Agent":"alot/0.0.0","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":35728,"web_url":"https://patchwork.libcamera.org/comment/35728/","msgid":"<85frcxt22b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2025-09-08T15:07:56","subject":"Re: [PATCH v16 04/12] config: Look up rpi configuration in the\n\tconfiguration file","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Paul,\n\nthank you for review.\n\nPaul Elder <paul.elder@ideasonboard.com> writes:\n\n> Hi Milan,\n>\n> Thanks for the patch.\n>\n> Quoting Milan Zamazal (2025-07-29 16:31:52)\n>> Let's make rpi configuration available in the global configuration file.\n>> It may be arguable whether pipeline specific configurations belong to\n>> the global configuration file.  But:\n>> \n>> - Having a single configuration file is generally easier for the user.\n>> - The original configuration via environment variables can be already\n>>   considered global.\n>> - This option points to other configuration files and it makes little\n>>   sense to add another configuration file to the chain.\n>> \n>> The rpi configuration is currently placed in a separate file, specified\n>> by LIBCAMERA_RPI_CONFIG_FILE environment variable.  Let's support the\n>> content of the file in the global configuration file.  `version' field\n>> is omitted as the global configuration file has its own version and the\n>> required version in the original file has been 1.0 anyway.\n>> \n>> The configuration snippet:\n>> \n>>   configuration:\n>>     pipelines:\n>>       rpi:\n>>         bcm2835:\n>>           pipeline_handler:\n>>             ...\n>>         pisp:\n>>           pipeline_handler:\n>>             ...\n>> \n>> To not break current user setups, LIBCAMERA_RPI_CONFIG_FILE environment\n>> variable is still supported and works as before, pointing to a separate\n>> configuration file.  Just the duplicate check for the configuration file\n>> version in platformPipelineConfigure methods is removed.\n>> \n>> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n>\n> The commit title should be s/config:/pipeline: rpi:/ , as this touches rpi code\n> and not global_configuration code.\n\nOK.\n\n>> ---\n>>  .../pipeline/rpi/common/pipeline_base.cpp     | 59 +++++++++++--------\n>>  .../pipeline/rpi/common/pipeline_base.h       |  3 +-\n>>  src/libcamera/pipeline/rpi/pisp/pisp.cpp      | 26 +++-----\n>>  src/libcamera/pipeline/rpi/vc4/vc4.cpp        | 26 +++-----\n>>  4 files changed, 56 insertions(+), 58 deletions(-)\n>> \n>> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n>> index 563df198e..1effa85cd 100644\n>> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n>> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n>> @@ -20,8 +20,10 @@\n>>  #include <libcamera/property_ids.h>\n>>  \n>>  #include \"libcamera/internal/camera_lens.h\"\n>> +#include \"libcamera/internal/global_configuration.h\"\n>>  #include \"libcamera/internal/ipa_manager.h\"\n>>  #include \"libcamera/internal/v4l2_subdevice.h\"\n>> +#include \"libcamera/internal/yaml_parser.h\"\n>>  \n>>  using namespace std::chrono_literals;\n>>  \n>> @@ -1091,35 +1093,46 @@ int CameraData::loadPipelineConfiguration()\n>>         /* Initial configuration of the platform, in case no config file is present */\n>>         platformPipelineConfigure({});\n>>  \n>> +       std::unique_ptr<YamlObject> root;\n>>         char const *configFromEnv = utils::secure_getenv(\"LIBCAMERA_RPI_CONFIG_FILE\");\n>> -       if (!configFromEnv || *configFromEnv == '\\0')\n>> -               return 0;\n>> -\n>> -       std::string filename = std::string(configFromEnv);\n>> -       File file(filename);\n>> +       if (configFromEnv && *configFromEnv != '\\0') {\n>> +               std::string filename = std::string(configFromEnv);\n>> +               File file(filename);\n>> +\n>> +               if (!file.open(File::OpenModeFlag::ReadOnly)) {\n>> +                       LOG(RPI, Warning) << \"Failed to open configuration file '\" << filename << \"'\"\n>> +                                         << \", using defaults\";\n>> +                       return 0;\n>> +               }\n>>  \n>> -       if (!file.open(File::OpenModeFlag::ReadOnly)) {\n>> -               LOG(RPI, Warning) << \"Failed to open configuration file '\" << filename << \"'\"\n>> -                                 << \", using defaults\";\n>> -               return 0;\n>> -       }\n>> +               LOG(RPI, Info) << \"Using configuration file '\" << filename << \"'\";\n>>  \n>> -       LOG(RPI, Info) << \"Using configuration file '\" << filename << \"'\";\n>> +               root = YamlParser::parse(file);\n>> +               if (!root) {\n>> +                       LOG(RPI, Warning) << \"Failed to parse configuration file, using defaults\";\n>> +                       return 0;\n>> +               }\n>>  \n>> -       std::unique_ptr<YamlObject> root = YamlParser::parse(file);\n>> -       if (!root) {\n>> -               LOG(RPI, Warning) << \"Failed to parse configuration file, using defaults\";\n>> -               return 0;\n>> -       }\n>> +               std::optional<double> ver = (*root)[\"version\"].get<double>();\n>> +               if (!ver || *ver != 1.0) {\n>> +                       LOG(RPI, Warning) << \"Unexpected configuration file version reported: \"\n>> +                                         << *ver;\n>> +                       return 0;\n>> +               }\n>>  \n>> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n>> -       if (!ver || *ver != 1.0) {\n>> -               LOG(RPI, Warning) << \"Unexpected configuration file version reported: \"\n>> -                                 << *ver;\n>> -               return 0;\n>> +               std::optional<std::string> t = (*root)[\"target\"].get<std::string>();\n>> +               if (t != target()) {\n>> +                       LOG(RPI, Error) << \"Unexpected target reported: expected \\\"\"\n>> +                                       << target() << \"\\\", got \" << (t ? t->c_str() : \"(unknown)\");\n>> +                       return -EINVAL;\n>> +               }\n>>         }\n>>  \n>> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n>> +       GlobalConfiguration::Configuration config =\n>> +               pipe()->cameraManager()->_d()->configuration().configuration()[\"pipelines\"][\"rpi\"];\n>\n> Don't we need to check if configuration()[\"pipelines\"] and configuration()[\"pipelines\"][\"rpi\"] exist?\n\nYamlObject::operator[] returns an empty YamlObject if the given key\ndoesn't exist, so it should be all fine.\n\n>> +       const YamlObject &phConfig = (root\n>> +                                             ? (*root)[\"pipeline_handler\"]\n>> +                                             : config[target()][\"pipeline_handler\"]);\n>\n> Same here, for config[target()] and config[target()][\"pipeline_handler\"] ?\n\nAgain, YamlObject should do the right thing as well as\nYamlObject::get<>() with a default value, used later in the code.\n\n> It looks like the raspberry pi config takes precedence.\n\nYes.\n\n> I suppose that's fine, since it will be removed. Maybe we should add a\n> warning message that it is deprecated and should be removed or moved\n> to the main configuration file.\n\nI don't plan the removal at the moment.  If it is intended to be done in\nthe future, I can add the warning.\n\n> The rest looks good.\n>\n>\n> Thanks,\n>\n> Paul\n>\n>>  \n>>         if (phConfig.contains(\"disable_startup_frame_drops\"))\n>>                 LOG(RPI, Warning)\n>> @@ -1135,7 +1148,7 @@ int CameraData::loadPipelineConfiguration()\n>>                 frontendDevice()->setDequeueTimeout(config_.cameraTimeoutValue * 1ms);\n>>         }\n>>  \n>> -       return platformPipelineConfigure(root);\n>> +       return platformPipelineConfigure(phConfig);\n>>  }\n>>  \n>>  int CameraData::loadIPA(ipa::RPi::InitResult *result)\n>> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n>> index 4bce4ec4f..ffbede798 100644\n>> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h\n>> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n>> @@ -95,8 +95,9 @@ public:\n>>         virtual V4L2VideoDevice::Formats ispFormats() const = 0;\n>>         virtual V4L2VideoDevice::Formats rawFormats() const = 0;\n>>         virtual V4L2VideoDevice *frontendDevice() = 0;\n>> +       virtual const std::string &target() const = 0;\n>>  \n>> -       virtual int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) = 0;\n>> +       virtual int platformPipelineConfigure(const YamlObject &phConfig) = 0;\n>>  \n>>         std::unique_ptr<ipa::RPi::IPAProxyRPi> ipa_;\n>>  \n>> diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n>> index 082724c5a..0fb7c3fe8 100644\n>> --- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n>> +++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n>> @@ -740,10 +740,16 @@ public:\n>>                 return cfe_[Cfe::Output0].dev();\n>>         }\n>>  \n>> +       const std::string &target() const override\n>> +       {\n>> +               static const std::string target = \"pisp\";\n>> +               return target;\n>> +       }\n>> +\n>>         CameraConfiguration::Status\n>>         platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const override;\n>>  \n>> -       int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) override;\n>> +       int platformPipelineConfigure(const YamlObject &phConfig) override;\n>>  \n>>         void platformStart() override;\n>>         void platformStop() override;\n>> @@ -1331,7 +1337,7 @@ PiSPCameraData::platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const\n>>         return status;\n>>  }\n>>  \n>> -int PiSPCameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &root)\n>> +int PiSPCameraData::platformPipelineConfigure(const YamlObject &phConfig)\n>>  {\n>>         config_ = {\n>>                 .numCfeConfigStatsBuffers = 12,\n>> @@ -1340,23 +1346,9 @@ int PiSPCameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject>\n>>                 .disableHdr = false,\n>>         };\n>>  \n>> -       if (!root)\n>> +       if (!phConfig)\n>>                 return 0;\n>>  \n>> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n>> -       if (!ver || *ver != 1.0) {\n>> -               LOG(RPI, Error) << \"Unexpected configuration file version reported\";\n>> -               return -EINVAL;\n>> -       }\n>> -\n>> -       std::optional<std::string> target = (*root)[\"target\"].get<std::string>();\n>> -       if (target != \"pisp\") {\n>> -               LOG(RPI, Error) << \"Unexpected target reported: expected \\\"pisp\\\", got \"\n>> -                               << (target ? target->c_str() : \"(unknown)\");\n>> -               return -EINVAL;\n>> -       }\n>> -\n>> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n>>         config_.numCfeConfigStatsBuffers =\n>>                 phConfig[\"num_cfe_config_stats_buffers\"].get<unsigned int>(config_.numCfeConfigStatsBuffers);\n>>         config_.numCfeConfigQueue =\n>> diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n>> index 99d43bd0a..71c425373 100644\n>> --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n>> +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n>> @@ -61,13 +61,19 @@ public:\n>>                 return unicam_[Unicam::Image].dev();\n>>         }\n>>  \n>> +       const std::string &target() const override\n>> +       {\n>> +               static const std::string target = \"bcm2835\";\n>> +               return target;\n>> +       }\n>> +\n>>         void platformFreeBuffers() override\n>>         {\n>>         }\n>>  \n>>         CameraConfiguration::Status platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const override;\n>>  \n>> -       int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) override;\n>> +       int platformPipelineConfigure(const YamlObject &phConfig) override;\n>>  \n>>         void platformStart() override;\n>>         void platformStop() override;\n>> @@ -493,30 +499,16 @@ CameraConfiguration::Status Vc4CameraData::platformValidate(RPi::RPiCameraConfig\n>>         return status;\n>>  }\n>>  \n>> -int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &root)\n>> +int Vc4CameraData::platformPipelineConfigure(const YamlObject &phConfig)\n>>  {\n>>         config_ = {\n>>                 .minUnicamBuffers = 2,\n>>                 .minTotalUnicamBuffers = 4,\n>>         };\n>>  \n>> -       if (!root)\n>> +       if (!phConfig)\n>>                 return 0;\n>>  \n>> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n>> -       if (!ver || *ver != 1.0) {\n>> -               LOG(RPI, Error) << \"Unexpected configuration file version reported\";\n>> -               return -EINVAL;\n>> -       }\n>> -\n>> -       std::optional<std::string> target = (*root)[\"target\"].get<std::string>();\n>> -       if (target != \"bcm2835\") {\n>> -               LOG(RPI, Error) << \"Unexpected target reported: expected \\\"bcm2835\\\", got \"\n>> -                               << (target ? target->c_str() : \"(unknown)\");\n>> -               return -EINVAL;\n>> -       }\n>> -\n>> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n>>         config_.minUnicamBuffers =\n>>                 phConfig[\"min_unicam_buffers\"].get<unsigned int>(config_.minUnicamBuffers);\n>>         config_.minTotalUnicamBuffers =\n>> -- \n>> 2.50.1\n>>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 14EC9C324E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  8 Sep 2025 15:08:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EA9656935A;\n\tMon,  8 Sep 2025 17:08:04 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D8C6B6934E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  8 Sep 2025 17:08:02 +0200 (CEST)","from mail-wm1-f69.google.com (mail-wm1-f69.google.com\n\t[209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-639-VJBDoBEkNgyc130NQGj40A-1; Mon, 08 Sep 2025 11:08:00 -0400","by mail-wm1-f69.google.com with SMTP id\n\t5b1f17b1804b1-45d6c770066so23585985e9.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 08 Sep 2025 08:08:00 -0700 (PDT)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-3e7483597ccsm5116761f8f.31.2025.09.08.08.07.57\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 08 Sep 2025 08:07:57 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"eCmLwKzq\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1757344081;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=YKnsGk2NSjD4uEX/mra1oeUACioz4A50UVWULUn/UbM=;\n\tb=eCmLwKzqJmTpfQtBCFBz1OZR5yT9fGg6USlAShBYc51vhRPIH9RflWRh+QyD9n7gwAJCvQ\n\tcVvenAviMlSELVAmyL2UhzemEWiMAgoeuXUBwRQ2mkPhHlB0ekbyHhqRMHNZouTFxmTmA6\n\tUV1ci/EZoIUi7w+D7dfzk3aPxF014jo=","X-MC-Unique":"VJBDoBEkNgyc130NQGj40A-1","X-Mimecast-MFC-AGG-ID":"VJBDoBEkNgyc130NQGj40A_1757344079","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1757344079; x=1757948879;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=YKnsGk2NSjD4uEX/mra1oeUACioz4A50UVWULUn/UbM=;\n\tb=MPNElnQW7s3LnO8zVUl2Zp+ic2PMRHaPoz9Pr5oZOUpa8+4tzpYbbqDEniFFCj4GvJ\n\tHQn5jjwoQiJBmB9H8AHKbLiuylzkSsWv3gbBcD8IujZwccJXutzXQFxzpYXTr4IMvDbc\n\tzX3hON8DRm5JNaYQ4pP4yxlea+pL5TMEoAPkS36sToBCYA5vuurv0VZMYHXLkTzkv/f6\n\t7NyofSqveIA/9Gtu1xIoWywks9AqX1VaoOaZiEjOsUiN13b77IXvNhHTRxkZ85LuNwWx\n\tLJbu2sEwBiRCd81OCYxYZJ7+o1xVPC8dYZzzrZtLTYYaJMOa0UIPPAqo+ASN3hDmVlu2\n\tCdNw==","X-Gm-Message-State":"AOJu0YzrPo8djH6cenRTG6SKvncjHG+jMwuzOv+FX9TGlzDbTARa/Q1u\n\tAmqn6PM/VIiar5isIKhINA/ZKkyESQhtziJSZvKdac/YupcNdNA4npqIrvFzkyWM4cp8sAAEt03\n\tw3Ma+hMovgs1H1gIg8nZId5VKIgbGoW46p8n3kkgAFT0wkhldZp4Ab7loQVy9GC8WrE5PcA6qo2\n\tPgzNWrrZg=","X-Gm-Gg":"ASbGncuVBM0W9ojcLvI8I/fdBXeBHg/0xu1pZBHLuwOCsvlOaj2KYlhxD7XT0ULgoLX\n\tVQQdZ8x5/3w+jWM3Ry9CVYajKFH1wTa2ui6FKNiPTTfa46P8SiJzkXf8xaxh9T13rvEzEzwhWRP\n\t2MHdbEkrSa0JfwpH3GMlgifK65kcWSxjW3KvSc7r7Ss5CPyrIWl7k5rC/WYW4mHxDIFGAmliSzi\n\t2lZSNr2t4xzUPfUz7sR5A6bKqOwKFFHFNaoXoYbTpz/DwOnhIzPl6oeOShRNa2rcjwJMN0/G7Jx\n\tXDHWe2LNLM2wQeH09U2QMV57eaxSXVKfaBeKY+I2Byx+QU0vbs+Ztvhw1lNdPJccwYFXcutYmMF\n\t3qwt+AiTq3jPSyZbG/A==","X-Received":["by 2002:a05:6000:2186:b0:3e7:4071:186e with SMTP id\n\tffacd0b85a97d-3e740711d5bmr4095811f8f.4.1757344078811; \n\tMon, 08 Sep 2025 08:07:58 -0700 (PDT)","by 2002:a05:6000:2186:b0:3e7:4071:186e with SMTP id\n\tffacd0b85a97d-3e740711d5bmr4095787f8f.4.1757344078159; \n\tMon, 08 Sep 2025 08:07:58 -0700 (PDT)"],"X-Google-Smtp-Source":"AGHT+IFU+kWJRyN/CyA2dhXSZfr+7WVNqcS8oV2dXHc9DOp8QdJZsRhh+YVnlTNmfhfYjtxsGE+5CQ==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab?=\n\t=?utf-8?b?w6FzIFDFkWN6ZQ==?= <barnabas.pocze@ideasonboard.com>,\n\tLaurent Pinchart  <laurent.pinchart@ideasonboard.com>","Subject":"Re: [PATCH v16 04/12] config: Look up rpi configuration in the\n\tconfiguration file","In-Reply-To":"<175732715099.2066996.108100931143731256@neptunite.rasen.tech>\n\t(Paul Elder's message of \"Mon, 08 Sep 2025 19:25:50 +0900\")","References":"<20250729073201.5369-1-mzamazal@redhat.com>\n\t<20250729073201.5369-5-mzamazal@redhat.com>\n\t<175732715099.2066996.108100931143731256@neptunite.rasen.tech>","Date":"Mon, 08 Sep 2025 17:07:56 +0200","Message-ID":"<85frcxt22b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"iZ0kNgCeIYyD9_Rc88a6djud3DNtc2UuxK8tMTuNFqQ_1757344079","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":35747,"web_url":"https://patchwork.libcamera.org/comment/35747/","msgid":"<175742627911.2127323.7806435989637469335@neptunite.rasen.tech>","date":"2025-09-09T13:57:59","subject":"Re: [PATCH v16 04/12] config: Look up rpi configuration in the\n\tconfiguration file","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"Hi Milan,\n\nQuoting Milan Zamazal (2025-09-09 00:07:56)\n> Hi Paul,\n> \n> thank you for review.\n> \n> Paul Elder <paul.elder@ideasonboard.com> writes:\n> \n> > Hi Milan,\n> >\n> > Thanks for the patch.\n> >\n> > Quoting Milan Zamazal (2025-07-29 16:31:52)\n> >> Let's make rpi configuration available in the global configuration file.\n> >> It may be arguable whether pipeline specific configurations belong to\n> >> the global configuration file.  But:\n> >> \n> >> - Having a single configuration file is generally easier for the user.\n> >> - The original configuration via environment variables can be already\n> >>   considered global.\n> >> - This option points to other configuration files and it makes little\n> >>   sense to add another configuration file to the chain.\n> >> \n> >> The rpi configuration is currently placed in a separate file, specified\n> >> by LIBCAMERA_RPI_CONFIG_FILE environment variable.  Let's support the\n> >> content of the file in the global configuration file.  `version' field\n> >> is omitted as the global configuration file has its own version and the\n> >> required version in the original file has been 1.0 anyway.\n> >> \n> >> The configuration snippet:\n> >> \n> >>   configuration:\n> >>     pipelines:\n> >>       rpi:\n> >>         bcm2835:\n> >>           pipeline_handler:\n> >>             ...\n> >>         pisp:\n> >>           pipeline_handler:\n> >>             ...\n> >> \n> >> To not break current user setups, LIBCAMERA_RPI_CONFIG_FILE environment\n> >> variable is still supported and works as before, pointing to a separate\n> >> configuration file.  Just the duplicate check for the configuration file\n> >> version in platformPipelineConfigure methods is removed.\n> >> \n> >> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> >\n> > The commit title should be s/config:/pipeline: rpi:/ , as this touches rpi code\n> > and not global_configuration code.\n> \n> OK.\n> \n> >> ---\n> >>  .../pipeline/rpi/common/pipeline_base.cpp     | 59 +++++++++++--------\n> >>  .../pipeline/rpi/common/pipeline_base.h       |  3 +-\n> >>  src/libcamera/pipeline/rpi/pisp/pisp.cpp      | 26 +++-----\n> >>  src/libcamera/pipeline/rpi/vc4/vc4.cpp        | 26 +++-----\n> >>  4 files changed, 56 insertions(+), 58 deletions(-)\n> >> \n> >> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> >> index 563df198e..1effa85cd 100644\n> >> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> >> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> >> @@ -20,8 +20,10 @@\n> >>  #include <libcamera/property_ids.h>\n> >>  \n> >>  #include \"libcamera/internal/camera_lens.h\"\n> >> +#include \"libcamera/internal/global_configuration.h\"\n> >>  #include \"libcamera/internal/ipa_manager.h\"\n> >>  #include \"libcamera/internal/v4l2_subdevice.h\"\n> >> +#include \"libcamera/internal/yaml_parser.h\"\n> >>  \n> >>  using namespace std::chrono_literals;\n> >>  \n> >> @@ -1091,35 +1093,46 @@ int CameraData::loadPipelineConfiguration()\n> >>         /* Initial configuration of the platform, in case no config file is present */\n> >>         platformPipelineConfigure({});\n> >>  \n> >> +       std::unique_ptr<YamlObject> root;\n> >>         char const *configFromEnv = utils::secure_getenv(\"LIBCAMERA_RPI_CONFIG_FILE\");\n> >> -       if (!configFromEnv || *configFromEnv == '\\0')\n> >> -               return 0;\n> >> -\n> >> -       std::string filename = std::string(configFromEnv);\n> >> -       File file(filename);\n> >> +       if (configFromEnv && *configFromEnv != '\\0') {\n> >> +               std::string filename = std::string(configFromEnv);\n> >> +               File file(filename);\n> >> +\n> >> +               if (!file.open(File::OpenModeFlag::ReadOnly)) {\n> >> +                       LOG(RPI, Warning) << \"Failed to open configuration file '\" << filename << \"'\"\n> >> +                                         << \", using defaults\";\n> >> +                       return 0;\n> >> +               }\n> >>  \n> >> -       if (!file.open(File::OpenModeFlag::ReadOnly)) {\n> >> -               LOG(RPI, Warning) << \"Failed to open configuration file '\" << filename << \"'\"\n> >> -                                 << \", using defaults\";\n> >> -               return 0;\n> >> -       }\n> >> +               LOG(RPI, Info) << \"Using configuration file '\" << filename << \"'\";\n> >>  \n> >> -       LOG(RPI, Info) << \"Using configuration file '\" << filename << \"'\";\n> >> +               root = YamlParser::parse(file);\n> >> +               if (!root) {\n> >> +                       LOG(RPI, Warning) << \"Failed to parse configuration file, using defaults\";\n> >> +                       return 0;\n> >> +               }\n> >>  \n> >> -       std::unique_ptr<YamlObject> root = YamlParser::parse(file);\n> >> -       if (!root) {\n> >> -               LOG(RPI, Warning) << \"Failed to parse configuration file, using defaults\";\n> >> -               return 0;\n> >> -       }\n> >> +               std::optional<double> ver = (*root)[\"version\"].get<double>();\n> >> +               if (!ver || *ver != 1.0) {\n> >> +                       LOG(RPI, Warning) << \"Unexpected configuration file version reported: \"\n> >> +                                         << *ver;\n> >> +                       return 0;\n> >> +               }\n> >>  \n> >> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n> >> -       if (!ver || *ver != 1.0) {\n> >> -               LOG(RPI, Warning) << \"Unexpected configuration file version reported: \"\n> >> -                                 << *ver;\n> >> -               return 0;\n> >> +               std::optional<std::string> t = (*root)[\"target\"].get<std::string>();\n> >> +               if (t != target()) {\n> >> +                       LOG(RPI, Error) << \"Unexpected target reported: expected \\\"\"\n> >> +                                       << target() << \"\\\", got \" << (t ? t->c_str() : \"(unknown)\");\n> >> +                       return -EINVAL;\n> >> +               }\n> >>         }\n> >>  \n> >> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n> >> +       GlobalConfiguration::Configuration config =\n> >> +               pipe()->cameraManager()->_d()->configuration().configuration()[\"pipelines\"][\"rpi\"];\n> >\n> > Don't we need to check if configuration()[\"pipelines\"] and configuration()[\"pipelines\"][\"rpi\"] exist?\n> \n> YamlObject::operator[] returns an empty YamlObject if the given key\n> doesn't exist, so it should be all fine.\n\nOh ok I see what you mean. That's neat.\n\n> \n> >> +       const YamlObject &phConfig = (root\n> >> +                                             ? (*root)[\"pipeline_handler\"]\n> >> +                                             : config[target()][\"pipeline_handler\"]);\n> >\n> > Same here, for config[target()] and config[target()][\"pipeline_handler\"] ?\n> \n> Again, YamlObject should do the right thing as well as\n> YamlObject::get<>() with a default value, used later in the code.\n> \n> > It looks like the raspberry pi config takes precedence.\n> \n> Yes.\n> \n> > I suppose that's fine, since it will be removed. Maybe we should add a\n> > warning message that it is deprecated and should be removed or moved\n> > to the main configuration file.\n> \n> I don't plan the removal at the moment.  If it is intended to be done in\n> the future, I can add the warning.\n\nOk.\n\n> \n> > The rest looks good.\n\nThen with the commit title fix,\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n> >\n> >\n> > Thanks,\n> >\n> > Paul\n> >\n> >>  \n> >>         if (phConfig.contains(\"disable_startup_frame_drops\"))\n> >>                 LOG(RPI, Warning)\n> >> @@ -1135,7 +1148,7 @@ int CameraData::loadPipelineConfiguration()\n> >>                 frontendDevice()->setDequeueTimeout(config_.cameraTimeoutValue * 1ms);\n> >>         }\n> >>  \n> >> -       return platformPipelineConfigure(root);\n> >> +       return platformPipelineConfigure(phConfig);\n> >>  }\n> >>  \n> >>  int CameraData::loadIPA(ipa::RPi::InitResult *result)\n> >> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> >> index 4bce4ec4f..ffbede798 100644\n> >> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> >> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> >> @@ -95,8 +95,9 @@ public:\n> >>         virtual V4L2VideoDevice::Formats ispFormats() const = 0;\n> >>         virtual V4L2VideoDevice::Formats rawFormats() const = 0;\n> >>         virtual V4L2VideoDevice *frontendDevice() = 0;\n> >> +       virtual const std::string &target() const = 0;\n> >>  \n> >> -       virtual int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) = 0;\n> >> +       virtual int platformPipelineConfigure(const YamlObject &phConfig) = 0;\n> >>  \n> >>         std::unique_ptr<ipa::RPi::IPAProxyRPi> ipa_;\n> >>  \n> >> diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n> >> index 082724c5a..0fb7c3fe8 100644\n> >> --- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n> >> +++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp\n> >> @@ -740,10 +740,16 @@ public:\n> >>                 return cfe_[Cfe::Output0].dev();\n> >>         }\n> >>  \n> >> +       const std::string &target() const override\n> >> +       {\n> >> +               static const std::string target = \"pisp\";\n> >> +               return target;\n> >> +       }\n> >> +\n> >>         CameraConfiguration::Status\n> >>         platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const override;\n> >>  \n> >> -       int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) override;\n> >> +       int platformPipelineConfigure(const YamlObject &phConfig) override;\n> >>  \n> >>         void platformStart() override;\n> >>         void platformStop() override;\n> >> @@ -1331,7 +1337,7 @@ PiSPCameraData::platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const\n> >>         return status;\n> >>  }\n> >>  \n> >> -int PiSPCameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &root)\n> >> +int PiSPCameraData::platformPipelineConfigure(const YamlObject &phConfig)\n> >>  {\n> >>         config_ = {\n> >>                 .numCfeConfigStatsBuffers = 12,\n> >> @@ -1340,23 +1346,9 @@ int PiSPCameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject>\n> >>                 .disableHdr = false,\n> >>         };\n> >>  \n> >> -       if (!root)\n> >> +       if (!phConfig)\n> >>                 return 0;\n> >>  \n> >> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n> >> -       if (!ver || *ver != 1.0) {\n> >> -               LOG(RPI, Error) << \"Unexpected configuration file version reported\";\n> >> -               return -EINVAL;\n> >> -       }\n> >> -\n> >> -       std::optional<std::string> target = (*root)[\"target\"].get<std::string>();\n> >> -       if (target != \"pisp\") {\n> >> -               LOG(RPI, Error) << \"Unexpected target reported: expected \\\"pisp\\\", got \"\n> >> -                               << (target ? target->c_str() : \"(unknown)\");\n> >> -               return -EINVAL;\n> >> -       }\n> >> -\n> >> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n> >>         config_.numCfeConfigStatsBuffers =\n> >>                 phConfig[\"num_cfe_config_stats_buffers\"].get<unsigned int>(config_.numCfeConfigStatsBuffers);\n> >>         config_.numCfeConfigQueue =\n> >> diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> >> index 99d43bd0a..71c425373 100644\n> >> --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> >> +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> >> @@ -61,13 +61,19 @@ public:\n> >>                 return unicam_[Unicam::Image].dev();\n> >>         }\n> >>  \n> >> +       const std::string &target() const override\n> >> +       {\n> >> +               static const std::string target = \"bcm2835\";\n> >> +               return target;\n> >> +       }\n> >> +\n> >>         void platformFreeBuffers() override\n> >>         {\n> >>         }\n> >>  \n> >>         CameraConfiguration::Status platformValidate(RPi::RPiCameraConfiguration *rpiConfig) const override;\n> >>  \n> >> -       int platformPipelineConfigure(const std::unique_ptr<YamlObject> &root) override;\n> >> +       int platformPipelineConfigure(const YamlObject &phConfig) override;\n> >>  \n> >>         void platformStart() override;\n> >>         void platformStop() override;\n> >> @@ -493,30 +499,16 @@ CameraConfiguration::Status Vc4CameraData::platformValidate(RPi::RPiCameraConfig\n> >>         return status;\n> >>  }\n> >>  \n> >> -int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &root)\n> >> +int Vc4CameraData::platformPipelineConfigure(const YamlObject &phConfig)\n> >>  {\n> >>         config_ = {\n> >>                 .minUnicamBuffers = 2,\n> >>                 .minTotalUnicamBuffers = 4,\n> >>         };\n> >>  \n> >> -       if (!root)\n> >> +       if (!phConfig)\n> >>                 return 0;\n> >>  \n> >> -       std::optional<double> ver = (*root)[\"version\"].get<double>();\n> >> -       if (!ver || *ver != 1.0) {\n> >> -               LOG(RPI, Error) << \"Unexpected configuration file version reported\";\n> >> -               return -EINVAL;\n> >> -       }\n> >> -\n> >> -       std::optional<std::string> target = (*root)[\"target\"].get<std::string>();\n> >> -       if (target != \"bcm2835\") {\n> >> -               LOG(RPI, Error) << \"Unexpected target reported: expected \\\"bcm2835\\\", got \"\n> >> -                               << (target ? target->c_str() : \"(unknown)\");\n> >> -               return -EINVAL;\n> >> -       }\n> >> -\n> >> -       const YamlObject &phConfig = (*root)[\"pipeline_handler\"];\n> >>         config_.minUnicamBuffers =\n> >>                 phConfig[\"min_unicam_buffers\"].get<unsigned int>(config_.minUnicamBuffers);\n> >>         config_.minTotalUnicamBuffers =\n> >> -- \n> >> 2.50.1\n> >>\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 03D51C324E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  9 Sep 2025 13:58:10 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 00E2169367;\n\tTue,  9 Sep 2025 15:58:09 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0AF896934B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Sep 2025 15:58:06 +0200 (CEST)","from neptunite.rasen.tech (unknown\n\t[IPv6:2404:7a81:160:2100:6f3a:4f34:f1fa:8b3])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 308AC605;\n\tTue,  9 Sep 2025 15:56:51 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"weVRY5r/\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1757426212;\n\tbh=qVDrSDeQXL9QuWSfXP6iPv8jJIjuQaAkZU1ZkfkSkGU=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=weVRY5r/JGBe34vYU/wBeACGUkc87fuTVyqkr/P83JTgu73J7MJ+soFZ00Uahbkdp\n\tNsQsDg6vmZlcYzdUVVZXcYQRIGAfHEUaCGB0NxAin5WNQhEpfNM8XEiqSYz/Tcxvwl\n\tyKg227QljTChGgGIV9y4RmxSHusb3MS6aVjrMpJc=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<85frcxt22b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","References":"<20250729073201.5369-1-mzamazal@redhat.com>\n\t<20250729073201.5369-5-mzamazal@redhat.com>\n\t<175732715099.2066996.108100931143731256@neptunite.rasen.tech>\n\t<85frcxt22b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","Subject":"Re: [PATCH v16 04/12] config: Look up rpi configuration in the\n\tconfiguration file","From":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org, Kieran Bingham\n\t<kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?=\n\t<barnabas.pocze@ideasonboard.com>, Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>","To":"Milan Zamazal <mzamazal@redhat.com>","Date":"Tue, 09 Sep 2025 22:57:59 +0900","Message-ID":"<175742627911.2127323.7806435989637469335@neptunite.rasen.tech>","User-Agent":"alot/0.0.0","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]