From patchwork Wed Feb 9 07:19:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanlin Chen X-Patchwork-Id: 15351 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 21FCCC3261 for ; Wed, 9 Feb 2022 07:19:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BBE52610DA; Wed, 9 Feb 2022 08:19:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="X5Fz9p7o"; dkim-atps=neutral Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E6C0060202 for ; Wed, 9 Feb 2022 08:19:40 +0100 (CET) Received: by mail-pl1-x62f.google.com with SMTP id k17so1516594plk.0 for ; Tue, 08 Feb 2022 23:19:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BXvbw/qFuh4/mv/AibxotkM+baDpuUOcjWD8E0nJer0=; b=X5Fz9p7o2v10nwD/Yv/oZkL8s5HINCb4vsc4Cpp7IrS1NDB0jeIQP2LPdmTuvBNFOg MRocsgb//OiBX70J/UuhUWolk1Fin/PbMhFemGwvneYhA7JPQb9f1J38HGeOs0xG6eDw flQfYnpltzUZVH3dzuwQn8MHMRSkDaEEYCpjU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BXvbw/qFuh4/mv/AibxotkM+baDpuUOcjWD8E0nJer0=; b=s0BnVde0kq00TQKIV/kNcT4F6u1ry/HO0hg3QOEVlr7HA4kQ9TnqMKOKIX7FNEbT3e DBl/2DhlGljPvU6v8tfrXQVxXhASz1k5DL004D6SC7WtKLioi5V1UJl7l8OtYLHVTqyC xhh/hvKr1KlkgVPF+5T6na0bXVXq1Pn4xentCR3DtuuEnSM/sg3Lhv31RsrWbFPuOvtW FZkjSUKGzZIMTMHUlXvnPOMHpNGTN6RRh1EyCFa9+UJnpBNg4Kbz9uWBdgplNRnKt69d rEmUjZDoLQAalSXuZQn/dPMWIMX5vltqP0TgQVr7GvztiETzgwM+ZEKy1/G0Cx0muXkd ejqQ== X-Gm-Message-State: AOAM530Bb43XXFth1YOsxUi9F2OdgBv5QVDQKPDDP7tPnka9cR19n7Ms x3WvqnMuwHkVQmx0iTV1iNvzGk7nYOJfvg== X-Google-Smtp-Source: ABdhPJxC0Uty7ZeV42eb0fBswVHFjDiKbb5Ozap1sU/j0O9JsSTDSKNmo88XJ6/Xaco7nLh5EbtmHw== X-Received: by 2002:a17:902:ba98:: with SMTP id k24mr925032pls.44.1644391178659; Tue, 08 Feb 2022 23:19:38 -0800 (PST) Received: from localhost ([2401:fa00:1:10:a5cf:9a43:1c6d:824]) by smtp.gmail.com with UTF8SMTPSA id c7sm18094412pfp.164.2022.02.08.23.19.37 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 08 Feb 2022 23:19:38 -0800 (PST) From: Han-Lin Chen To: libcamera-devel@lists.libcamera.org Date: Wed, 9 Feb 2022 15:19:15 +0800 Message-Id: <20220209071917.559993-8-hanlinchen@chromium.org> X-Mailer: git-send-email 2.35.0.263.gb82422642f-goog In-Reply-To: <20220209071917.559993-1-hanlinchen@chromium.org> References: <20220209071917.559993-1-hanlinchen@chromium.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 7/9] libcamera: ipu3: Add helper class PipeConfigPreference X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- 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 + +#include + +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 &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 validVideoConfigs; + std::vector 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 + +#include + +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 videoPipeConfigs_; + std::vector stillPipeConfigs_; + + Size maxVideoResolution_; + Size maxStillResolution_; + + Size minVideoResolution_; + Size minStillResolution_; +}; + +} /* namespace libcamera */