[libcamera-devel] [PATCH 7/9] libcamera: ipu3: Add helper class PipeConfigPreference
Han-Lin Chen
hanlinchen at chromium.org
Wed Feb 9 08:19:15 CET 2022
Add helper class PipeConfigPreference to load the caliberated ipu3
pipeline configuration files, and provides query interface for the
pipeline handler.
Signed-off-by: Han-Lin Chen <hanlinchen at chromium.org>
---
include/libcamera/geometry.h | 4 +
src/libcamera/geometry.cpp | 20 ++
src/libcamera/pipeline/ipu3/meson.build | 1 +
.../pipeline/ipu3/pipe_config_pref.cpp | 285 ++++++++++++++++++
.../pipeline/ipu3/pipe_config_pref.h | 80 +++++
5 files changed, 390 insertions(+)
create mode 100644 src/libcamera/pipeline/ipu3/pipe_config_pref.cpp
create mode 100644 src/libcamera/pipeline/ipu3/pipe_config_pref.h
diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h
index 7838b679..ede54981 100644
--- a/include/libcamera/geometry.h
+++ b/include/libcamera/geometry.h
@@ -46,6 +46,8 @@ static inline bool operator!=(const Point &lhs, const Point &rhs)
return !(lhs == rhs);
}
+std::ostream &operator<<(std::ostream &out, const Point &d);
+
class Size
{
public:
@@ -192,6 +194,8 @@ static inline bool operator>=(const Size &lhs, const Size &rhs)
return !(lhs < rhs);
}
+std::ostream &operator<<(std::ostream &out, const Size &s);
+
class SizeRange
{
public:
diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp
index cb3c2de1..a65f9f2f 100644
--- a/src/libcamera/geometry.cpp
+++ b/src/libcamera/geometry.cpp
@@ -83,6 +83,16 @@ bool operator==(const Point &lhs, const Point &rhs)
* \return True if the two points are not equal, false otherwise
*/
+/**
+ * \brief Insert operation for Point with ostream
+ * \return The input std::ostream
+ */
+std::ostream &operator<<(std::ostream &out, const Point &p)
+{
+ out << "(" << p.x << ", " << p.y << ")";
+ return out;
+}
+
/**
* \struct Size
* \brief Describe a two-dimensional size
@@ -428,6 +438,16 @@ bool operator<(const Size &lhs, const Size &rhs)
* \sa bool operator<(const Size &lhs, const Size &rhs)
*/
+/**
+ * \brief Insert operation for Size with ostream
+ * \return The input std::ostream
+ */
+std::ostream &operator<<(std::ostream &out, const Size &s)
+{
+ out << s.width << "x" << s.height;
+ return out;
+}
+
/**
* \struct SizeRange
* \brief Describe a range of sizes
diff --git a/src/libcamera/pipeline/ipu3/meson.build b/src/libcamera/pipeline/ipu3/meson.build
index a1b0b31a..dcc450f0 100644
--- a/src/libcamera/pipeline/ipu3/meson.build
+++ b/src/libcamera/pipeline/ipu3/meson.build
@@ -5,4 +5,5 @@ libcamera_sources += files([
'frames.cpp',
'imgu.cpp',
'ipu3.cpp',
+ 'pipe_config_pref.cpp',
])
diff --git a/src/libcamera/pipeline/ipu3/pipe_config_pref.cpp b/src/libcamera/pipeline/ipu3/pipe_config_pref.cpp
new file mode 100644
index 00000000..5b4a17c9
--- /dev/null
+++ b/src/libcamera/pipeline/ipu3/pipe_config_pref.cpp
@@ -0,0 +1,285 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * pipe_config_pref.cpp - Helper class for IPU3 pipeline config preference
+ */
+
+#include "pipe_config_pref.h"
+
+#include <libcamera/base/log.h>
+
+#include <libcamera/internal/yaml_parser.h>
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(IPU3)
+
+namespace {
+
+std::ostream &operator<<(std::ostream &out,
+ const PipeConfigPreference::PipeConfig &d)
+{
+ out << "cio2: " << d.cio2 << " bds: " << d.bds
+ << " gdc: " << d.gdc << " iff: " << d.iff
+ << " main: " << d.main << " viewfinder: " << d.viewfinder;
+ return out;
+}
+
+int loadPipeConfig(const YamlObject &yamlObject,
+ PipeConfigPreference::PipeConfig &pipeConfig)
+{
+ if (!yamlObject.isMember("bds") ||
+ !yamlObject.isMember("gdc") ||
+ !yamlObject.isMember("iff") ||
+ !yamlObject.isMember("cio2") ||
+ !yamlObject.isMember("main") ||
+ !yamlObject.isMember("viewfinder")) {
+ LOG(IPU3, Error) << "Missing mandatory attributes in a config";
+ return -EINVAL;
+ }
+
+ pipeConfig.bds = yamlObject.get("bds").asSize();
+ pipeConfig.gdc = yamlObject.get("gdc").asSize();
+ pipeConfig.iff = yamlObject.get("iff").asSize();
+ pipeConfig.cio2 = yamlObject.get("cio2").asSize();
+ pipeConfig.main = yamlObject.get("main").asSize();
+ pipeConfig.viewfinder = yamlObject.get("viewfinder").asSize();
+
+ return 0;
+}
+
+int loadPipeConfigs(const YamlObject &yamlPipeConfigs,
+ std::vector<PipeConfigPreference::PipeConfig> &pipeConfigs,
+ Size &maxResolution, Size &minResolution)
+{
+ for (int i = 0; i < yamlPipeConfigs.length(); i++) {
+ const YamlObject &yamlConfig = yamlPipeConfigs[i];
+ pipeConfigs.emplace_back();
+ if (loadPipeConfig(yamlConfig, pipeConfigs.back()))
+ return -EINVAL;
+ }
+
+ if (pipeConfigs.size() == 0)
+ return -EINVAL;
+
+ maxResolution = minResolution = pipeConfigs[0].main;
+
+ for (const PipeConfigPreference::PipeConfig &config : pipeConfigs) {
+ maxResolution.expandTo(config.main);
+ minResolution.boundTo(config.main);
+ }
+
+ /* Sort configs by the size of the cio2 */
+ sort(pipeConfigs.begin(), pipeConfigs.end(),
+ [](const auto &a, const auto &b) -> bool {
+ return a.cio2 < b.cio2;
+ });
+
+ return 0;
+}
+
+} /* namespace */
+
+PipeConfigPreference::PipeConfigPreference()
+ : valid_(false)
+{
+}
+
+/**
+ * \struct PipeConfig
+ * \brief Describe a valid ImgU configuration
+ *
+ * The ImgU unit processes images through several components, which have
+ * to be properly configured inspecting the input image size and the desired
+ * output sizes. This structure collects the ImgU configuration for IF, BDS
+ * and GDC, and the requested main output, viewfinder and the input (CIO2)
+ * resolutions.
+ */
+
+/**
+ * \brief Parse the configuration file from a path
+ * \param[in] path The path to the configuration file
+ *
+ * Parse the configuration file from a path and set isValid() to true if
+ * success.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int PipeConfigPreference::parsePreferenceFile(const std::string &path)
+{
+ valid_ = false;
+
+ FILE *fh = fopen(path.c_str(), "r");
+ if (!fh) {
+ LOG(IPU3, Error) << "Fail to open file: " << path;
+ return -EINVAL;
+ }
+
+ YamlParser yamlParser;
+ YamlObject yamlObjectPreference;
+
+ int ret = yamlParser.ParseAsYamlObject(fh, yamlObjectPreference);
+ fclose(fh);
+
+ if (ret)
+ return -EINVAL;
+
+ ret = load(yamlObjectPreference);
+
+ if (ret)
+ return -EINVAL;
+
+ valid_ = true;
+ return 0;
+}
+
+/**
+ * \brief Query the valid pipeline configuration for video and still pipe
+ * \param[in] videoMain The size of main output from video pipe
+ * \param[in] videoViewfinder The size of viewfinder output from video pipe
+ * \param[in] stillMain The size of main output from still pipe
+ * \param[in] stillViewfinder The size of viewfinder output from still pipe
+ * \param[out] videoResult The ImgU setting for video pipe
+ * \param[out] stillResult The ImgU setting for still pipe
+ *
+ * Helper function to query valid settings for ImgU with the desired
+ * output resolutions. The query interface is based on the assumption
+ * that both video and still ImgU might be used together.
+ * An output can be set disabled if not required. If both main and viewfinder
+ * are set disabled for a ImgU, video or still, the corresponding pipeConfig
+ * undefined. For example, a typical usage is to only one video output is
+ * required, the user may set:
+ *
+ * videoMain = [width, height]
+ * videoViewfinder = Disabled
+ * stillMain = Disabled
+ * stillViewfinder = Disabled
+ *
+ * In the case, only the videoResult would be valid, since still pipe is not
+ * used. When both video and still ImgU are used, their cio2 will have the
+ * same resolution, since they should use the same raw capture.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int PipeConfigPreference::queryPipeConfig(
+ const Size &videoMain, const Size &videoViewfinder,
+ const Size &stillMain, const Size &stillViewfinder,
+ PipeConfig &videoResult, PipeConfig &stillResult) const
+{
+ bool hasVideo = (videoMain != Disabled) && (videoMain >= videoViewfinder);
+ bool hasStill = (stillMain != Disabled) && (stillMain >= stillViewfinder);
+
+ if (!hasStill && !hasVideo)
+ return -EINVAL;
+
+ std::vector<PipeConfig> validVideoConfigs;
+ std::vector<PipeConfig> validStillConfigs;
+
+ for (auto &config : videoPipeConfigs_) {
+ if (config.main == videoMain && config.viewfinder == videoViewfinder)
+ validVideoConfigs.emplace_back(config);
+ }
+
+ for (auto &config : stillPipeConfigs_) {
+ if (config.main == stillMain && config.viewfinder == stillViewfinder)
+ validStillConfigs.emplace_back(config);
+ }
+
+ /*
+ * Since the configurations are sorted by the size of CIO2, pick
+ * the first valid resolution for lower bandwith.
+ */
+ if (hasVideo && !hasStill) {
+ if (validVideoConfigs.empty())
+ return -EINVAL;
+ videoResult = validVideoConfigs[0];
+ return 0;
+ }
+
+ if (hasStill && !hasVideo) {
+ if (validStillConfigs.empty())
+ return -EINVAL;
+ stillResult = validStillConfigs[0];
+ return 0;
+ }
+
+ /* (hasVideo && hasStill) */
+ bool found = false;
+ for (const PipeConfig &videoConfig : validVideoConfigs) {
+ for (const PipeConfig &stillConfig : validVideoConfigs) {
+ if (videoConfig.cio2 == stillConfig.cio2) {
+ found = true;
+ videoResult = videoConfig;
+ stillResult = stillConfig;
+ break;
+ }
+ }
+ }
+
+ return (found) ? 0 : -EINVAL;
+}
+
+void PipeConfigPreference::dump()
+{
+ LOG(IPU3, Debug) << "Video Pipe configs: ";
+ for (auto &configs : videoPipeConfigs_) {
+ LOG(IPU3, Debug) << configs;
+ }
+
+ LOG(IPU3, Debug) << "Still Pipe configs: ";
+ for (auto &configs : stillPipeConfigs_) {
+ LOG(IPU3, Debug) << configs;
+ }
+}
+
+int PipeConfigPreference::load(const YamlObject &configs)
+{
+ /*
+ * Load the pipeline configure file properties.
+ *
+ * Each valid configuration is a list of properties associated
+ * with the corresponding IMGU settings and grouped into still
+ * and video modes. For each configuration, the main output should
+ * be valid, and the viewfinder is optional. If the viewfinder is
+ * disabled, its width and height should be set to [0, 0];
+ *
+ * still_mode:
+ * - bds: [width, height]
+ * cio2: [width, height]
+ * gdc: [width, height]
+ * iff: [width, height]
+ * main: [width, height]
+ * viewfinder: [0, 0]
+ * ...
+ *
+ * video_mode:
+ * - bds: [width, height]
+ * cio2: [width, height]
+ * gdc: [width, height]
+ * iff: [width, height]
+ * main: [width, height]
+ * viewfinder: [0, 0]
+ * ...
+ */
+
+ if (!configs.isMember("video_mode") || !configs.isMember("still_mode"))
+ return -EINVAL;
+
+ videoPipeConfigs_.clear();
+ stillPipeConfigs_.clear();
+
+ int ret = loadPipeConfigs(configs.get("video_mode"), videoPipeConfigs_,
+ maxVideoResolution_, minVideoResolution_);
+ if (ret)
+ return -EINVAL;
+
+ ret = loadPipeConfigs(configs.get("still_mode"), stillPipeConfigs_,
+ maxStillResolution_, minStillResolution_);
+ if (ret)
+ return -EINVAL;
+
+ return 0;
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/pipeline/ipu3/pipe_config_pref.h b/src/libcamera/pipeline/ipu3/pipe_config_pref.h
new file mode 100644
index 00000000..08626d4e
--- /dev/null
+++ b/src/libcamera/pipeline/ipu3/pipe_config_pref.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * pipe_config_pref.h - Helper class for IPU3 pipeline config preference
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <libcamera/geometry.h>
+
+namespace libcamera {
+
+class YamlObject;
+
+class PipeConfigPreference final
+{
+public:
+ constexpr static Size Disabled = Size(0, 0);
+
+ struct PipeConfig {
+ Size cio2;
+ Size bds;
+ Size gdc;
+ Size iff;
+ Size main;
+ Size viewfinder;
+ };
+
+ PipeConfigPreference();
+
+ int parsePreferenceFile(const std::string &path);
+ bool isValid() const
+ {
+ return valid_;
+ }
+ bool invalid()
+ {
+ return valid_ = false;
+ }
+ Size maxVideoResolution()
+ {
+ return maxVideoResolution_;
+ }
+ Size maxStillResolution()
+ {
+ return maxStillResolution_;
+ }
+ Size minVideoResolution()
+ {
+ return minVideoResolution_;
+ }
+ Size minStillResolution()
+ {
+ return minStillResolution_;
+ }
+
+ int queryPipeConfig(const Size &videoMain, const Size &videoViewfinder,
+ const Size &stillMain, const Size &stillViewfinder,
+ PipeConfig &videoPipeConfig,
+ PipeConfig &stillPipeConfig) const;
+ void dump();
+
+private:
+ int load(const YamlObject &object);
+ bool valid_;
+
+ std::vector<PipeConfig> videoPipeConfigs_;
+ std::vector<PipeConfig> stillPipeConfigs_;
+
+ Size maxVideoResolution_;
+ Size maxStillResolution_;
+
+ Size minVideoResolution_;
+ Size minStillResolution_;
+};
+
+} /* namespace libcamera */
--
2.35.0.263.gb82422642f-goog
More information about the libcamera-devel
mailing list